Delphi - Egy érdekes grafikai effekt

forráskód letöltése
Ebben a cikkben egy olyan 3D stílusú "lámpát" készítünk, melynek színe tetszőleges lehet. A mellékelt példaprogram megnyitása előtt a ColorLamp.pas-ban lévő komponenst telepítenie kell a Delphi alá.

Ennél a komponensnél már tetszőleges színt megadhatunk, és a megjelenését is szabályozhatjuk. Ha a Shadow property értéke True, akkor a komponens kinézete 3D-s hatású. Most nézzük meg, hogy ezt a hatást hogyan lehet viszonylag egyszerűen elérni.

Először is készítenünk kell egy szürkeárnyalatos képet, amelyet a meghatározott színű komponens fölé rajzolunk úgy, hogy az átlátszóságát 50%-ra állítjuk. Így azt az eredményt érjük el, hogy ahol a szürkeárnyalatos kép világosabb, ott az eredeti szín is világosabb, ahol pedig sötétebb, ott az eredeti szín is sötétebb lesz. Tehát egy olyan képet kell készítenünk, amely egy fényes, szürke gömbre hasonlít. Ezt a képet a ColorLamp.res fájlban tároljuk. Ha egy kicsit változtatni akarunk a megjelenésen, például nem egy sima felületű rajzot szeretnénk kapni, akkor csak el kell készítenünk az új szürkeárnyalatos képet, és létrehozni belőle egy ColorLamp.res nevű állományt, az eredetit felülírva. A komponens újrafordítása után már az új képnek megfelelően jelenik meg a komponens. Nem kötelező a képnek szürkeárnyalatosnak lennie, de ha nem az, akkor az eredetileg megadott szín módosulni fog!

A komponens kirajzolása itt is a Paint metódusban történik:
procedure TColorLamp.Paint;
var Blend:TBlendFunction;
    pw:integer;
    r:TRect;
begin
  inherited;
Először kirajzolunk egy kört, melyet az FColor property-ben meghatározott színnel színezünk ki. Ha a komponens szélessége és magassága nem egyezik meg, akkor a rajz ellipszis lesz.
  with Canvas do begin
    Brush.Color:=ColorToRGB(FColor);
    Brush.Style:=bsSolid;
    Pen.Width:=1;
    Pen.Color:=FColor;
    Ellipse(ClientRect);
  end;
Ha az FShadow property értéke True, akkor az AlphaBlend függvénnyel kirajzoljuk a szürkeárnyalatos képet a komponens fölé 50%-os átlátszósággal. Az 50%-os átlátszóságot úgy állítjuk be, hogy a Blend változó SourceConstantAlpha mezőjének értékét 128-ra állítjuk be.
  if FShadow then begin
    Blend.BlendOp:=0;
    Blend.BlendFlags:=0;
    Blend.SourceConstantAlpha:=128;
    Blend.AlphaFormat:=AC_SRC_OVER;
    AlphaBlend(
      Canvas.Handle, 0, 0, Width, Height,
      FShadowBmp.Canvas.Handle, 0, 0, FShadowBmp.Width, FShadowBmp.Height,
      Blend);
  end;
Ha az FOutline property értéke True, akkor még egy fekete körvonalat is rajzolunk. Ennek vastagságát a komponens méretétől tesszük függővé.
  if FOutline then begin
    pw:=Round((Width+Height)/63);
    r:=ClientRect;
    r.Left:=r.Left+pw div 2;
    r.Right:=r.Right-pw div 2;
    r.Top:=r.Top+pw div 2;
    r.Bottom:=r.Bottom-pw div 2;
    with Canvas do begin
      Brush.Style:=bsClear;
      Pen.Color:=clBlack;
      Pen.Width:=pw;
      Ellipse(r);
    end;
  end;
end;