Jak wygląda mechanizm przechwytu komunikatów?

1

Jak wygląda mechanizm przechwytu komunikatów - messages z Windows, tj. tych wszystkich WM_,
czyli WM_KEYDOWN, WM_SIZE, WM_LBUTTONDOWN, itd, potem WM_COMMAND z menu i kontrolek, no i z 500 innych?

Może przykład, niekoniecznie poprawny w Delphi:

TSuperWin = class(TWin)

 procedure WMPaint(var m : TMsg); message WM_Paint;

// jakieś inne 
 a,b,c : integer;
 color : superinteger;
end;

I teraz mam utworzony ten TSuperWin, powiedzmy że zmienna nazywa się sw,
no i jak tam jest zapakowana ta procedura WMPaint plus odpowiedni kod - WM_PAint,
bo może być przecież wiele różnych?

Wewnątrz, czyli z punktu widzenia asemblera.

Jest tam jakaś specjalna tabela procedur message,
podobnie jak dla metod virtual: sw.vmtT ?

Aha, czy można w Delphi przechwytywać komunikaty od kontrolek?

procedure IDList((notify_code : uint); message ID_LIST; ???

To jest wysyłane w postaci WM_COMMAND, plus id kontrolki i kod, np. LBN_SELCHANGE,
czyli to musiałoby być realizowane wewnątrz WMCommand:

procedure WMCommand; 
begin 
  if msg.id = ID_LIST and ... then IDList;
///
end;

Jest dokumentacja tych internalsów w delphi, albo i innego paskala, który coś takiego obrabia?

0

Piszę teraz z głowy, bo nie mam dostępu do swoich źródeł programów w WinAPI. Także najlepiej doczytaj na MSDNie. Do komunikatów odbieranych przez kontrolki dostaniesz się przez funkcję SetWindowLong z parametrem GWL_WNDPROC. Ewentualnie przez podmianę własności WndProc dla kontrolek pod VCL. A komunikaty z N przed _ o ile pamiętam są wysyłane po komunikacie WM_NOTIFY, a następnie na ogól w Hi/LoWord WParam. Pogogluj sobie za przykładowymi kodami w Google, a wszystko stanie się jaśniejsze. Co do VCLowych metod z parametrami TCosikMessage, to rzadko ich używam pod VCL, a pod czystym WinAPI, obsługuje się tak, jak wyjaśnia to MSDN dla konkretnych komunikatów WM_.... A konkretniej dla Delphi niuanse WinAPI wyjaśnić powinna Tobie strona www.angelfire.com/hi5/delphizeus/

0

Ja Windows tym zasuwa to ja wiem bardzo dobrze.

WM_NOTIFY jest od common controls ale tych nowszych: tree, listview, tab, up_down, itp.

Nie chcę rzeźbić w VCL, lecz w samym paskalu, i chodzi mi o zbiorcze załatwienie tych komunikatów z windows za pomocą rozszerzeń składni samego paskala, tj. metod message.

Nie będę przecież tworzył kodu w stylu:

procedure doMessage(m)
begin 

 case m.wm of
  WM_ACTIVATE: aktivate;
  WM_CHAR: char;
  WM_MOUSEMOVE: mousemove;
  WM_SETCURSOR: setcursor;
  WM_PAINT: paint;
  WM_SIZE: size;
  WM_INITMENU: initmenu;

  WM_COMMAND: if iscommand then command else if isnotify then idnotify;
  WM_NOTIFY: notify;
  WM_QUIT: quit;

 else Default end;

Swoją drogą taka metoda byłaby niezła, pod warunkiem że kompilator wywoływałby sam te funkcji - po nazwach. :)

usunięcie cytowania całego poprzedniego posta - fp

0
olesio napisał(a):

strona www.angelfire.com/hi5/delphizeus/

O! Właśnie dzisiaj sam to znalazłem.
Ciekawe podejście, ale nie ma tam nic o obsłudze komunikatów za pomocą metod message.

On programuje linearnie, znaczy jak w C, czyli w ogóle bez obiektów.
Wtedy się robiło właśnie takie giga switche w mainloopie:

GetMessage albo Peek i jedziemy z tym na piechotę.
Metoda może i dobra, bo pewna i niezawodna, ale to dość ciężko potem wygląda, takie nieczytelne i rozwleczone.

Ja chciałem zrobić tylko kilka klass bazowych, które będą robić to za mnie.

