2010-07-21 10 views
12

Po uruchomieniu akcji, "nadawca" jest zawsze samym działaniem. Zwykle jest to najbardziej przydatne, ale czy w jakiś sposób można się dowiedzieć, kto uruchomił zdarzenie onexecute akcji?Jak mogę sprawdzić, kto wywołał akcję w Delphi?

Przykład

Powiedzmy masz formularz z następującymi:

  • 2 przyciski, zwany Button1 i Button2
  • 1 TAction nazywa actDoStuff

tego samego działania jest przypisany do obu przycisków. Czy mogę pokazać, który przycisk kliknąłem?

Example.dfm

object Form1: TForm1 
    object Button1: TButton 
    Action = actDoStuff 
    end 
    object Button2: TButton 
    Action = actDoStuff 
    Left = 100 
    end 
    object actDoStuff: TAction 
    Caption = 'Do Stuff' 
    OnExecute = actDoStuffExecute 
    end 
end 

Example.pas

unit Example; 
interface 
uses Windows, Classes, Forms, Dialogs, Controls, ActnList, StdCtrls; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    Button2: TButton; 
    actDoStuff: TAction; 
    procedure actDoStuffExecute(Sender: TObject); 
    end; 

var 
    Form1: TForm1; 

implementation  
{$R *.dfm} 

procedure TForm1.actDoStuffExecute(Sender: TObject); 
begin 
    ShowMessage('Button X was clicked'); 
end; 

end. 

Jedynym rozwiązaniem widzę w tej chwili jest, aby nie używać właściwości działania przycisków, ale o eventhandler dla każdego przycisku i wywołanie stamtąd actDoStuffExecute(), ale tego rodzaju całkowicie przeciwstawia się celowi używania akcji.

Nie chcę mieć dedykowanego działania dla każdej osobnej kontroli. Powyższy przykład to uproszczona wersja problemu, z którym mam do czynienia. Mam menu ze zmienną liczbą pozycji menu (nazw plików), a każdy element menu zasadniczo musi robić to samo, z wyjątkiem ładowania innego pliku. Posiadanie akcji dla każdego elementu menu byłoby trochę głupie.

+0

Zobacz parametr "Nadawca: TObject"? ... To jest wstępnie wypełnione dla Ciebie ... Spróbuj rzucić okiem na Nadawcę w swojej funkcji. – Fosco

+0

Tak, ale w powyższym przykładzie 'actDoStuff' będzie nadawcą. Chcę wiedzieć, czy naciśnięto przycisk 1 lub przycisk 2. –

Odpowiedz

18

Spróbuj użyć ActionComponent właściwość:

ShowMessage((Sender as TAction).ActionComponent.Name); 

Używanie tego mam "Button1" i "Button2" gdy klikam pierwszy i drugi przycisk odpowiednio .

+9

Uwaga: co się stanie, gdy czynność zostanie wywołana przez skrót klawiaturowy? –

+0

Świetnie, dokładnie tego, czego szukałem! –

0

Ok, w międzyczasie Chyba znalazłem skutecznego rozwiązania ..

mogę mieć wszystkie elementy sterujące korzystają z tego samego działania; Muszę tylko zastąpić ich program obsługi zdarzeń OnClick i potrzebuję tylko jednego programu obsługi dla nich wszystkich.

ja nadal jestem zainteresowany, aby wiedzieć, czy to możliwe, aby dowiedzieć się, jakie kontrola wywołał akcję, ale dla mojego bieżącej aplikacji używam rozwiązanie, które jest podobny do poniższego kodu:

unit Example; 

interface 

