Привет всем, пишу программу, и вот столкнулся с проблеммой! В программе есть ListView(LVS_REPORT), хочу сделать так что бы определённый SubItem можно было изменять с помощью ComboBox. Облазил весь инет, и пока ничего хорошего не нашел, если у кого-нибудь есть какие-нибудь соображения или идеи как это можно реализовать, буду рад выслушать! А вот пока куски кода которые я сам написал: Код (Text): ; Узнаёт куда нужно поместить combobox ; wid - индификатор окна, на главном окне ; iCol - индекс колонки, начинается он 0, то есть 0 1 2 3 ; iItem - идификатор строки .... proc SetLVComboboxPos wid,iCol,iItem local .rect RECT mov [.rect.bottom],10 lea eax,[.rect] invoke SendDlgItemMessage,[mainhwnd],[wid],LVM_GETITEMPOSITION,[iItem],eax invoke SendDlgItemMessage,[mainhwnd],[wid],LVM_GETCOLUMNWIDTH,[iCol],0 mov [.rect.right],eax dec [iCol] stdcall GetColummWidth,IDW_MAINLISTVIEW,[iCol] mov [.rect.left],eax invoke GetDlgItem,[mainhwnd],[wid] invoke GetDlgItem,eax,IDW_LVCOMBOBOX mov [wid],eax invoke SetWindowPos,[wid],HWND_TOP,[.rect.left],[.rect.top],[.rect.right],[.rect.bottom],SWP_SHOWWINDOW+SWP_DRAWFRAME ;+SWP_FRAMECHANGED invoke SendMessage,[wid],CB_SETITEMHEIGHT,-1,[.rect.bottom] ret endp ; Устанавливает новую функцию оброботки сообщений окна, ; и посылает WM_USER ; wid - индификатор окна, на главном окне ; new_proc - адресс новый функции ; wparam - это wparam в WM_USER сообщении proc SetWndProc,wid,new_proc,wparam invoke GetDlgItem,[mainhwnd],[wid] mov [wid],eax invoke SetWindowLong,eax,GWL_WNDPROC,[new_proc] push eax invoke SendMessage,[wid],WM_USER,[wparam],0 pop eax ret endp ; Функция обработки ListView, создаёт combobox proc ComboboxListview hwnd,wmsg,wparam,lparam local .buffer rb 255 invoke CallWindowProc,[listviewproc],[hwnd],[wmsg],[wparam],[lparam] push eax cmp [wmsg],WM_USER jne @F invoke CreateWindowEx,0,_combobox,0,WS_CHILD+CBS_DROPDOWN,1,1,50,10,[hwnd],IDW_LVCOMBOBOX,0,0 invoke GetStockObject,DEFAULT_GUI_FONT invoke SendDlgItemMessage,[hwnd],IDW_LVCOMBOBOX,WM_SETFONT,eax,0 @@: cmp [wmsg],WM_LBUTTONDOWN jne @F invoke GetDlgCtrlID,[hwnd] stdcall GetItemSel,eax stdcall SetLVComboboxPos,IDW_MAINLISTVIEW,4,eax @@: pop eax ret endp ; Узнаёт длину в пикселях от края до определённой метки(колонки) ; wid - индификатор окна, на главном окне ; iCol - индекс колонки, начинается он 0, то есть 0 1 2 3 proc GetColummWidth wid,iCol push ebx mov ebx,[iCol] and [iCol],0 @@: invoke SendDlgItemMessage,[mainhwnd],[wid],LVM_GETCOLUMNWIDTH,ebx,0 add [iCol],eax test ebx,ebx jz @F dec ebx jmp @B @@: mov eax,[iCol] pop ebx ret endp proc GetItemSel,wid local .top dd ? push ebx invoke SendDlgItemMessage,[mainhwnd],[wid],LVM_GETTOPINDEX,0,0 mov [.top],eax invoke SendDlgItemMessage,[mainhwnd],[wid],LVM_GETCOUNTPERPAGE,0,0 mov ebx,eax @@: cmp [.top],ebx je @F invoke SendDlgItemMessage,[mainhwnd],[wid],LVM_GETITEMSTATE,[.top],LVIS_SELECTED cmp eax,LVIS_SELECTED je @F inc [.top] jmp @B @@: mov eax,[.top] pop ebx ret endp
я когда-то мутился с субклассированием этого листвью - там не все так просто, особенно когда переключается фокус, когда пользователь начинает колонки двигать и т.п. - я правда сделал "напролом" - заблокировал то что мне мешало но возможно я шёл неправильным путём здесь создаются две колонки с простыми полями, или в правой можно выбирать файлы или папки кнопкой обзора. тебе просто класс поменять edit на combobox. посмотри - может чем-то поможет если посмотреть как оно в жизни - здесь shootest и shoolib. если вопрос почему где как - задавай
тоже задавался этим вопросом недавно, нашел только два исходника, один shoo, другой four-f (только там edit, но я думаю можно и combobox прикрутить) shoo, я давно хотел тебе задать вопрос про lv_sect, как насчет порта под си? наработка в аттаче, но там какой-то баг закрался найти никак не могу и ещё про небольшую оптимизацию, я думаю list_cmd и list_key можно объединить в одну процедуру и в _list_key можно немного код подоптимизировать, позже выложу свой вариант _list_key
а в чём баг проявляется? (я сейчас не смогу скомпилировать твой код - у меня стоит голый vc2003 без заголовочных файлов)
Хм, сейчас буду исходники изучать! Я вот кстате на интересную статью по этому поводу наткнулся http://support.microsoft.com/kb/816188. И вот что я ещё думаю: для изменения первого Item там есть встроенный Edit его дескрипрот можно узнать с помощью LVM_EDITLABEL, а я вот думаю а если насильственно поменять сам Class с Edit в ComboBox, а потом просто HitTest отлеживать в нужной области... как вам такая идея?
этот эдит создаётся в момент начала редактирования и уничтожается после его окончания - не представляю, как подменять ему класс.
Я вот тут кое что нашел, и опять же таки это библиотека, а я такого не хочу http://www.codeproject.com/listctrl/xlistctrl.asp
есть еще вариант - библиотека от Кетилы (я смотрел, но не пользовался). и исходник по-моему к ней есть.
или еще вариант - у меня используется кнопка для обзора - в ее обработчике можно вместо обзора вызывать списочек, который лепить прямо под эдитом (или над если низковато) - вот, хоть и не комбо, но почти
баг проявляется в следующем, см. аттач ps. я юзал ragrid от KetilO, тоже неплохая вещь, но не хватает вертикального текста для заголовков таблицы и текст внутри ячеек странно центруется
пока 100% не вкурил, но может ты быстрее ответишь: для нормальной работы нужно добавлять хотя бы одну пустую строку (см. функцию LvSectClear) ============ а, она же в инит тоже добавляется - уже забыл как оно работает ============ попробовал в PellesC - сейчас его снесу нафик
Делал как-то такую функциональность для Edit-а на C#, но всё равно вручную. Т.е. смысл везде один и тот же: высчитываем координаты и размеры куда нужно поместить контрол (любой) и создаем его там динамически как child ListView.
Avoidik заборол си (скомбинировал тут кое-что)... у меня нет такого эффекта как на твоей картинке правда, клавиши хождения по таблице не работают и 0-й столбец ненулевой ширины...
если щелкать везде и всюду, то эффект все равно наблюдается уже пару раз с нуля переписывал, то одно не работает, то другое. у тебя в коде используется конструкция: Код (Text): mov eax,[ebx+LV_SECT.list_c] mov eax,[ebx+LV_SECT.var_p + eax*8 - 8] pop ebx leave push dword ptr esp mov dword ptr esp + 4,eax jmp [CallWindowProc] правильно ли я её понял? Код (Text): if(hData->list_c != 1) return CallWindowProc(hData->val_p,hWnd,wMsg,wParam,lParam); else return CallWindowProc(hData->var_p,hWnd,wMsg,wParam,lParam);
воспроизвёл - этот эффект появляется если щёлкнуть на несуществующей строке, т.е. ниже последней строки. насчет CallWindowProc вроде все правильно. проверь наличия аналога вот этих строк: Код (Text): invoke SendMessage,[hWnd],LVM_SUBITEMHITTEST,0,esp add esp,3*4 pop eax pop edx cmp eax,[ebx + LV_SECT.list_t] ja .done LV_SECT.list_t - количество строк в списке. если полученное больше - щелчок игнорируется.
вот оно: Код (Text): ind=SendMessage(hWnd,LVM_SUBITEMHITTEST,NULL,(LPARAM)&hit); if(ind > hData->list_t) { hData->list_r=hit.iItem; hData->list_c=hit.iSubItem; } было: if(ind <= hData->list_t) ========== короче, быстро не получилось, но собака зарыта где-то здесь