Zaczynamy od TWin i tam już same się robią te podstawowe komunikaty,
plus przerzucanie WM_COMMAND do dzieci, jakieś tam wyświetlanie ToolTipów, i inne toolboxy, statusy, menusy.

Potem sobie tylko definiuję specjalistyczne klasy z tego TWin, lub TDlg, może coś tam jeszcze,
i tu mogę obsługiwać inne messagesy i w tym pokrywać niektóre z TWin.

Byłoby z 90% mniej roboty.

0

Nie wiem w takim razie, co Tobie mogę jeszcze doradzić. Sposób jaki podałeś powyżej, a przynajmniej częściowo stosowałem w swoich programach w WinAPI. W zasadzie poza WM_INITDIALOG czy WM_COMAND, ewentualnie WM_PAINT nie stosuje wiele innych. Oczywiście możesz sobie zaprojektować klasę po swojemu z obsługą OnWMPaint i tym podobnych. Można pokombinować tak jak na www.kolmck.net - ja piszę czasem rozwlekłą funkcję obsługi komunikatów okna głównego, a kontrolki subclasuje tak jak opisałem, najczęściej rozdzielam tylko dokładniej WM_COMMAND. Osobiście się w tym odnajduje.

0
olesio napisał(a):

Nie wiem w takim razie, co Tobie mogę jeszcze doradzić. Sposób jaki podałeś powyżej, a przynajmniej częściowo stosowałem w swoich programach w WinAPI. W zasadzie poza WM_INITDIALOG czy WM_COMAND, ewentualnie WM_PAINT nie stosuje wiele innych.

W dużych aplikacjach trzeba zwykle obsługiwać znacznie więcej komunikatów.
W edytorach dojdzie np. wm_setfocus, wm_setcursor, klawiatura, mysz - prawy, lewy, move, dblclk, itd. minimum z 20 różnych.
Jeszcze WM_NOTIFY z nowszymi kontrolkami - podobnie WM_cmd...

olesio napisał(a):

Oczywiście możesz sobie zaprojektować klasę po swojemu z obsługą OnWMPaint i tym podobnych. Można pokombinować tak jak na www.kolmck.net

Nie wiem za bardzo co to jest, ale tam jest plik pas o rozmiarze ponad 1MB, czyli chyba kolejna kobyła, wbrew zeznaniom autora.

Pewnie tak zawsze się kończą próby automatyzacji tych komunikatów.
Ma być coś prostego, a potem dokładamy, urozmaicamy, rozszerzamy i ostatecznie mamy nowe VCL, albo nawet i .net...
To jest dobre, ale tylko dla samych twórców - autorów, bo oni znają na pamięć co tworzyli i rozbudowywali stopniowo przez 10 lat. P)

Ale i tak wydaje mi się, że można zrobić coś prostego i na tym zakończyć.
Z 5 klass bazowych, każda po kilka funkcji, plus trochę kodu;
pewnie byłoby tego kilka KB, czyli znacznie poniżej MB.
A potem definiujemy już tylko swoje klasy z tych bazowych, a w nich metody messages i chyba tyle wystarczy.

W VCL albo MFC jest za dużo tych klas - dla każdej kontrolki z osobna: TEdit, TListBox, TTreeView, TButton, itd.
I to jest całkowicie zbyteczne i prowadzi do przerostu aplikacji - tam jest chyba ze sto razy powtarzany ten sam kod.

0

Skombinuj sobie skądś w ramach poglądowych choćby wersję Delphi 7 Enterprise. Tam są w podkatalogu Source żródeł VCL, zobaczysz, że kod się raczej nie powtarza. A co do kolmck, to kiedyś polecił mi tę stronę Misiekd. Ale korzystam tylko z zamieszczonych tam zamieników modułów systemowych i Windows. Dzięki czemu exek w Delphi 7 jest jeszcze mniejszy. Moduły te jednak mają przynajmniej dwie wady, które zauważyłem. Mianowicie aplikacja konsolowa nie przekieruje wyników do pliku. Oraz występuje problem z zakładaniem hooków na funkcje API, bo występują błedy av mimo prawidłowego kodu. To że kod jednego modułu ma 1 MB lub więcej to faktycznie przesada, ale skoro tak Cie to razi można mawet podzielić kod lamersko ma pliki dyrektywą kompilatora $I. Zestaw komponentów kolmck pozwala tworzyć wizualnie programy, a kod wynikowy powinien być mały jak w WinAPI. Mi niestety się nie udało zmusić tego do działania - kod wynikowy był nadal opasły. Także sobie odpuściłem. Jeśli bardzo czujesz potrzebę to zakodujm sobie zestaw klas do obsługi aplikacji WinAPI. Ja to jednak uważam za rozmienianie się na drobne. Gdyż nie wiem jak mamy Ci pomóc, ja piszę bez takiego kombinowania. Gdybym tracił czas na perfekcyjne stworzenie klas, to w rozumieniu WinAPI daleko'bym się nie posunął, a i wielu programów na swoje potrzeby w krótkim czasie bym nie stworzył.

