Odczytanie stringa z message LB_ADDSTRING.

0

No właśnie jak to zrobić. Tak wiem, to mega lamerskie pytanie, ale już późna pora, a ja googlując za przykładami nie znalazłem I tak czasami bywa, że nie możemy wpaśc na najprostsze rozwiązania. I do tego chyba za słabo ogarniam Pointery. Bo według MSDN przy message LB_ADDSTRING LParam ma być wksźnikiem na null terminated string czyli może to byc dla Delphi PChar. Tak samo jak w WM_COPYDATA - to LParam jest wskaźnikiem na strukture CopyDataStruct czyli dla Delphi typ zwie się TCopyDataStruct i poniższy przykładowy kod działa ok:

function DlgProc(HwndDlg : HWND; Msg : UINT; wParam : wParam; lParam : lParam) : BOOL; stdcall;
var
  P0 : ^TCopyDataStruct;
begin
  result := false;
  case msg of
    WM_INITDIALOG :
      begin
        HDialog := HwndDlg;
        SetWindowLong(HwndDlg, GWL_EXSTYLE, WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW);
      end;
    WM_CLOSE :
      begin
        HDialog := 0;
        EndDialog(HwndDlg, 1);
        Result := True;
      end;
    WM_COPYDATA :
      begin
        P0 := Pointer(lParam);
        if P0.dwData = 4758 then
        begin
          TTSCommand(GlobalPlugident, CmdSpeak, PChar(P0^.lpData));
          repeat
            Sleep(100);
          until TTSCommand(GlobalPlugident, CmdIsSpeaking, nil) = 0;
        end;
      end;
  end;
end;

Jednak jak zrobić aby funkcja SMsg pokazująca string pokazała mi dodawany do ListBoxa element tekstowy czyli coś jak robimy dla TListBox Items.Add ale tutaj oczywiście w WinAPI? Bo kombinowałem już na wiele sposób różnie rzutując i definiując typy aby tylko się skompilowało, również bez GetMem, ale albo treśc w MessageBoxie była pusta albo były jakieś krzaki albo program się wysypywał. No to idę spać i z góry dziękuję za wszelkie podpowiedzi. I kajam się, że nie umiem sobie ogarnąc może tak banalnej sprawy albo wygooglować konkretnego przykładu w Delphi, bo wszędzie jest wysyłąnie komunikatu aby dodać nowy string, a nie ma sposobu jak pod Delphi go odebrać i przetworzyć.

function NewSendMessageA(AHWnd : HWND; UMsg : UINT;
  AWParam : WPARAM; ALParam : LPARAM) : BOOL; stdcall;
var
  P0 : ^PChar;
begin
  if UMsg = LB_ADDSTRING then
  begin
    if (GetControlClassName(AHWnd) = MyListBox_Class_Name) then
    begin
      GetMem(P0, 100);
      P0^ := PChar(ALParam);
      SMsg(P0^);
    end;
  end;
  Result := OriginalSendMessageA(AHWnd, UMsg, AWParam, ALParam);
end;

Chyba, że jedyną metodą nieco bardziej jeszcze lamerską niż moje pytanie jest postąpienie na około i zerowanie jakiegoś licznika później co komunikat zwiększania go o jeden i odczytywania innym funkcjami z komunikatmi do odczytu stringów takimi jak LB_GETTEXTLEN i LB_GETTEXT, ale chyba da się prościej. Tylko właśnie nie umiem ogarnąc samodzielnie jak i liczę na Was.

1

Nie wiem czy dobrze zrozumiałem chcesz obsługiwać komunikat LB_ADDSTRING i pokazać string jaki zawiera?
Jeżeli tak to nie chciało mi się rzeźbić w WinApi tylko pod VCL ale w WinApi też powinno działać bo niby dlaczego nie:

procedure TForm1.ListBoxWndProc(var Msg: TMessage);
begin
  if (Msg.Msg = LB_ADDSTRING)then
    ShowMessage(PAnsiChar(Msg.LParam));
  Msg.Result:= CallWindowProc(pOldListBoxProc, ListBox1.Handle, Msg.Msg,
      Msg.wParam, Msg.lParam);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SendMessage(ListBox1.Handle, LB_ADDSTRING, 0, LParam(PAnsiChar('dupa')));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  pNewListBoxProc:= Classes.MakeObjectInstance(ListBoxWndProc);
  pOldListBoxProc:= Pointer(SetWindowLong(ListBox1.Handle, GWL_WNDPROC,
    Integer(pNewListBoxProc)));
