2012. október 12., péntek

Gomb menüvel

Ma egy kis programozás félével rukkolok elő. A Firefox böngésző program menüje ihletett meg, aminek hatására szerettem volna valami hasonlót előállítani. Itt balra a mellékelt ábrán látszik is, hogy mire gondolok. Az elhatározást tett követte, lássuk mire jutottam.
Amire szükség lesz az a Lazarus fejlesztőkörnyezet. Itt hozzunk létre egy új projektet, majd a szerkeszthető formra tegyünk egy panelt. A panel színét  clMenuBar színűre kell beállítani. Az igazítást (Align) pedig alTop-ra. A BevelInner és a BevelOuter propertyk legyenek egységesen bvNonera állítva. Ezzel meg is kaptuk azt a fekete részt a képen, ami az ablak címsora alatt van. Most tegyünk fel erre a panelre egy SpeedButtont. Ezt már nem a Standard, hanem az Additional palettán találjuk. Azért erre a komponensre lesz most szükségünk, mert itt be tudjuk állítani, hogy lapos legyen. Tegyük is meg mindjárt és állítsuk be a gombunk Flat propertyjét Truera. Ezt követően adjunk valami cimkét a gombnak, ami legyen mondjuk Menü ▼. Mint látható tettem ide egy fura karaktert, ami egy lefelé mutató kis háromszög. Ezt a karaktertáblából ki tudjuk másolni a kódja U+25BC. Ha a gombunk nem méreteződik át automatikusan a szövegünk méretéhez, akkor méretezzük át. Ezt megtehetjük az egér segítségével, vagy a Height és a Width property beállításával.

Most, hogy már akad egy gombunk jó lenne összeházasítani valami menüfélével. Ehhez használjuk a komponenspaletta Standard fülén található PopupMenu komponenst. Ezt csak tegyük le valahova a formra, a pozíciónak nincsen jelentősége. Az Object Inspector ablakában nyomjunk egy jobb klikket a Popupmenün és válasszuk ki a Menu editort. Ennek segítségével hozzunk létre néhány menüpontot, hogy majd legyen mit megjeleníteni.
Van már gombunk és van menü elemünk is, kezdjünk hát hozzá, hogy kicsit testre szabjuk őket. Első körben azt szeretném, hogy ha az egeret a gombra viszem, akkor az megváltozzon, mint az az ábrán is látható. Ehhez a gomb eseményeit kell kezelésbe venni. A kívánt hatás eléréséhez három eseményt fogunk felhasználni a gomb esetében és egyet a menüében. Maradjunk még a gombnál tehát. Elsőnek az onMouseEnter esemény beállítása következik, ez hajtódik végre akkor, amikor az egér a gomb fölé kerül. Itt beállítom a gomb színét, a gombon levő szöveg színét és a korábban beállított Flat propertyt.
A kész esemény az alábbiak szerint alakul:

procedure TForm1.spBtnMouseEnter(Sender: TObject);
begin
   spBtn.Color:=clBtnFace;
   spBtn.Flat:=False;
   spBtn.Font.Color:=clBtnText;
end;


Ezt követően azt is meg kell csinálni, hogy mi történjen ha az egér elhagyja a gombot. Ehhez az onMouseLeave eseményt kell elkészíteni, ahol az imént beállított értékeket fogjuk visszaállítani valahogy így:

procedure TForm1.spBtnMouseLeave(Sender: TObject);
begin
   spBtn.Color:=clMenuBar;
   spBtn.Flat:=True;
   spBtn.Font.Color:=clMenuText;
end;


Most ha lefordítjuk a programot, akkor már ki is próbálhatjuk, hogy mit barkácsoltunk össze. Az egér mozgatása a gombra és le róla szemmel láthatóan működik.
Következzék a menü és gomb összekapcsolása. Nos, itt nem kell semmi komolyra gondolni, mindössze annyi fog történni, hogy a gombunk onClick eseményét hozzuk létre, hiszen azt szeretnénk, hogy a gombra történő kattintáskor megjelenjen a menü. Amit ehhez tudnunk kell az az, hogy a menüt pont a gomb alá akarjuk pozicionálni. Ezért az eseményhez létrehozott eljárásban deklarálok egy mnuPoint változót TPoint típussal, ebben fogjuk tárolni azt a koordinátát, ami a menünk bal felső sarkát jelenti. Az eljárás az alábbiak szerint néz ki:

procedure TForm1.spBtnClick(Sender: TObject);
var
  mnuPoint: TPoint;
begin
   mnuPoint.X:=spBtn.Left+2;
   mnuPoint.Y:=spBtn.Top+spBtn.Height;
   mnuPoint:=ClientToScreen(mnuPoint);
   pMnu.PopUp(mnuPoint.X,mnuPoint.Y);
end;


Látható, hogy az X koordinátába a menügombunk bal oldali pozíciójának az értéke kerül, de ehhez hozzá adok még kettőt, mert így nekem jobban néz ki, amikor a menü megjelenik. Az Y koordináta kiszámításához pedig a gomb felső szélének a pozíciójára valamint a gomb magasságára van szükségünk, e kettő érték összege megadja a gomb alsó szélének pozícióját. És van itt még valami. Mi lehet ez a ClientToScreen függvény? Nos, ez a TControl komponens egy függvénye és azt csinálja, hogy átalakítja nekünk a kapott koordinátákat, melyek a kliens relatív koordinátái, a képernyőn levő abszolút koordinátákká. Ami nagyjából annyit tesz, hogy kiderül a képernyőhöz viszonyítva hol helyezkedik el a gombunk bal alsó sarka. És azért van erre az értékre szükség, mert az előugró menünk popup propertyje ezeket a koordinátákat várja.
Már majdnem készen is vagyunk a dologgal, még a PopupMenu komponensünk egy eseményét állítsuk be, hogy a hatás még inkább kielégítő legyen. Ehhez állítsuk be az előugró menü onClose eseményére ugyan azt az eseménykezelőt, amit a gombnál arra használtunk, hogy lekezelje azt az eseményt, amikor a kurzor elhagyja a gombot. És készen is vagyunk.

Hellyel-közzel ugyan ez videón:


Alkalmasint majd készítek egy jobb videót a dologról, amiben az összes, a bejegyzésben szereplő elem látható lesz. A videót jobb minőségben is el lehet érni a youtubeon, ha itt a lejátszón a kis youtube ikonra kattintunk. Majd, már a youtubeon, a lejátszón levő kis fogaskerék gombra bökve vagy a 720p, vagy az 1080p felbontást válasszuk.