artykuły

Delphi - Komunikaty I

17:28
śro, 10 listopad 2004
Pierwsza część popularnej serii artykułów objaśniająca zagadnienie komunikatów systemowych (nie mylić z oknami dialogowymi), ich funkcjonowanie i wykorzystywanie. W części pierwszej zaprezentowana zostanie podstawowa, a czytelnik nauczy się na prostym przykładzie pisać programy reagujące na określony typ komunikatów przekazywanych przez system.

Wstęp

Zapewne wielu z Was kojarzy tytuł z Windows'owskimi tabliczkami (MessageBox'ami), które system wyświetla gdy chce porozumieć się z użytkownikiem. Jednak gdy zagłębimy się w tytułowy temat - przestaniemy kojarzyć ze sobą te dwie rzeczy.

W istocie z komunikatami spotykamy się na co dzień podczas pracy z systemem Windows. W tym wirtualnym świecie systemu, komunikatem dla systemu jest wszystko to co robisz. Podczas poruszania kursorem myszy do systemu jest wysyłany komunikat, że mysz zmieniła swoje położenie. Gdy naciskasz przycisk myszy, system jest o tym informowany także za pomocą komunikatów. W sumie rozpoznaje ich około 700.

W Delphi projektujemy aplikacje, często nie zdając sobie sprawy z ich istnienia. Zazwyczaj wygląda to tak, że tworzymy nowy obiekt (dajmy na to przycisk Button1) i dwukrotnie na niego klikamy, chcąc mu przypisać instrukcje, które nastąpią po jego naciśnięciu. Czasem posługujemy się Inspektorem Obiektów, klikając na zakładkę Events i wybierając jedną z dostępnych dla danej kontrolki akcji. Mamy tam do wyboru różne zdarzenia, np. OnMouseMove, które zostaje wywołane gdy tylko kursor "zderzy się" z danym obiektem.

Czasami jednak, w bardziej skrajnych przypadkach, zachodzi potrzeba kontrolowania zdarzeń, których nie ma na karcie Events - Co wtedy? No cóż, pora nauczyć się "ręcznej" obsługi komunikatów. Delphi udostępnia nam także i taką funkcję. Z początku może Ci to stworzyć nieco problemów, jednak z biegiem czasu przestanie być to dla Ciebie czymś niewykonalnym i zaczniesz z tego korzystać. Sam mogę powiedzieć, że rzadko wykorzystuję komunikaty i pisanie aplikacji sprowadza się u mnie do metody dla "leniuchów".

Komunikaty są składnikiem czystego WinAPI, czyli Windows Application Programming Interface. Jest to technika programowania, która nie wykorzystuje formularzy. W uproszczeniu - wszystko wpisujemy ręcznie. Tam nie korzystamy z techniki przeciągnij i upuść, która tak upraszcza nam życie. Gdy w API zachodzi potrzeba stworzenia jakiegoś formularza bądź przycisku, musimy go napisać (!), czyli ręcznie przyporządkować wszystkie potrzebne właściwości typu kolor, rozmiary, nazwę, etykietę itp. Wiem, że dla niektórych może być to szok, ale nie martwcie się - jeśli czytacie ten artykuł to znaczy, że szybko Wam to nie grozi, gdyż do nauki API trzeba posiadać znacznie rozleglejszą wiedzę. Jest to praktycznie ostateczna faza rozwoju programisty ;) Jeśli nauczysz się API - żadne ograniczenie już Cię nie powstrzyma. Ważną zaletą API jest rozmiar skompilowanych programów. W Delphi program zajmuje ok. 300 kB, a w API ? - (uwaga!) ok. 5 kB. Patrząc na sprawę z innej perspektywy - komunikaty to pierwszy krok w stronę oświecenia. Zanim jednak Wasze dusze wydostaną się z wiecznych ciemności obiektowego programowania - polecam niniejszą lekturkę ;)

Jak z tego korzystać?

Cóż, popatrz:
Najpierw, w module, w sekcji private (można też w public) deklarujemy nową procedurę. Jest prawie normalna. "Prawie" oznacza, że nie do końca. Popatrz:

procedure klawisz(var msg: TMessage); message WM_CHAR;

Najpierw mamy słówko "procedure", potem nazwa procedury (klawisz). W nawiasie słówko var, a po nim deklaracja zmiennej msg jako typ TMessage, dalej zamknięcie nawiasu i średnik. Właśnie - normalna procedura na tym by się skończyła, jednak chcąc obsłużyć jakiś komunikat, musimy po średniku dopisać parę słówek, które "powiedzą" naszemu programowi jaki komunikat chcemy obsłużyć. Możemy to zrobić wpisując za średnikiem słówko message, a po nim typ komunikatu ( w tym wypadku WM_CHAR - odpowiada za naciśnięcie klawisza ). I na końcu znowu średnik.

Widzicie, nie taki wilk straszny... Problem jednak nie tyle w konstrukcji procedury co w zapamiętaniu nazw komunikatów. W tym przykładnie użyłem WM_CHAR, gdyż wydaje mi się on najprostszy. Można zareagować na kliknięcie lewym przyciskiem myszy:

procedure klawisz(var msg: TMessage); message WM_LBUTTONDOWN;

bądź prawym:

procedure klawisz(var msg: TMessage); message WM_RBUTTONDOWN;

lub środkowym:

procedure klawisz(var msg: TMessage); message WM_MBUTTONDOWN;

Dostępne są także inne komunikaty (przedstawiam najciekawsze):

