我正在尝试对WindowProcTListView进行子类化,以在编辑TListView标题后(如果用户取消编辑)来检测ESC键的按下。 ListViewWndProc被清楚地调用,但是应该检测到的代码参数永远不会获得LVN_ENDLABELEDIT值。为什么注释部分永远不会被调用?我看不到错误,应该正在发生。

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";
}

最佳答案

在C++中,LVN_ENDLABELEDEDIT的值取决于项目的TCHAR_Mapping,可以通过"_TCHAR maps to"配置项在“项目设置”中进行更改。默认情况下,除非从早期版本迁移项目,否则_TCHAR在C++ Builder 2009和更高版本中设置为wchar_t,在这种情况下,默认情况下为char
LVN_ENDLABELEDIT是一个宏,当LVN_ENDLABELEDITA_TCHAR时,它映射到char(4294967190);当LVN_ENDLABELEDITW_TCHAR时,它映射到wchar_t(4294967120)。

像在Delphi源代码中一样检查常量LVN_ENDLABELEDEDITALVN_ENDLABELEDEDITW,应该可以。

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);
}

10-06 11:00