Delphi - Parametr Sender
Sat, 25 January 2003
Wstęp
Witam! Na pewno zastanawialiście się kiedyś, pisząc kod powstającego programu, nad uniwersalnym zastosowaniem procedur, a właściwie zdarzeń jakie wywoływane są przy naciskaniu przycisku przez użytkownika, czy wciśnięciu jakiegoś klawisza na klawiaturze. Zapewne męczyło was ciągłe powtarzanie tych samych instrukcji w dwóch różnych procedurach. W tym artykule chciałbym przedstawić sposób na ominięcie rozwiązania jakim jest kopiowanie kodu z procedury do procedury, nawet jeżeli kody te nieco się różnią.
Nieco więcej o procedurach
Procedura to po prostu część kodu źródłowego odpowiedzialna za wykonanie określonego zadania. Nikt nie powiedział, że z procedury może korzystać tylko jeden komponent. Dlaczego więc wszyscy, z nielicznymi wyjątkami, tak postępują? Być może łatwiej jest kopiować kod źródłowy jednej procedury i wklejać go w nieco zmienionej formie do drugiej procedury, jednak zawsze musisz pamiętać o tym, o czym wiele programistów w dzisiejszych czasach zapomina, że należy zawsze oszczędzać dostępną pamięć oraz pisać kod przejżyście. Prawdą jest to, że w dzisiejszych czasach pół giga RAM'u nie jest już nowością, a dyski rozrastają się w swych rozmiarach przeciętnie do 120 Giga. Nie jest to jednak argument za tym iż program może wykonywany być niedbale. W każdej procedurze należy używać optymalnych typów dla zmiennych. Jeśli nie potrzeba aż tyle pamięci ile oferuje typString, skorzystaj zPChar, który skonstruowany został tak, iż zabiera mniej pamięci. Przy małych programach nie znaczy to jeszcze tak wiele, ale mogę sobie tylko wyobrazić, jak wyglądałaby "nieco" większa aplikacja. Na pewno wielu z Was myśli sobie pewnie oAPI. Tak, sztuka pisania wWinAPIjest bardzo przydatną umiejętnością, a programiści potrafiący pisać w czystymAPIna pewno więcej uwagi przywiązują do przydzielania pamięci. Ale póki co wróćmy na ziemię, doAPIjeszcze nam daleko :). Przestanę więc nudzić o pamięci i bierzemy się do roboty zwracając uwagę na powyższy tekst ;) Zanim jednak zaczniemy, przypatrzcie się konstrukcji typowej procedury obsługującej zdarzenieOnClick:
procedure TForm1.Button1Click(Sender: TObject);
begin
end;
Sender - z czym to się je...
Procedury tego typu posiadają parametr -SendertypuTObject. ParametrSenderzawiera informację o komponencie który wywołał procedurę. Możemy więc korzystać z tej samej procedury, wywoływanej przez np. dwa inne obiekty (komponenty). Można to zrobić na trzy sposoby. Pierwszym sposobem jest możliwość wykorzystania funkcjiSender.ClassName()zwracającej wartość typuShortStringz nazwą klasy obiektów, który wywołał procedurę. Inaczej można to zapisać stosując funkcjęSender.ClassNameIs(Name: String), która zwraca wartość True gdy podamy prawidłową nazwę klasy obiektu, który wywołał to zdarzenie. Trzecim sposobem jest możliwość zastosowania operatorais. Prześledźmy te trzy metody na przykładach.
Otwórz Delphiego, na formie umieść przycisk i etykietę. Oba komponenty znajdują się na palecieStandardpod nazwamiButton(przycisk) iLabel(etykieta). Na formie umieszczasz je klikając na ikonę danej kontrolki na palecie, następnie klikając na formularz. Teraz dwukrotnie klikasz na przycisk. Delphi przenosi Cię do edytora kodu. W nowo utworzonej procedurzeTForm1.Button1Click(Sender: TObject)wpisujecie:
If Sender.ClassName = 'TButton' Then
ShowMessage('Nacisnąłeś przycisk')
else If Sender.ClassName = 'TLabel' Then
ShowMessage('Nacisnąłeś etykietę, bardzo mądrze ;)');
Przenieś się do formy (F12), zaznacz obiektLabel1(pojedynczym kliknięciem), a wInspektorze obiektów(Object Inspekotr - F11), na zakładceEvents, odnajdź zdarzenieOnClicki kliknij obok w białym polu. Powinna rozwinąć się lista, z której wybieramyButton1Click. W ten sposób komponentLabelbędzie korzystał z procedury wywoływanej przy naciśnięciu przycisku. Uruchom program (F9). Kliknij na przycisk, następnie na etykietę. Informacja w komunikatach zmienia się zależnie od tego na który obiekt klikniecie. Proste. Teraz podam przykłady kodu w trzech różnych sposobach.
I sposób - ClassName()
If Sender.ClassName = 'TButton' Then
ShowMessage('Nacisnąłeś przycisk')
else If Sender.ClassName = 'TLabel' Then
ShowMessage('Kliknąłeś na etykietę - bardzo mądrze ;)');
II sposób - ClassNameIs(Name: String)
If Sender.ClassNameIs('TButton') Then
ShowMessage('Nacisnąłeś przycisk')
else If Sender.ClassNameIs('TLabel') Then
ShowMessage('Kliknąłeś na etykietę - bardzo mądrze ;)');
III sposób - operator is
If Sender is TButton Then
ShowMessage('Nacisnąłeś przycisk')
else If Sender is TLabel Then
ShowMessage('Kliknąłeś na etykietę - bardzo mądrze ;)');
To który sposób wybierzecie, zależy tylko od was, wszystkie działają równie sprawnie. Osobiście używam III - najmniej do pisania ;)
Myślę, że zrozumieliście przykłady, jeszcze tylko małe objaśnienie.
procedure TForm1.Button1Click(Sender: TObject);
begin
If Sender is TButton Then
ShowMessage('Nacisnąłeś przycisk')
else If Sender is TLabel Then
ShowMessage('Kliknąłeś na etykietę - bardzo mądrze ;)');
end;
Pierwsza linijka kodu procedury: JeśliSenderjestTButton'em To
Druga linika: Pokaż komunikat o treści "Nacisnąłeś przycisk"
Trzecia linijka: w przeciwnym wypadku, jeśliSenderjestTLabel'em To
Czwarta linijka: Pokaż komunikat o treści "Kliknąłeś na etykietę - bardzo mądrze ;)"
Zakończenie
ParametrSenderzawiera nazwę klasy np.TButton(typowe dla klas jest użycie przedrostka T). Badając tę nazwę za pomocą instrukcji warunkowych możemy dojść do tego, czy użytkownik kliknął Przycisk czy Etykietę.
Myślę, że przydadzą Wam się te wskazówki przy pisaniu nowych programów. Pozdrawiam i życzę udanych projektów!