0
olesio napisał(a):

Skombinuj sobie skądś w ramach poglądowych choćby wersję Delphi 7 Enterprise. Tam są w podkatalogu Source żródeł VCL, zobaczysz, że kod się raczej nie powtarza.

Kiedyś to przeglądałem i zauważył, że tam próbują robić wiele rzeczy od nowa, które są już zrobione - w tych dll windowsa.

Robienie obiektów z wszystkie to też znany i stary błąd:
TFont, TPen, jakiś tam TCanvas do rysowania - po co to komu?

Przecież to działa z 50 razy wolniej od funkcji z systemu.

Może niech sobie zrobią jeszcze obiekty: TIneger, TFloat, i temu podobne (może to już nawet i jest).
Wtedy szybkość działania aplikacje będzie już przeogromna - prędkość światła.

olesio napisał(a):

Gdyż nie wiem jak mamy Ci pomóc, ja piszę bez takiego kombinowania. Gdybym tracił czas na perfekcyjne stworzenie klas, to w rozumieniu WinAPI daleko'bym się nie posunął, a i wielu programów na swoje potrzeby w krótkim czasie bym nie stworzył.

Znalazłem już to o co mi chodziło, tj. strukturę objektów i klas.
Przynajmniej w wersji dla free pascala, ale w innych jest pewnie podobnie:
http://www.freepascal.org/docs-html/prog/progsu164.html#x207-2200008.2.12

+16 Pointer to the dynamic method table (using message with integers).

0

Jeśli chcesz własną kontrolkę w WinAPI, proponuję (już niezależnie od tych message'y) napisać to tak, jak ludzie od Common Controls to zrobili: osobna DLL-ka udostępniająca natywne kontrolki, tak że potem można to obiektowo opakować w kontrolkę VCL, WindowsForms czy co komu będzie potrzebne.

Od strony programistycznej: DLL-ka robi RegisterClass, posiada swoją funkcję WndProc która wysyła WM_NOTIFY/WM_COMMAND do parenta, a exek robi CreateWindow z tą samą nazwą klasy (albo wartością ATOM zwróconą przez RegisterClass).

Działa to bardzo fajnie, i jest przenośne na wszystkie biblioteki wysokiego poziomu.

0

Ale ja chcę zrobić coś dokładnie przeciwnego:
zautomatyzować obsługę kontrolek w ogóle, a wtedy nieważne jest czy one będą standardowe, czy też nie.

Potem w programie robiłbym tylko procedury do komunikatów i nic poza tym.
Technicznie wyglądałoby to tak:

mam okno, czy dialog, z kilkoma kontrolkami, które muszą być, bo jakoś przecież trzeba wprowadzać dane do programu, więc robię kod, który to robi, wsadzam w odpowiednie messages i tyle.

Mniej robić nie można, a więcej nie ma sensu.

I nie potrzeba mi tu robić żadnych takich: TEdit, TMemo, TListView, itd. a zwłaszcza: TLabel, TGroupbox, TPicture, i inne takie dekoracje.

One są już przecież zrobione w Windows.
Wsadzam tylko dane do niektórych kontrolek na starcie, potem obsługuję niektóre komunikaty podczas edycji, a na końcu ściągam wpisane, wybrane dane.

Wsadzenie danych to przecież kilka linii kodu: do list ładujemy zwykle jakieś stringi,
do edit jeden - niekiedy długi (memo to to to samo co edit, jedynie flaga 'multiline' - jeden bit różnicy),
radiobutony, checkboxy - tu nie ma nic do roboty, jedno wywołanie funkcji to ustawia.

Prywatne odmiany kontrolek można robić łatwo z tych standardowych -
poprzez sam przechwyt komunikatów: rysować po swojemu, sortować, klikać inaczej, albo może przewijać cyklicznie te listy... hihi!

Całkiem nowe też nie trudno sobie postawić, co zresztą każda aplikacja i tak musi zrobić przynajmniej raz: stawiając to okno główne.

usunięcie cytowania całego poprzedniego posta - fp

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