Delphi - Árnyék megjelenítése a Form-on

forráskód letöltése
Egy grafikus felületen elhelyezett Panel komponens nem túl szép látvány, de feldobhatjuk úgy, hogy úgy jelenítjük meg, mintha árnyékot vetne a háttérre, ezzel mintegy kiemelve a Form síkjából. Az árnyék pozícióját és tulajdonságait (pl. átlátszóság) ugyanúgy állíthatjuk be szerkesztési időben, mint a többi vizuális komponensnél, viszont futási időben a komponens területén a Form háttere fog látszani, a megadott mértékben elsötétítve.
A mellékelt példaprogram megnyitása előtt a Shadow.pas-ban lévő komponenst telepítenie kell a Delphi alá. Ehhez válassza a Component - Install Component menüpontot.
A komponenst a TControl osztályból származtatjuk, aminek az lesz az előnye, hogy szerkesztési időben meg tudjuk határozni a helyét és méretét. A komponens futási időben nem látszik, ha a construktor-ban a Visible property-jét hamisra állítjuk. Az árnyék átlátszóságát a Transparency property-ben lehet beállítani, egy 0-100 közötti értékkel. A 0 értéknél az árnyék fekete lesz, míg 100-nál teljesen átlátszó, tehát nem is látható.
A komponens tulajdonképpen rajzolni fog a Form-ra, arra a területre, ahová a komponenst helyeztük. A rajzolás akkor történik meg, amikor a Form a WM_PAINT üzenetet kapja. A Form üzeneteinek megszerzéséhez az eseménykezelő eljárást át kell irányítanunk a saját eljárásunkra. Ebben meghívjuk az eredeti eljárást, majd ha a WM_PAINT üzenet érkezett, akkor meghívjuk a DrawShadow eljárást is.
A DrawShadow eljárásban létrehozunk egy TBitmap-et, aminek a mérete pont akkora lesz, amekkora az árnyék. Erre átmásoljuk a Form azon területét, amelyet az árnyék lefed. Ezután egy ciklusban elsötétítjük a bitkép pixeleit a Transparency property-ben megadott értéknek megfelelően, majd a bitmap-et rámásoljuk a Form-ra.
        for yy:=0 to Height-1 do begin
          l:=ScanLine[yy];
          for xx:=0 to Width-1 do begin
            l[xx].rgbtRed:=Min(Round(l[xx].rgbtRed*FTransparency/100), 255);
            l[xx].rgbtGreen:=Min(Round(l[xx].rgbtGreen*FTransparency/100), 255);
            l[xx].rgbtBlue:=Min(Round(l[xx].rgbtBlue*FTransparency/100), 255);
          end;
        end;
A Control-ok mindig az árnyék felett jelennek meg, viszont például az Image komponens nem, így az árnyék az ebben megjelenített kép pixeleit is el fogja sötétíteni, ahogyan az a mellékelt példában is látszik.