Reputation: 3753
I am trying to subclass the WindowProc
of TListView
to detect ESC key press after editing TListView
caption (if user cancels editing). ListViewWndProc is getting called clearly, but the code parameter which is supposed to detect that never gets LVN_ENDLABELEDIT value. Why the commented part never gets called? I cannot see the error, it should be happening.
TWndMethod OldWndProc;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
OldWndProc = ListView1->WindowProc;
ListView1->WindowProc = ListViewWndProc;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListViewWndProc(TMessage &Message)
{
if (Message.Msg == CN_NOTIFY)
{
LPNMHDR pnmh = reinterpret_cast<LPNMHDR>(Message.LParam);
if (pnmh->code == LVN_ENDLABELEDIT) // UPDATE: if LVN_ENDLABELEDIT is replaced with 4294967120 it works
{
// !!! THE FOLLOWING NEVER HAPPENS !!!
// UPDATE: Looks like LVN_ENDLABELEDIT is incorrectly defined in C++ Builder 2010
// if LVN_ENDLABELEDIT is replaced with 4294967120 the code works
LV_DISPINFO *pdi = reinterpret_cast<LV_DISPINFO*>(Message.LParam);
if (pdi->item.pszText == NULL)
{
Edit1->Text = "Cancelled";
return;
}
}
}
OldWndProc(Message);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListView1Editing(TObject *Sender, TListItem *Item, bool &AllowEdit)
{
Edit1->Text = "Editing";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListView1Edited(TObject *Sender, TListItem *Item, UnicodeString &S)
{
Edit1->Text = "Done";
}
Upvotes: 2
Views: 334
Reputation: 11252
In case anybody else gets here looking for a solution in Delphi, I have just translated Kerem D's code:
constructor TForm1.Create(_Owner: TComponent);
begin
inherited;
OldWndProc = ListView1.WindowProc;
ListView1.WindowProc = ListViewWndProc;
end;
procedure TForm1.ListViewWndProc(var _Message: TMessage);
var
LvDispInfo: PLVDispInfo; // declared in CommCtrl
Code: Integer;
begin
if _Message.Msg = CN_NOTIFY then begin
Code := PNMHdr(_Message.lParam).Code;
if (Code = LVN_ENDLABELEDITA) or (Code = LVN_ENDLABELEDITW) then begin
LvDispInfo := PLVDispInfo(_Message.lParam);
if LvDispInfo.Item.pszText = nil then begin
Edit1.Text := 'Cancelled';
Exit; //==>
end;
end;
end;
OldWndProc(_Message);
end;
It works for me in Delphi 6 to 10.2 (used in GExperts)
Upvotes: 2
Reputation: 449
In C++, the value of LVN_ENDLABELEDEDIT
depends on the project's TCHAR_Mapping, which can be changed in the Project Settings via the "_TCHAR maps to"
configuration item. By default, _TCHAR
is set to wchar_t
in C++Builder 2009 and later, unless you migrate a project from an earlier version, in which case it is char
by default instead.
LVN_ENDLABELEDIT
is a macro that maps to LVN_ENDLABELEDITA
(4294967190) when _TCHAR
is char
, and to LVN_ENDLABELEDITW
(4294967120) when _TCHAR
is wchar_t
.
Checking for both constants LVN_ENDLABELEDEDITA
and LVN_ENDLABELEDEDITW
, like it is done in the Delphi source code, should be OK.
void __fastcall TForm1::ListViewWndProc(TMessage &Message)
{
if (Message.Msg == CN_NOTIFY)
{
LPNMHDR pnmh = reinterpret_cast<LPNMHDR>(Message.LParam);
if ((pnmh->code == LVN_ENDLABELEDITA) || (pnmh->code == LVN_ENDLABELEDITW))
{
LV_DISPINFO *pdi = reinterpret_cast<LV_DISPINFO*>(Message.LParam);
if (pdi->item.pszText == NULL)
{
Edit1->Text = "Cancelled";
return;
}
}
}
OldWndProc(Message);
}
Upvotes: 3