ComboBox в ListView(LVS_REPORT)

Тема в разделе "WASM.WIN32", создана пользователем Songoku, 16 фев 2007.

  1. Songoku

    Songoku Эдгар

    Публикаций:
    0
    Регистрация:
    1 мар 2003
    Сообщения:
    68
    Адрес:
    Belarus
    Привет всем,
    пишу программу, и вот столкнулся с проблеммой!
    В программе есть ListView(LVS_REPORT), хочу сделать так что бы определённый SubItem можно было изменять с помощью ComboBox. Облазил весь инет, и пока ничего хорошего не нашел, если у кого-нибудь есть какие-нибудь соображения или идеи как это можно реализовать, буду рад выслушать!
    А вот пока куски кода которые я сам написал:
    Код (Text):
    1. ; Узнаёт куда нужно поместить combobox
    2. ; wid - индификатор окна, на главном окне
    3. ; iCol - индекс колонки, начинается он 0, то есть 0 1 2 3
    4. ; iItem - идификатор строки ....
    5. proc SetLVComboboxPos wid,iCol,iItem
    6. local   .rect RECT
    7. mov     [.rect.bottom],10
    8. lea     eax,[.rect]
    9. invoke  SendDlgItemMessage,[mainhwnd],[wid],LVM_GETITEMPOSITION,[iItem],eax
    10. invoke  SendDlgItemMessage,[mainhwnd],[wid],LVM_GETCOLUMNWIDTH,[iCol],0
    11. mov     [.rect.right],eax
    12. dec     [iCol]
    13. stdcall GetColummWidth,IDW_MAINLISTVIEW,[iCol]
    14. mov     [.rect.left],eax
    15. invoke  GetDlgItem,[mainhwnd],[wid]
    16. invoke  GetDlgItem,eax,IDW_LVCOMBOBOX
    17. mov     [wid],eax
    18. invoke  SetWindowPos,[wid],HWND_TOP,[.rect.left],[.rect.top],[.rect.right],[.rect.bottom],SWP_SHOWWINDOW+SWP_DRAWFRAME  ;+SWP_FRAMECHANGED
    19. invoke  SendMessage,[wid],CB_SETITEMHEIGHT,-1,[.rect.bottom]
    20. ret
    21. endp                              
    22.  
    23. ; Устанавливает новую функцию оброботки сообщений окна,
    24. ; и посылает WM_USER
    25. ; wid - индификатор окна, на главном окне
    26. ; new_proc - адресс новый функции
    27. ; wparam - это wparam в WM_USER сообщении
    28. proc  SetWndProc,wid,new_proc,wparam
    29. invoke  GetDlgItem,[mainhwnd],[wid]
    30. mov     [wid],eax
    31. invoke  SetWindowLong,eax,GWL_WNDPROC,[new_proc]
    32. push    eax
    33. invoke  SendMessage,[wid],WM_USER,[wparam],0
    34. pop     eax
    35. ret
    36. endp
    37.  
    38. ; Функция обработки ListView, создаёт combobox
    39.  
    40. proc  ComboboxListview hwnd,wmsg,wparam,lparam
    41. local   .buffer rb 255
    42.  
    43. invoke  CallWindowProc,[listviewproc],[hwnd],[wmsg],[wparam],[lparam]
    44.  
    45. push    eax
    46. cmp     [wmsg],WM_USER
    47. jne      @F
    48. invoke  CreateWindowEx,0,_combobox,0,WS_CHILD+CBS_DROPDOWN,1,1,50,10,[hwnd],IDW_LVCOMBOBOX,0,0
    49. invoke  GetStockObject,DEFAULT_GUI_FONT
    50. invoke  SendDlgItemMessage,[hwnd],IDW_LVCOMBOBOX,WM_SETFONT,eax,0
    51. @@:
    52. cmp     [wmsg],WM_LBUTTONDOWN
    53. jne     @F
    54. invoke  GetDlgCtrlID,[hwnd]
    55. stdcall GetItemSel,eax
    56. stdcall SetLVComboboxPos,IDW_MAINLISTVIEW,4,eax
    57. @@:
    58.  
    59. pop     eax
    60.  
    61.  
    62.  
    63. ret
    64. endp                    
    65.  
    66.  
    67. ; Узнаёт длину в пикселях от края до определённой метки(колонки)
    68. ; wid - индификатор окна, на главном окне
    69. ; iCol - индекс колонки, начинается он 0, то есть 0 1 2 3
    70. proc GetColummWidth wid,iCol
    71. push    ebx
    72. mov     ebx,[iCol]
    73. and     [iCol],0
    74. @@:
    75. invoke  SendDlgItemMessage,[mainhwnd],[wid],LVM_GETCOLUMNWIDTH,ebx,0
    76. add     [iCol],eax
    77. test    ebx,ebx
    78. jz      @F
    79. dec     ebx
    80. jmp     @B
    81. @@:
    82. mov     eax,[iCol]
    83. pop     ebx
    84. ret
    85. endp        
    86.  
    87.  
    88.  
    89. proc GetItemSel,wid
    90. local   .top dd ?
    91. push    ebx
    92. invoke  SendDlgItemMessage,[mainhwnd],[wid],LVM_GETTOPINDEX,0,0
    93. mov     [.top],eax
    94. invoke  SendDlgItemMessage,[mainhwnd],[wid],LVM_GETCOUNTPERPAGE,0,0
    95. mov     ebx,eax
    96. @@:
    97. cmp     [.top],ebx
    98. je      @F
    99. invoke  SendDlgItemMessage,[mainhwnd],[wid],LVM_GETITEMSTATE,[.top],LVIS_SELECTED
    100. cmp     eax,LVIS_SELECTED
    101. je      @F
    102. inc     [.top]
    103. jmp     @B
    104. @@:
    105. mov     eax,[.top]
    106. pop     ebx
    107. ret
    108. endp
     
  2. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    я когда-то мутился с субклассированием этого листвью - там не все так просто, особенно когда переключается фокус, когда пользователь начинает колонки двигать и т.п. - я правда сделал "напролом" - заблокировал то что мне мешало :) но возможно я шёл неправильным путём :)
    здесь создаются две колонки с простыми полями, или в правой можно выбирать файлы или папки кнопкой обзора. тебе просто класс поменять edit на combobox.
    посмотри - может чем-то поможет :)
    если посмотреть как оно в жизни - здесь shootest и shoolib.

    если вопрос почему где как - задавай
     
  3. Avoidik

    Avoidik New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2004
    Сообщения:
    288
    Адрес:
    Russia
    тоже задавался этим вопросом недавно, нашел только два исходника, один shoo, другой four-f (только там edit, но я думаю можно и combobox прикрутить)

    shoo, я давно хотел тебе задать вопрос про lv_sect, как насчет порта под си? наработка в аттаче, но там какой-то баг закрался найти никак не могу :dntknw: и ещё про небольшую оптимизацию, я думаю list_cmd и list_key можно объединить в одну процедуру и в _list_key можно немного код подоптимизировать, позже выложу свой вариант _list_key
     
  4. Avoidik

    Avoidik New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2004
    Сообщения:
    288
    Адрес:
    Russia
    аттач
     
  5. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    а в чём баг проявляется? (я сейчас не смогу скомпилировать твой код - у меня стоит голый vc2003 без заголовочных файлов)
     
  6. Songoku

    Songoku Эдгар

    Публикаций:
    0
    Регистрация:
    1 мар 2003
    Сообщения:
    68
    Адрес:
    Belarus
    Хм, сейчас буду исходники изучать!
    Я вот кстате на интересную статью по этому поводу наткнулся http://support.microsoft.com/kb/816188.
    И вот что я ещё думаю: для изменения первого Item там есть встроенный Edit его дескрипрот можно узнать с помощью LVM_EDITLABEL, а я вот думаю а если насильственно поменять сам Class с Edit в ComboBox, а потом просто HitTest отлеживать в нужной области... как вам такая идея?
     
  7. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    этот эдит создаётся в момент начала редактирования и уничтожается после его окончания - не представляю, как подменять ему класс.
     
  8. Songoku

    Songoku Эдгар

    Публикаций:
    0
    Регистрация:
    1 мар 2003
    Сообщения:
    68
    Адрес:
    Belarus
    Я пришел к этому же выводу :dntknw:
     
  9. Songoku

    Songoku Эдгар

    Публикаций:
    0
    Регистрация:
    1 мар 2003
    Сообщения:
    68
    Адрес:
    Belarus
  10. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    есть еще вариант - библиотека от Кетилы (я смотрел, но не пользовался). и исходник по-моему к ней есть.
     
  11. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    или еще вариант - у меня используется кнопка для обзора - в ее обработчике можно вместо обзора вызывать списочек, который лепить прямо под эдитом (или над если низковато) - вот, хоть и не комбо, но почти :)
     
  12. Songoku

    Songoku Эдгар

    Публикаций:
    0
    Регистрация:
    1 мар 2003
    Сообщения:
    68
    Адрес:
    Belarus
    Вот что у меня пока получилось...
     
  13. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    нормально, только высоту для комбобокса сделай с учётом списка (100 например)
     
  14. Avoidik

    Avoidik New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2004
    Сообщения:
    288
    Адрес:
    Russia
    баг проявляется в следующем, см. аттач

    ps. я юзал ragrid от KetilO, тоже неплохая вещь, но не хватает вертикального текста для заголовков таблицы и текст внутри ячеек странно центруется
     
  15. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    пока 100% не вкурил, но может ты быстрее ответишь: для нормальной работы нужно добавлять хотя бы одну пустую строку (см. функцию LvSectClear)
    ============
    а, она же в инит тоже добавляется - уже забыл как оно работает :)
    ============
    попробовал в PellesC - сейчас его снесу нафик :)
     
  16. Gelios

    Gelios New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2006
    Сообщения:
    16
    Делал как-то такую функциональность для Edit-а на C#, но всё равно вручную.
    Т.е. смысл везде один и тот же: высчитываем координаты и размеры куда нужно поместить контрол (любой) и создаем его там динамически как child ListView.
     
  17. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    Avoidik
    заборол си (скомбинировал тут кое-что)...
    у меня нет такого эффекта как на твоей картинке
    правда, клавиши хождения по таблице не работают и 0-й столбец ненулевой ширины...
     
  18. Avoidik

    Avoidik New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2004
    Сообщения:
    288
    Адрес:
    Russia
    если щелкать везде и всюду, то эффект все равно наблюдается :) уже пару раз с нуля переписывал, то одно не работает, то другое. у тебя в коде используется конструкция:

    Код (Text):
    1.     mov     eax,[ebx+LV_SECT.list_c]
    2.     mov     eax,[ebx+LV_SECT.var_p + eax*8 - 8]
    3.     pop ebx
    4.     leave
    5.     push    dword ptr esp
    6.     mov dword ptr esp + 4,eax
    7.     jmp [CallWindowProc]
    правильно ли я её понял?

    Код (Text):
    1.     if(hData->list_c != 1)
    2.         return CallWindowProc(hData->val_p,hWnd,wMsg,wParam,lParam);
    3.     else
    4.         return CallWindowProc(hData->var_p,hWnd,wMsg,wParam,lParam);
     
  19. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    воспроизвёл - этот эффект появляется если щёлкнуть на несуществующей строке, т.е. ниже последней строки. насчет CallWindowProc вроде все правильно.

    проверь наличия аналога вот этих строк:
    Код (Text):
    1.     invoke SendMessage,[hWnd],LVM_SUBITEMHITTEST,0,esp
    2.     add esp,3*4
    3.     pop eax
    4.     pop edx
    5.     cmp eax,[ebx + LV_SECT.list_t]
    6.     ja  .done
    LV_SECT.list_t - количество строк в списке. если полученное больше - щелчок игнорируется.
     
  20. shoo

    shoo New Member

    Публикаций:
    0
    Регистрация:
    17 июл 2003
    Сообщения:
    1.537
    Адрес:
    Ukraine
    вот оно:
    Код (Text):
    1. ind=SendMessage(hWnd,LVM_SUBITEMHITTEST,NULL,(LPARAM)&hit);
    2.             if(ind > hData->list_t)
    3.             {
    4.                 hData->list_r=hit.iItem;
    5.                 hData->list_c=hit.iSubItem;
    6.             }
    было: if(ind <= hData->list_t)
    ==========
    короче, быстро не получилось, но собака зарыта где-то здесь