A Borland Delphi
rendszer számos, a Windowsban (és a Linuxban) használt rendszereszközhöz
tartalmaz komponenseket, osztályokat. Mégis érhetetlen módon több elem hiányzik
belőle, melyek sokszor, vagy csak ritkán, de jól jönnének egy program
fejlesztése során. Cikksorozatunkban ilyen komponenseket fogunk készíteni. A
sorozatot más programnyelvek használóinak is ajánlom, hiszen a bemutatott
Windows API függvények bizonyára más nyelveken is elérhetőek.
Előző
számunkban az Windows Asztalra helyezhető eszköztárakkal, az ún.
Application Desktop Toolbar-okkal kezdtünk el foglalkozni. Áttekintettük a
megvalósításhoz szükséges Windows API ismeretek egy részét, amit most folytatni
fogunk.
A cikksorozat
korábbi részében megismerkedtünk a callback függvényekkel. Megbeszéltük, hogy ezek arra
alkalmasak, hogy a Windows bizonyos eseményeket visszajelezzen programunk
számára. Ez nem mindig a legmegfelelőbb módszer.
Egy másik
lehetőséget már tulajdonképpen használtuk. A SendMessage API függvénnyel üzeneteket küldtünk
egy-egy ablak leíróval, azonosítóval ellátott vezérlőnek, amelynek
segítségével parancsokat adtunk neki. Így tudtunk például elrejteni egy gombot
egy Formon, vagy éppen magát a Formot bezárni. Ilyen üzenettel azonban
állapotokat is jelezhetünk a vezérlőknek, melyeket aztán belátásuk szerint
értelmezhetnek és feldolgozhatnak.
Egy másik módszer
tehát a callback függvények
mellett az üzenetek küldése.
Üzenetek
fogadásához először deklarálnunk kell egy függvényt, mely a következő
formát követi:
Procedure FVNev(var Msg :
TMessage); message ÜZENET_KONSTANS;
Ha belenézünk a Windows
és Messages unitba, számos WM_xxx formájú konstanst találunk. Ezek
mind olyan üzenetek, amelyek a Delphi, és mi is használhatunk. A legtöbbre
azonban nincs szükség, mivel a Delphi komponensek ezeket mind lekezelik.
Definiálhatunk saját üzeneteket is – ahogy ezt tenni is fogjuk. Van egy
speciális üzenet konstans, amelynek felhasználása nem meghatározott, sőt,
a konstansnál nagyobb számok szintén korlátozás nélkül használhatóak. Ez a WM_USER
(=$7FFF) konstans. Már csak azt nem beszéltük meg, hogy mit takar ez a TMessage
típus. Ez egy rekord, melynek deklarációja a követező:
TMessage = packed
record
Msg: Cardinal;
case
Integer of
0: (
WParam: Longint;
LParam: Longint;
Result: Longint);
1: (
WParamLo: Word;
WParamHi: Word;
LParamLo: Word;
LParamHi: Word;
ResultLo: Word;
ResultHi: Word);
end;
Emlékezzünk
vissza a SendMessage függvény paramétereire (ha nem emlékszünk, keressük
vissza a CD-t és nézzük meg :) ) Az Msg mező tartalmazza a küldött üzenet azonosítóját. Volt egy lParam és egy wParam paraméterünk is. Azt is megbeszéltük
anno, hogyan lehet nem egész szám típusú paramétereket is egész számként
átadni. Nos, ezeket a paramétereket ebben a rekordban kapjuk meg (a
megfelelő mezőkben természetesen). Üzenettől függően
egy-egy visszatérési értékre is szükség van, melyek az üzenet feldolgozásának
sikerét jelzik, de más jellegű információt is vissza lehet természetesen
adni.
Most nézzünk egy
konkrét példát, hogy végleg letisztuljon, ami esetleg így még nem világos.
Példánkban egy
olyan üzenetet fogunk készíteni, amely az ablak átméretezése után kiírja annak
új szélességét és magasságát. Ehhez kezdjünk egy új projektet és a private kulcsszó elé hozzunk létre egy WMSize eljárást a fent leírt sablon szerint:
TForm1 = class(TForm)
procedure
WMSize(var Msg : TMessage); message WM_SIZE;
private
{ Private declarations }
public
{ Public declarations }
end;
És most a minden
kételyt és ködöt eloszlató kifejtő rész:
procedure
TForm1.WMSize(var Msg: TMessage);
begin
inherited;
case Msg.WParam
of
SIZE_MAXIMIZED :
ShowMessage('Maximalizálva - Szélesség: ' + IntToStr(Msg.LParamLo) + ';
Magasság:' + IntToStr(Msg.LParamHi));
SIZE_RESTORED :
ShowMessage('Visszaállítva - Szélesség: ' + IntToStr(Msg.LParamLo) + ';
Magasság:' + IntToStr(Msg.LParamHi));
end;
end;
Az egyetlen
dolog, amit eddig még nem magyaráztam meg, hogy mit keres ott az inherited
kulcsszó. Nos a Delphi is természetesen ezt a módszert használja, hogy megfogja
ezeket az üzeneteket, és például olyan többletfunkciókat adjon, mint a méret
korlátozás, stb. Ehhez a TForm-ban található WMSize is le kell, hogy fusson. A message
direktívával megjelölt metódusok öröklődése némiképp eltér a hagyományos
metódusokétól. Nem feltétlenül kell egy-egy üzenethez tartozó kezelő metódust
minden osztályban ugyanazzal a névvel deklarálni ahhoz, hogy az inherited
megtalálja az ős példányt. Ilyenkor nem a metódus neve lesz a kulcs, ami
alapján az inherited keres, hanem az üzenetazonosító. Ha most példánkban
nem WMSize-nak, hanem például
MeretUzenet-nek neveztük volna el a metódust, a
program akkor is ugyan úgy működött volna.
Még néhány
apróság és a komponens megírása következik a következő számban.
Addig is minden
jót mindenkinek.