Delphi - Appication Bar alkalmazás komponense

forráskód letöltése
Ha egy Appication Bar alkalmazást szeretnénk készíteni (ilyen például a Windows Tálca, vagy az Office Indítópult is), akkor bizony elég sok feladatot el kell végeznünk. Mi lenne, ha mindezt egy komponens elvégezné helyettünk, és nekünk semmi más dolgunk nem lenne, csak ezt a komponenst elhelyezni a Form-on. A mellékelt példaprogram megnyitása előtt az AppBar.pas-ban lévő komponenst telepítenie kell a Delphi alá.

Egy TAppBarData típusú változó (abd) lesz segítségünkre abban, hogy az ablakunkból AppBar ablakot varázsoljunk. Az ablak a képernyő alsó, felső, baloldali vagy jobboldali széléhez lesz mindig igazítva, és a felhasználó az egérrel ahhoz az oldalhoz mozgathatja, ahova akarja, hasonlóan a Tálcához. Mivel ehhez több Windows üzenetet is tudnunk kell fogadni, ezért egy új üzenetkezelő eljárást kell készítenünk. Az ablak méretét az egyes pozíciókban a Width és a Height property-k határozzák meg. Az Align property azt határozza meg, hogy az ablakot a képernyő mely széléhez kell igazítani. Az előkészületeket a komponens konstruktorában kell elvégeznünk:
constructor TAppBar.Create;
begin
  inherited;
A Heigh és Width property-k értékét beállítjuk az ablak szélességére és magasságára.
  FWidth:=(Owner as TForm).Width;
  FHeight:=(Owner as TForm).Height;
Az FAlign property azt határozza meg, hogy az ablak a képernyő mely széléhez legyen igazítva. Alapértelmezésként a képernyő alsó szélét adjuk meg.
  TAppBarAlign = (alTop, alBottom, alLeft, alRight);

  FAlign:=alBottom;
Csak a program futtatása közben lépünk működésbe, mert szerkesztési időben kényelmetlen lenne az AppBar ablakot kezelni!
  if NOT (csDesigning in ComponentState) then
  begin
Létrehozzuk az üzenetkezelő eljárásunkat úgy, hogy az eredetit eltároljuk az FOldWndProc változóban. Ezután beállítjuk az ablak keretének stílusát bsToolWindow-ra. Ezzel elérjük azt, hogy az ablakot nem lehet átméretezni!
    FDestroying:=false;
    FOldWndProc:=(AOwner as TForm).WindowProc;
    FMsgNum:=MessageNum;
    inc(messagenum);
    (Owner as TForm).WindowProc:=WndProc;
    (Owner as TForm).BorderStyle:=bsToolWindow;
Beállítjuk az AppBar adatokat. A cbSize a TAppBarData rekord mérete, a hWnd az ablakunk azonosítója (Handle), az uCallBackMessage az üzenet azonosítója. Az SHAppBarMessage függvénnyel létrehozzuk az AppBar ablakunkat. Ez a függvény lesz az, amivel az összes AppBar-ral kapcsolatos tevékenységet végeztetjük.
    abd.cbSize := sizeof(abd);
    abd.hWnd := (Owner as TForm).Handle;
    abd.uCallBackMessage := wm_AppBarMessage;
    abd.uEdge:=ABE_BOTTOM;
    SHAppBarMessage(ABM_NEW, abd);
  end
  else FDestroying:=true;
end;
Az ablakhoz érkezett üzeneteket a WindProc eljárásban dolgozzuk fel. Ez egy TMessage paramétert kap, amiből minden üzenet esetében az azzal összefüggő adatokat olvashatjuk ki, ill. adhatjuk meg.
procedure TAppBar.WndProc;
var P:TPoint;
begin
  case msg.Msg of
  WM_CLOSE, WM_DESTROY:
    begin
      FDestroying:=true;
    end;
Ha az ablakot aktivizálták, akkor az AppBar-t is aktivizáljuk.
  WM_ACTIVATE:
    begin
      SHAppBarMessage(ABM_ACTIVATE, abd);
    end;