uses 
    Windows, Classes, Forms, Dialogs, Controls, ActnList, StdCtrls; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    Button2: TButton; 
    actDoStuff: TAction; 
    procedure actDoStuffExecute(Sender: TObject); 
    procedure ButtonClick(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.actDoStuffExecute(Sender: TObject); 
begin 
    ShowMessage('Button '+TControl(Sender).Name +' was clicked') 
end; 

procedure TForm1.ButtonClick(Sender: TObject); 
begin 
    actDoStuffExecute(Sender) 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    Button1.OnClick := ButtonClick; 
    Button2.OnClick := ButtonClick 
end; 

end. 
+1

Jeśli piszesz programy obsługi zdarzeń OnClick w przyciskach, uprzejmie odłącz całkowicie od akcji. Poważnie! –

+0

Potrzebujesz linku z akcją, jeśli chcesz włączyć/wyłączyć wszystkie przyciski w jednym miejscu (program obsługi onupdate akcji lub akcji). Ty jednak musisz zachować ostrożność, ponieważ program obsługi onclick może zostać nadpisany przy każdej aktualizacji akcji. –

8

wiedząc, co Przycisk uruchamia rodzaj akcji w stosunku do punktu użycia akcji - akcja może zostać wywołana kliknięciem przycisku lub kliknięciem menu lub dowolną liczbą innych działań użytkownika. Istnieją działania mające na celu ujednolicenie zarządzania stanami włączania/wyłączania i obsługi klikania między przyciskami i menu.

Jeśli chcesz wiedzieć, który przycisk uruchomił akcję, ponieważ chcesz wykonać nieco inną operację lub "smakować" operację w inny sposób, to być może ta metoda nie jest właściwym rozwiązaniem dla tego, co chcesz zrobić.

+0

Proponujesz tutaj, że ta metoda nie jest właściwym rozwiązaniem, ale nie proponujesz alternatywy. Wyłączanie akcji na całym świecie jest najłatwiejszym sposobem na wyłączenie funkcji programu, gdy nie można ich wykonywać, i często potrzebujesz nieco innej funkcjonalności w różnych oknach, więc wdrożenie własnego rozwiązania nie jest zbyt praktyczne, zamiast korzystania z gotowych rozwiązań, takich jak np. TAction. Wyłączenie funkcji programu poprzez wyłączenie akcji często wymaga minimalnej konserwacji później (automatycznie wyłącza wszystkie odpowiednie menu, paski narzędzi itp. We wszystkich oknach, które jej używają). – Coder12345

+2

Jestem wielkim orędownikiem Taktowania. Sugeruję, że projekt, który ma na celu zmianę zachowania zdarzenia na podstawie którego elementu UI użyto do wystrzelenia zdarzenia, jest wadliwym projektem. Używaj TAKACJI do równomiernego obsługiwania akcji bez względu na wyzwalacz. Jeśli naprawdę potrzebujesz czegoś innego, niż kliknięcie przycisku zamiast elementu menu, stwórz inną akcję. – dthorpe

0

ustawić Tag z przycisków jako 1, 2, ... etc, a następnie:

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    Button1.OnClick := ButtonClick; 
    Button2.OnClick := ButtonClick; 
end; 

procedure TForm1.ButtonClick(Sender: TObject); 
begin 
    if Sender is TButton then 
    begin 
    Caption := 'Button: ' + IntToStr(TButton(Sender).Tag); 
    end; 
end; 
3

Zamiast działań, wystarczy użyć zdarzenie click. Ustaw wszystkie przyciski, aby korzystać z tego samego modułu obsługi zdarzeń. Idealnie NIE jest nazwana po pierwszym przycisku (możesz zmienić jej nazwę).

Oto kod:

Procedure TMyForm.DestinationButtonClickHandlerThing(Sender: TObject); 
begin 
    if Sender = Btn_ViewIt then 
    begin 
    // View It 
    end 
    else if Sender = Btn_FaxIt then 
    begin 
    // Fax It 
    end 
    else if Sender = Btn_ScrapIt then 
    begin 
    // Scrap It 
    end 
    else 
    .... // error 
    ... 
end; 
+0

Korzystanie z programów do obsługi zdarzeń OnClick, nawet jeden moduł obsługi dla kilku przycisków, oznacza utratę możliwości włączania/wyłączania itd. W jednym miejscu (procedura obsługi onupdate akcji lub akcji). Bez tego nie łączysz ich z akcją. Przypisanie akcji spowoduje jednak nadpisanie procedury obsługi onclick, dlatego należy ją zresetować dla wszystkich zaangażowanych przycisków i ewentualnie wykonać to za każdym razem, gdy zmieni się coś w akcji. –

+0

Oczywiście jest to ** właściwa odpowiedź! ** Dlatego właśnie jest "Nadawca". – Vassilis

1

Istnieją sytuacje, w których to samo działanie powinno dotyczyć podobnych kontroli. Problem z

ShowMessage((Sender as TAction).ActionComponent.Name); 

jest to, że gdy akcja jest wywoływana przez menu kontekstowego powiedzmy, masz nazwy użytkownika menu podręcznego. Możesz użyć:

procedure TMyForm.actMyActionExecute(Sender: TObject); 
var 
    LMyControl: TMyControl; 
begin 
    if Screen.ActiveControl.Name = 'MyControl1' then 
    LMyControl = Sender as TMyControl 
    else 
    Exit; 
    // Use the local variable for whatever needed 
end; 
Powiązane problemy