end;
0

Dziękuję za odpowiedź, ale co ciekawe taki sposób oczywiście działa pod VCL, ale w przypadku założonego Hooka zwraca pusty tekst. Może dlatego, że kombinuje z Hookiem na kontrolkę TMyListBox w Total Commanderze, która najprawdopodobniej była pisana od zera przez autora, ale chyba musi dziedziczyć z ListBoxa przynajmniej tego z WinAPI, ponieważ inaczej chyba nie dochodzil by do niej taki komunikat. No coż, poradziłem sobie trochę na około, w taki sposób jak napisałem na końcu poprzedniego posta. Jednak jak ktoś ma jeszcze jakiś pomysł co może być nie tak, że zwraca mi pusty łańcuch to piszcie tutaj.

0

A to trzeba było od razu mówić że kombinujesz z odczytaniem komunikatu wysyłanego do innego programu. Jak później będę miał czas to się pobawię i jak się oda to napiszę.

0

Już ogarnąłem temat nieco inaczej - przez zastosowanie Hooka. Wiem, mało elegancko, ale póki co tylko ta metoda działa jak powinna. Może jak znajdę więcej czasu to wykombinuje inny, bardziej elegancki sposób. Oczywiście Twój kod @kAzek działa również pod WinAPI. Po prostu podczepienie się Hookiem na funkcję API lub przez SetWindowLong z użyciem GWL_WNDPROC dla funkcji obsługi komunikatów, nawet pod na 10000% prawidłowy uchwyt kontrolki dziedziczącej (za pewne po TListBox) w przypadku Total Commandera (a może i innych programów, chociaż sprawdzałem dla własnego programu w WinAPI, no i tam nie było takich problemów) sprawia, że nie uzyskamy po komunikacie LB_ADDSTRING w PChar(ALParam) ani prawidłowego stringa z dodanym Itemem, ani nie sprawdzimy go przez wysyłanie prawidłowej funkcji SendMessage z komunikatem LB_GETTEXT. Po prostu zostaną zwrócone jakieś "śmieci". Bez podczepiania się pod funkcję obsługi komunikatów w przypadku Total Commandera wszystko będzie ok. Może sprecyzyuje z czym tak kombinuję. Póki co na bazie Hooka mam działający pod Windowsami XP i nowszymi plugin, który pokaże w dodanej, własnej kolumnie numer porządkowy pozycji. Niestety pluginy do obśługi contentu i własnych kolumn dla TotalCmd (czyli te o rozszerzeniach *.wdx) nie obsługują funkcji reagujących na takie zdarzenia jak zmienianie sortowania. A w kolumnie co zrozumiałe dla optymnalizacji i szybkości działania zostaną wyświetlone jedynie dane dotyczące widocznych aktualnie plików w danym panelu. Później dane te zostaną zapamiętane i można reagować tylko na ich odświeżenie przez na przykład kombinację Ctrl+R. Poza tym przy wczytywaniu dwóch ListBoxów na raz przy ich pierwszym tworzeniu elementy dodawane są na przemian - raz w lewym, a raz w prwym, Także to co mamy zwracane w Pointerze FieldValue, w funkcji ContentGetValue zostało zaprojektowane w taki sposób, aby dotyczyło tylko pliku widocznego w zmiennej FileName. Trzeba albo kombinowac z Hookiem na 'SendMessageA co nie działa pod Windowsami 98 (a wiadomo ktoś jeszcze może używac takiego systemu choćby na jakiejś wirtualnej maszynie) i dodatkowo użyć listy / tablicy do zapisania wyszukanych nazw przy ich dodawaniu aby później przy przewijaniu mieć na pewno aktualny numer pozycji. Ewentualnie później jak będę miał więcej wolnego czasu napiszę na oficjalne forum supportu, gdzie zapronuje autorowi aby standardowy jakby wbudowany "plugin" o nazwie tc - dla conentu, miał po prostu możliwość pokazywania numeru porządkowego i również reagował na zmiany sortowania i zawartości katalogu. Także problem częściowo rozwiązany. Jakby ktoś miał pojęcie dlaczego podczepianie się pod funkcję obsługi komunikatu kontrolki w akurat w tym programie VCL powoduje "cyrki" to dajcie znać. I sorry za rozpisanie się.

1 użytkowników online, w tym zalogowanych: 0, gości: 1