Delphi és Win32 API – Nem csak Delphi felhasználóknak: V. rész

Application Desktop Toolbars - 2.

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.

 

Callback függvény alternatíva

 

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ása Delphi-ben

 

Ü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.

 

Egy példa

 

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.

 

Geiger Tamás - info@gsc.hu