Podobne artykuly:
- KillAd
- Delphi - Budowa modułu
- Delphi - Piszemy własny odtwarzacz multimedialny
- Delphi - Piszemy prosty edytor tekstu
- Delphi - Jak pisać?
- Delphi - Pobieranie plików z Internetu
- Delphi - Potęga możliwości ShellExecute()
Skomentuj
Komentarze czytelników
-
- Robert
- Tue, 24 February 2015, 13:57
- Dzięki, napisałem program na którego formie jest 200 BitBtn i chciałem je zaprogamować za pomocą 1 procedury, jednak nie chciałem programować każdej z osobna: i oto jest rozwiązanie :D
-
- danonek
- Tue, 21 May 2013, 19:59
- Można też zrobić tak TButton(Sender) Jeszcze chciałem dodać że zamiast operować na nazwach komponentów (stringach) lepiej jest zapisać numerek do wartości Tag komponentu. Odwołanie się do Integer'a jest dużo szybsze niż operowanie na stringach :)
-
- pytacz
- Wed, 23 June 2010, 11:14
- A jak zmienie nazwe button'a tonie działa!!
Odp: ...no tak. Nie można stosować tego kodu jeśli się nie wie o co w nim chodzi. Owszem jeśli zmienisz nazwę na taką która ma mniej lub więcej liter od tej dla której pisany był kod to ów kod nie będzie działał. Bo jak pewnie wiesz, wycina on fragment będący numerem przycisku, zaczynając od 7-ego znaku.
-
- pytacz
- Sun, 31 January 2010, 15:10
- A jak masz trzy klawisze Button1..2 i 3 to jeśli dowiemy się że jest to klasa TButton to gdzie odczytać numer buttona?
Odp: Cóż... Numer buttona nie jest zapisywany osobno. Dlatego należy go wyciągnąć z nazwy przycisku jeśli jest koniecznie potrzebny. Można to zrobić w następujący sposób:
Na formularzu kładziemy kilka przycisków, którym przypisujemy poniższą procedurę obsługi zdarzenia:
procedure TForm1.Button1Click(Sender: TObject);
var
numer_buttona : integer;
begin
if Sender is TButton Then
begin
numer_buttona := StrToInt(Copy(TButton(Sender).Name,7,Length(TButton(Sender).Name)-5-1));
ShowMessage(IntToStr(numer_buttona));
end;
end;