TListView обнаруживает ESC или неизменное редактирование - PullRequest
0 голосов
/ 27 мая 2018

Я пытаюсь создать подкласс WindowProc из TListView для обнаружения нажатия клавиши ESC после редактирования заголовка TListView (если пользователь отменяет редактирование).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";
}

Ответы [ 2 ]

0 голосов
/ 30 июня 2018

На случай, если кто-нибудь еще найдет решение в Delphi, я только что перевел код Kerem D:

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;

У меня это работает в Delphi 6 - 10.2 (используется в GExperts)

0 голосов
/ 28 мая 2018

В C ++ значение LVN_ENDLABELEDEDIT зависит от TCHAR_Mapping проекта , который можно изменить в настройках проекта с помощью элемента конфигурации "_TCHAR maps to".По умолчанию _TCHAR установлено в wchar_t в C ++ Builder 2009 и более поздних версиях, если только вы не перенесете проект из более ранней версии, в этом случае вместо него будет char по умолчанию.

LVN_ENDLABELEDIT - это макрос, который отображается на LVN_ENDLABELEDITA (4294967190), когда _TCHAR равен char, и на LVN_ENDLABELEDITW (4294967120), когда _TCHAR равен wchar_t.

Проверка обеих константLVN_ENDLABELEDEDITA и LVN_ENDLABELEDEDITW, как это сделано в исходном коде Delphi, должны быть в порядке.

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