Ha egy WM_APPBARMESSAGE üzenetet kapunk, akkor ellenőrizzük, hogy indítottak-e egy olyan alkalmazást, ami a teljes képernyő területét elfoglalja. Ha igen, akkor elrejtjük az ablakunkat, ellenkező esetben pedig megjelenítjük azt. Még ugyanennél az üzenetnél ellenőrizzük azt is, hogy meg kell-e változtatni az ablak helyzetét. Ha igen, akkor beállítjuk az új pozíciót, a képernyő széléhez való igazítás figyelembevételével.
  WM_APPBARMESSAGE:
    begin
      if Msg.wParam = ABN_FULLSCREENAPP then
        if Msg.lParam <> 0 then (Owner as TForm).Hide else (Owner as TForm).Show;

      if Msg.wParam = ABN_POSCHANGED then
      begin
        abd.rc := RequestRect;
        SHAppBarMessage(ABM_QUERYPOS, abd);
        case abd.uEdge of
          ABE_TOP: abd.rc.Bottom := abd.rc.Top + FHeight;
          ABE_LEFT: abd.rc.Right := abd.rc.Left + FWidth;
          ABE_RIGHT: abd.rc.Left := abd.rc.Right - FWidth;
          ABE_BOTTOM: abd.rc.Top := abd.rc.Bottom - FHeight;
        end;
        SHAppBarMessage(ABM_SETPOS, abd);
        (Owner as TForm).SetBounds(abd.rc.Left, abd.rc.Top, abd.rc.Right-abd.rc.Left, abd.rc.Bottom-abd.rc.Top);
      end;
      msg.Result:=integer(true);
    end;
Ha az ablak pozícióját megváltoztatták, akkor küldünk egy ABM_WINDOWPOSCHANGED üzenetet az SHAppBarMessage függvénnyel. Ezzel tudatjuk a rendszerrel, hogy az AppBar ablakunk pozícióját megváltoztatták.
  WM_WINDOWPOSCHANGED:
    begin
      SHAppBarMessage(ABM_WINDOWPOSCHANGED, abd);
      msg.Result:=integer(true);
    end;
Amikor a felhasználó az ablakot a fejlécénél fogva elmozgatja, akkor egy WM_MOVING üzenetet kapunk. Ennél az üzenetnél lekérdezzük az egér kurzor pozícióját, és annak megfelelően beállítjuk az ablak AppBar igazítását és az ablak pozícióját.
  WM_MOVING:
    begin
      GetCursorPos(P);

      if (P.Y < Screen.Height/Screen.Width*P.X) and
         (P.Y < -(Screen.Height/Screen.Width*P.X)+Screen.Height) then
      begin
        abd.uEdge := ABE_TOP;
        abd.rc := RequestRect;
        SHAppBarMessage(ABM_QUERYPOS, abd);
        abd.rc.Bottom := abd.rc.Top + FHeight;
        PRect(Msg.lParam)^ := abd.rc;
      end;

      if (P.Y >= Screen.Height/Screen.Width*P.X) and
         (P.Y < -(Screen.Height/Screen.Width*P.X)+Screen.Height) then
      begin
        abd.uEdge := ABE_LEFT;
        abd.rc := RequestRect;
        SHAppBarMessage(ABM_QUERYPOS, abd);
        abd.rc.Right := abd.rc.Left + FWidth;
        PRect(Msg.lParam)^ := abd.rc;
      end;

      if (P.Y >= Screen.Height/Screen.Width*P.X) and
         (P.Y >= -(Screen.Height/Screen.Width*P.X)+Screen.Height) then
      begin
        abd.uEdge := ABE_BOTTOM;
        abd.rc := RequestRect;
        SHAppBarMessage(ABM_QUERYPOS, abd);
        abd.rc.Top := abd.rc.Bottom - FHeight;
        PRect(Msg.lParam)^ := abd.rc;
      end;

      if (P.Y < Screen.Height/Screen.Width*P.X) and
         (P.Y >= -(Screen.Height/Screen.Width*P.X)+Screen.Height) then
      begin
        abd.uEdge := ABE_RIGHT;
        abd.rc := RequestRect;
        SHAppBarMessage(ABM_QUERYPOS, abd);
        abd.rc.Left := abd.rc.Right - FWidth;
        PRect(Msg.lParam)^ := abd.rc;
      end;
      msg.Result:=integer(true);
    end;

Ha az ablakot új pozícióba helyeztük, akkor az AppBar koordinátáit is módosítani kell. Ezt a WM_EXITSOZEMOVE üzenetnél kell elvégeznünk, mert az akkor jön létre, amikor az ablak átméretezése ill. elmozgatása megtörtént.
  WM_EXITSIZEMOVE:
    begin
      (Owner as TForm).SetBounds(abd.rc.Left, abd.rc.Top, abd.rc.Right-abd.rc.Left, abd.rc.Bottom-abd.rc.Top);
      SHAppBarMessage(ABM_SETPOS, abd);
      msg.Result:=integer(true);
    end;
  end;
  FOldWndProc(MSG);
end;
A GetRequestRect függvénnyel meghatározhatjuk az AppBar koordinátáit. A függvény visszatérési értéke egy TRect rekord.