Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.06.19;
Скачать: CL | DM;

Вниз

Помогите с 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 вся ветка

Текущий архив: 2003.06.19;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.02 c
3-60082
Dimaz-z
2003-05-28 15:16
2003.06.19
Какой запрос надо поставить, чтобы сортировать базу по алфавиту?


11-60097
Kirill
2002-09-10 11:01
2003.06.19
Печать в KOL


7-60441
DV
2003-04-15 16:51
2003.06.19
Еще раз про ком-порт


1-60244
Катерина
2003-06-05 13:59
2003.06.19
Циклическая перестановка байтов в integer


3-60085
denary
2003-05-29 01:38
2003.06.19
Как сделать частичную замену в строке?