artykuły

Delphi - Parametr Sender

20:47
Sat, 25 January 2003
Tekst objaśnia sposób wykorzystania parametru Sender przekazywanego do każdej procedury obsługującej zdarzenia. Artykuł pomaga zrozumieć funkcję przez niego pełnioną oraz opisuje sposób na jego wykorzystanie w celu optymalizacji długości i czytelności kodu.

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!

12345
Delphi - Parametr Sender Autor opinii: Czytelnicy, data przesłania: 5

Podobne artykuly:

Skomentuj

Aby zamieścić komentarz, proszę włączyć JavaScript - niestety roboty spamujące dają mi niezmiernie popalić.






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;
Dexter