Opisy wybranych komunikatów
Nazwa komunikatu Opis
WM_CHAR Naciśnięcie dowolnego klawisza na keyboard'zie
WM_LBUTTONDOWN Kliknięcie lewym przyciskiem myszy
WM_RBUTTONDOWN Kliknięcie prawym przyciskiem myszy
WM_MBUTTONDOWN Kliknięcie środkowym przyciskiem myszy
WM_CLOSE Występuje gdy zamykamy okno
WM_QUIT Występuje gdy program powinien być zakończony
WM_PAINT Występuje gdy okno zostało odświeżone
WM_ACTIVATE Występuje gdy okno stało się aktywne
CM_MOUSEENTER Najechanie kursorem na obiekt
WM_CREATE Podczas tworzenia formy
WM_DESTROY Podczas niszczenia formy (kiedy np. zamykamy program

Wszystko fajnie, ale żeby coś się działo trzeba napisać procedurę :) Teraz, gdy spróbujemy odpalić program - Delphi wskaże nam błąd. Zadeklarowaliśmy bowiem procedurę z komunikatem jednak jej nie napisaliśmy :). W takim wypadku Delphi nie wie co robić gdy dana procedura zostanie wywołana. Musimy się za to zabrać !

Poniżej słówka implementation wpisujemy procedurę, a w niej instrukcje, które mają być wykonane, gdy procedura zostanie wywołana.

Jednak uważajcie (!) poniżej słówka implementation znajduje się komentarz w nawiasach klamrowych. Wiem, że uczono Was, abyście nie zwracali uwagi na komentarz, gdyż kompilator je automatycznie pomija - jednak nie wszystkie. Wiem, że teraz robię Wam mentlik w głowie jednak istnieją typy komentarzy na które kompilator uwagę swą zwraca. Do takich wyjątków należy właśnie {$R *.dfm} . Zresztą - usuńcie go i zobaczcie co się stanie gdy uruchomicie program...

Narazie się tym nie przejmujcie - po prostu gdy czasem przyjdzie wam chęć "odchudzenia" kodu - ograniczcie swoją działalność jedynie do swoich procedur i funkcji (czyli tzw. metod).

Zboczyłem nieco z tematu, sorry, ale myślę, że ciekawostki się przydadzą. Skończyliśmy na wpisywaniu procedury. Powinno to wyglądać mniej więcej w ten sposób:

procedure TNazwa_Formy.nazwa_procedury(var nazwa_zmiennej_komunikatu : TMessage); begin {treść procedury} end;

czyli w praktyce:

procedure TForm1.klawisz(var msg: TMessage); begin TForm1.Color := clRed; ShowMessage('Witaj wielki świecie! Wywołałeś komunikat!'); end;

Cały kod prezentuje poniżej. Po powyższej lekturze nie powinniście mieć (większych ;) problemów z jego interpretacją.
Najpierw, w sekcji private następuje deklaracja procedury o tajemniczej nazwie "klawisz". Następnie, po procedurze widzimy słówko message i nazwę komunikatu jaki procedura "klawisz" ma obsłużyć. W tym wypadku jest to WM_CHAR, który reaguje na naciśnięcie klawisza. To jest jakby warunek wywołania tej procedury. Jeśli naciśniemy klawisz to wywołamy procedurę "klawisz", której kod znajduje się w sekcji implementation. W procedurze - typowe instrukcje. Przypisanie koloru czerwonego ;) formularzowi i wywołanie tabliczki z tekstem 'Witaj wielki świecie! Wywołałeś komunikat!'

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) private procedure klawisz(var msg: TMessage); message WM_CHAR; public end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.klawisz(var msg: TMessage); begin Form1.Color := clRed; ShowMessage('Witaj wielki świecie! Wywołałeś komunikat!'); end; end.

Zakończenie

Wiecie? To w zasadzie tyle jeśli chodzi o jednostronną obsługę komunikatów - czyli ich przechwytywanie. Chciałbym Was zachęcić do drugiej części artykułu, w której będziemy się zajmować wysyłaniem komunikatów do różnych aplikacji. Będziemy mogli zamknąć aplikację, znając jedynie jej nazwę! Podoba się? Jeśli tak - zapraszam do kolejnej części artykułu Delphi - komunikaty.

12345
Delphi - Komunikaty I Autor opinii: Czytelnicy, data przesłania: 5

Podobne artykuly:

Skomentuj

Aby zamieścić komentarz, proszę włączyć JavaScript - niestety roboty spamujące dają mi niezmiernie popalić.






Komentarze czytelników

    • Danielk32
    • czw, 1 wrzesień 2011, 0:39
    • Chciałem przechwycić kliknięcie prawego przycisku myszy i to działa ale tylko na formie a poza nią już nie czemu? i jak przechwycić kliknięcie poza formą?


      if Ustaw.Caption=''Wczytuje współrzędne'' then
      begin
      GetCursorPos(P);
      Wox.Text:=IntToStr(P.X);
      Woy.Text:=IntToStr(P.Y);
      Ustaw.Caption:=''Ustaw współrzędne'';
      end;






      Odp: Witam serdecznie. Zapoznaj się z tematem hooka na mysz. Hook pozwala na przechwytywanie zdarzeń napływających z danego źródła (klawiatura, mysz). Jest to już nieco wyższa szkoła jazdy, bo w grę wchodzą czyste procedury Windows API. Był o tym kiedyś artykuł na About.com - bardzo proszę:
      http://delphi.about.com/od/windowsshellapi/a/mousehook.htm
Dexter