|
|
|
|
Példaprogram letöltése
8880 bájt
|
A CycleButton egy olyan komponens, amely alapvetően gombként működik, de leginkább egy ComboBox és egy TButton keresztezésének tűnik. Lényege, hogy minden egyes kattintásra megváltozik a felirata. A feliratok egy TStringList típusú property-ben vannak tárolva, és az éppen látható felirat sorszámát az ItemIndex property-ből lehet kiolvasni. Nincs legördülő lista, a feliratok sorban követik egymást.
A mellékelt példaprogram megnyitása előtt a CycleButton.pas-ban lévő komponenst telepítenie kell a Delphi alá.
Az új komponenst a TGraphicControl osztályból származtatjuk, mivel ennek megvan minden olyan tulajdonsága, amire nekünk szükségünk lesz. Létrehozunk egy CaptionList property-t, amiben a komponens feliratait tároljuk. Az ItemIndex property-ből kiolvasható, vagy ezen keresztül beállítható az aktuális felirat sorszáma.
Egy gomb-szerű komponens (pl. TButton, TRadioButton, TCheckBox, stb.) működésénél a következőket figyelhetjük meg:
- ha a bal egérgombot lenyomjuk a komponens fölött, és nyomva tartjuk, akkor a komponens "lenyomott" állapotban van;
- ha továbbra is nyomva tartjuk az egérgombot, de lehúzzuk az egeret, akkor normál állapotba kerül, de ha visszatoljuk, akkor megint lenyomott állapotba kerül;
- az OnClick esemény csak akkor következik be, ha a bal egérgombot felengedték miközben az egér a komponens fölött volt;
Ahhoz, hogy a mi komponensünk is ennek megfelelően működjön a következő eljárásokat kell használnunk:
procedure Click; override;
procedure MouseEnter(var Msg:TMessage); message CM_MOUSEENTER;
procedure MouseLeave(var Msg:TMessage); message CM_MOUSELEAVE;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
A Click eljárás automatikusan végrehajtódik, ha a bal egérgombbal kattintottak a komponensen. A MouseEnter és MouseLeave eljárások akkor hajtódnak végre, amikor az egér a komponens területe fölé ér, illetve elhagyja azt, miközben valamelyik egérgomb le van nyomva. A MouseDown és MouseUp akkor kerül végrehajtásra, amikor valamelyik egérgombot lenyomták, illetve felengedték.
Most nézzük meg egy kicsit részletesebben, hogy mi is történik ezekben az eljárásokban.
A Click eljárásban ellenőrizzük, hogy a komponens engedélyezve van-e. Ezt az FEnabled property-ből tudhatjuk meg. Ez után megnézzük, hogy a Shift billentyűt lenyomva tartják-e. Normális esetben a kattintásra mindig a következő, míg a Shift billentyű nyomva tartása mellett az előző felirat kerül megjelenítésre. Hozzáadjuk az FItemIndex változóhoz a megfelelő értéket (1 vagy -1), és ellenőrizzük, hogy egy olyan index-et kaptunk-e, ami valóban létezik. Ha a kapott index nagyobb, mint az utolsó felirat sorszáma, akkor az első, míg ha az index kisebb, mint 0, akkor az utolsó felirat lesz az aktív. Ha megvan a megfelelő index, akkor az ItemIndex property-t beállítjuk erre az értékre.
procedure TCycleButton.Click;
var d:integer;
begin
inherited;
if FEnabled then begin
if FShift then d:=-1 else d:=1;
inc(FItemIndex, d);
if FItemIndex>=FCaptionList.Count then FItemIndex:=0;
if FItemIndex<0 then FItemIndex:=FCaptionList.Count-1;
SetItemIndex(FItemIndex);
end;
end;
A MouseEnter eljárásban csak annyit teszünk, hogy az FMouseEnter logikai változó értékét igazra állítjuk. Ez a változó tudatja majd velünk, hogy az egér a komponens felett van.
A MouseLeave eljárásban az FMouseEnter változó értékét False-ra állítjuk.
A MouseDown eljárásban az FMouseDown logikai változó értékét True-ra állítjuk abban az esetben, ha a komponens engedélyezve van (FEnabled=True) és a bal egérgombot nyomták le, egyébként False. Ennek a változónak az értékéből tudjuk majd a kirajzolásnál, hogy az egérgombot lenyomták-e. Az FShift változó értéke akkor True, ha a Shift billentyűt is lenyomva tartják.
procedure TCycleButton.MouseDown;
begin
inherited MouseDown(Button, Shift, X, Y);
FMouseDown:=FEnabled and (Button=mbLeft);
FShift:=(ssShift in Shift);
Invalidate;
end;
A MouseUp eljárásban az FMouseDown változó értékét False-ra állítjuk.
procedure TCycleButton.MouseUp;
begin
inherited MouseDown(Button, Shift, X, Y);
FMouseDown:=False;
Invalidate;
end;
Ezzel az öt eljárással tehát biztosítottuk, hogy a komponensünk működése a fent leírtaknak meg fog felelni. Mindez rendben is volna eddig, de a komponenst meg is kell jeleníteni. A komponens kirajzolása a Paint eljárásban történik:
procedure TcycleButton.Paint;
var r:TRect;
w, h, xp, yp:integer;
dist:integer;
begin
inherited;
Lekérdezzük a komponens kliens területének méretét egy TRect típusú változóba.
A Color property-ben beállított színnel töröljük a komponens területét.
Canvas.Brush.Style:=bsSolid;
Canvas.Brush.Color:=Color;
Canvas.FillRect(r);
Ha a bal egérgomb le van nyomva, és az egér a komponens felett van, akkor a gombot benyomott állapotban jelenítjük meg, míg egyébként a normál nézetben. A dist változóban tároljuk azt az értéket, amennyivel balra illetve lefelé el fogjuk tolni a feliratot, az elválasztó vonalat valamint a fel-le nyilat.
if (FMouseDown and FMOuseEnter) then begin
dist:=1;
DrawEdge(Canvas.Handle, r, EDGE_SUNKEN, BF_RECT);
end else begin
DrawEdge(Canvas.Handle, r, EDGE_RAISED, BF_RECT);
dist:=0;
end;
A komponens bal szélén megjelenítünk egy fel-le nyilat. Ez a karakter a Marlett font "v" betűjén található. Itt jegyzem meg, hogy a Marlett font az a betűkészlet, amelyet a Windows is használ bizonyos komponensek megjelenítésénél (pl. RadioButton, CheckBox, a Form-ok gombjainak ábrái, stb.).
Canvas.Brush.Style:=bsClear;
Canvas.Font.Name:='MARLETT';
Canvas.Font.Style:=[];
Canvas.Font.Size:=10;
Ha a komponens nem engedélyezett, akkor a fel-le nyilat szürke, ellenkező esetben fekete színnel jelenítjük meg. A w és h változókban eltároljuk a karakter szélességét és magasságát, és ezek segítségével kiszámoljuk a koordinátákat. Az xp változóban az elválasztó vonal koordinátáját tároljuk.
if FEnabled then Canvas.Font.Color:=clBlack
else Canvas.Font.Color:=clBtnShadow;
w:=Canvas.TextWidth('v');
h:=Canvas.TextHeight('v');
xp:=Round(Height*0.8)+dist;
yp:=(Height div 2) - (h div 2)+dist;
Canvas.TextOut((xp div 2)-(w div 2), yp, 'v');
Megrajzoljuk az elválasztó vonalat, ami a fel-le nyíl és a komponens felirata között található.
r.Left:=xp-2;
r.Top:=r.Top+3;
r.Bottom:=r.Bottom-3;
DrawEdge(Canvas.Handle, r, EDGE_ETCHED, BF_LEFT);
Most már csak a komponens felirat megjelenítése van hátra.
Canvas.Font.Assign(Font);
yp:=(Height div 2) - (Canvas.TextHeight('Ty') div 2) + dist;
Canvas.TextOut(xp+4, yp, FCaption);
end;
|
Könyv
Ez a cikk megtalálható ebben a könyvben:
Delphi Software Offline 2001 évkönyv 280. oldal
Felhasználási feltételek
A Software Online szoftverfejlesztői magazin mindegyik cikke, minden megjelent képe, és egyéb publikált anyaga szerzői jog védelme alatt áll! Bármilyen formában történő másodlagos terjesztésük, közzétételük vagy felhasználásuk kizárólag a kiadó előzetes írásbeli engedélyével történhet!
|