Форум: "WinAPI";
Текущий архив: 2003.06.19;
Скачать: [xml.tar.bz2];
ВнизПомогите с ListView и LVN_ENDLABELEDIT - нет моих больше сил! Найти похожие ветки
← →
DVM (2003-04-19 23:55) [0]Есть такая проблема: никак не могу заставить ListView сохранять результат редактирования подписи под значком.
Собственно упрощенный код такой:
program ListViewDemo;
uses windows, messages, Commctrl;
type
TMyItem = packed record
Name : PChar;
Path : PChar;
Param : PChar;
PathToIcon : PChar;
end;
PMyItem = ^TMyItem;
var
wc : TWndClassEx;
hMainWnd : HWND;
Mesg : TMsg;
hListView:hWnd;
hEdit, HIcon, himlLarge:THandle;
InitCtrls: TInitCommonControlsEx;
nmhdr:PNMHdr;
lpLvdi:PLVDispInfo;
i:integer;
TempItem:PMyItem;
Items : array [0..2] of TMyItem;
lvi : TLVItemA;
function WindowProc(wnd:HWND; Msg : Integer; Wparam:Wparam; Lparam:Lparam):Lresult; stdcall;
begin
case msg of
WM_NOTIFY:
begin
nmhdr:=PNMHdr(lParam);
lpLvdi:=PLVDispInfo(nmhdr);
TempItem:=PMyItem(lpLvdi.item.lParam);
case nmhdr.code of
LVN_GETDISPINFO:
begin
if (lpLvdi.item.mask and LVIF_TEXT)=1 then
begin
case lpLvdi.item.iSubItem of
0: lpLvdi.item.pszText := TempItem^.Name;
end;
end;
end;
LVN_BEGINLABELEDIT:
begin
result:=0;
end;
LVN_ENDLABELEDIT:
if (lpLvdi.item.iItem<>-1) and (lpLvdi.item.pszText<>nil) then
lstrcpy(TempItem.Name,lpLvdi.item.pszText);
end;
end;
wm_destroy :
Begin
postquitmessage(0);
exit;
Result:=0;
End;
else Result:=DefWindowProc(wnd,msg,wparam,lparam);
end;
End;
//Продолжение следует...
← →
DVM (2003-04-20 00:00) [1]//...продолжение
begin
wc.cbSize:=sizeof(wc);
wc.style:=cs_hredraw or cs_vredraw;
wc.lpfnWndProc:=@WindowProc;
wc.cbClsExtra:=0;
wc.cbWndExtra:=0;
wc.hInstance:=HInstance;
wc.hIcon:=LoadIcon(0,idi_application);
wc.hCursor:=LoadCursor(0,idc_arrow);
wc.hbrBackground:=COLOR_BTNFACE+1;
wc.lpszMenuName:=nil;
wc.lpszClassName:="ListViewDemo";
if RegisterClassEx (wc) = 0 then exit;
hMainWnd:=CreateWindowEx(0, "ListViewDemo", "ListViewDemo", ws_overlappedwindow,
1, 1, 400, 300, 0, 0, Hinstance, nil);
if hMainWnd = 0 then exit;
ShowWindow(hMainWnd,CmdShow); UpdateWindow(hMainWnd);
InitCtrls.dwICC := ICC_LISTVIEW_CLASSES;
InitCtrls.dwSize := sizeof(TInitCommonControlsEx);
InitCommonControlsEx(InitCtrls);
hListView:=CreateWindowEx(LVS_EX_HEADERDRAGDROP,
WC_LISTVIEW,
"",
LVS_SINGLESEL or lvs_icon or ws_child or ws_visible
or ws_border or LVS_SHOWSELALWAYS or LVS_EDITLABELS,
0,0,300,250,
hMainWnd,
0,Hinstance,nil);
himlLarge := ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), ILC_COLOR32 or ILC_MASK, 1, 1);
ListView_DeleteAllItems(hListView);
HIcon:= LOADICON(0,IDI_EXCLAMATION);
ImageList_AddIcon(himlLarge, HIcon);
ListView_SetImageList(hListView, himlLarge, LVSIL_NORMAL );
Items[0].Name:="aaa";
Items[1].Name:="bbb";
Items[2].Name:="ccc";
lvi.mask := LVIF_TEXT or LVIF_IMAGE or LVIF_PARAM;
lvi.pszText := LPSTR_TEXTCALLBACK;
for i:=0 to 2 do
begin
lvi.iItem := i;
lvi.iSubItem := 0;
lvi.cchTextMax := 40;
lvi.lParam := longint(@Items[i]);
lvi.iImage := 0;
ListView_InsertItem(hListView, lvi);
end;
While GetMessage(Mesg,0,0,0) do
begin
TranslateMessage(Mesg);
DispatchMessage(Mesg);
end;
end.
← →
DVM (2003-04-20 00:03) [2]Проблема в том, что вот здесь:
LVN_ENDLABELEDIT:
if (lpLvdi.item.iItem<>-1) and (lpLvdi.item.pszText<>nil)
then lstrcpy(TempItem.Name,lpLvdi.item.pszText);
lpLvdi.item.pszText все время пустой. Что за дела???
← →
Suntechnic (2003-04-20 06:04) [3]>DVM ©
Он и должен быть пустым, если ты Cancel жмёшь после редактирования. А в остальном всё прекрасно работает (в смысле, что не пустой).
← →
Suntechnic (2003-04-20 06:10) [4]Да... если тебя всё-таки интересует почему подпись не обновляется, то ты кое-что забыл. А именно вызвать что-то типа вот этого
ListView_SetItemText(nmhdr.hwndFrom, lpLvdi.item.iItem, lpLvdi.item.iSubItem, lpLvdi.item.pszText);
после lstrcpy.
Потому как
When label editing is canceled or completed, a list view control sends its parent window an LVN_ENDLABELEDIT notification message. The parent window is responsible for updating the item label if it keeps the new label.
← →
DVM (2003-04-20 11:00) [5]
> Он и должен быть пустым, если ты Cancel жмёшь после редактирования.
> А в остальном всё прекрасно работает (в смысле, что не пустой).
У Вас вышеприведенный код работает? Я проверял сразу после после окончания редактирования значение переменной lpLvdi.item.pszText - там пусто. Соответственно надпись под значком исчезает, т.к. в элемент массива Items[], откуда список берет подписи к значкам ничего не попадает.
> Да... если тебя всё-таки интересует почему подпись не обновляется,
> то ты кое-что забыл. А именно вызвать что-то типа вот этого
>
> ListView_SetItemText(nmhdr.hwndFrom, lpLvdi.item.iItem,
> lpLvdi.item.iSubItem, lpLvdi.item.pszText); после lstrcpy.
С этой строкой все конечно работает.
А это разве надо? Ведь в моем случае список САМ должен обновится, т.к. он использует LVN_GETDISPINFO и при первой же перерисовке он значения подписей получет из элементов массива, связанных со значками.
← →
DVM (2003-04-20 11:12) [6]Мне надо положить новое значение подписи в массив элементов, связанный со значками списка, так как в последствии название к значку будет браться оттуда.
Когда я пишу так все работает:
LVN_ENDLABELEDIT:
if (lpLvdi.item.iItem<>-1) and (lpLvdi.item.pszText<>nil) then
begin
TempItem.Name:=pchar("*****");
end;
Подпись под значком обновляется сама и становится "*****"
Но вот такая запись ни к чему не приводит:
LVN_ENDLABELEDIT:
if (lpLvdi.item.iItem<>-1) and (lpLvdi.item.pszText<>nil) then
begin
TempItem.Name:=lpLvdi.item.pszText;
end;
← →
Suntechnic (2003-04-20 15:25) [7]>DVM ©
Ты вон о чём оказывается. Надо ж об этом с самого начала и писать, а том не лично облом сидеть и разбираться в локиге программы. Теперь по сути...
Конечно же проблема не в lpLvdi.item.pszText, там всегда содержится строка и никакой это не ноль. Тут проблема в другом.
LVN_ENDLABELEDIT:
if (lpLvdi.item.iItem<>-1) and (lpLvdi.item.pszText<>nil)
then lstrcpy(TempItem.Name,lpLvdi.item.pszText);
А память кто под строку будет выделять в вышеуказанной строке? lstrcpy всего лишь копирует в вышеуказанное место, в выделением памяти она не занимается. TempItem.Name:=lpLvdi.item.pszText - так тожу писать нельзя ибо мы всего-лишь присвоили указатель на строку, а выделением строки тоже не занимались. Это обычные операции с null-terminated строкой, которые так хорошо известны любому с-шнику. Я вообще-то по Delphi не крупный специалист, поэтому как именно решить проблему сказать точно не могу, но направление мысли дать могу:
LVN_ENDLABELEDIT:
if (lpLvdi.item.iItem<>-1) and (lpLvdi.item.pszText<>nil) then
begin
TempItem.Name:= StrAlloc(lstrlen(lpLvdi.item.pszText) + 1);
lstrcpy(TempItem.Name,lpLvdi.item.pszText);
end;
Вот если так напишешь, то это работать будет, только тут есть один нюанс. На лицо memory leak так как память под строку мы выделили, а DisposeAlloc так и не вызвали. Вообще подумай, где под строку выделять память и где её освобождать.
← →
DVM (2003-04-20 20:04) [8]Спасибо, я вообще то и сам в том же направлении копал. Указатели и нуль-теминэйт строки - это то, в чем я плохо пока разбираюсь.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2003.06.19;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.276 c