2010-07-21 3 views
12

Wenn eine Aktion sogar ausgelöst wird, ist der "Absender" immer die Aktion selbst. Normalerweise ist das am nützlichsten, aber ist es irgendwie möglich herauszufinden, wer das einmalige Ereignis der Aktion ausgelöst hat?Wie kann ich sehen, wer in Delphi eine Aktion ausgelöst hat?

Beispiel

Angenommen, Sie haben ein Formular mit den folgenden:

  • 2 Knöpfe, genannt Button1 und Button2
  • 1 TAction actDoStuff
  • genannt

Die gleiche Aktion ist beiden Tasten zugewiesen. Ist es möglich zu zeigen, auf welchen Knopf ich geklickt habe?

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. 

Die einzige Lösung, die ich im Moment sehe, ist nicht die Aktion Eigenschaft von Tasten zu bedienen, aber einen Eventhandler mit für jede Schaltfläche, und Aufruf von actDoStuffExecute() von dort, aber diese Art von trotzt den ganzen Zweck der Verwendung von Aktionen an erster Stelle.

Ich möchte auch keine dedizierte Aktion für jede einzelne Steuerung haben. Das obige Beispiel ist eine vereinfachte Version des Problems, dem ich gegenüberstehe. Ich habe ein Menü mit einer variablen Anzahl von Menüpunkten (Dateinamen), und jedes Menüelement muss grundsätzlich dasselbe tun, außer dass eine andere Datei geladen wird. Aktionen für jeden Menüpunkt zu haben wäre ein bisschen albern.

+0

Sehen Sie, dass "Sender: TObject" -Parameter? ... Das ist für Sie bereits ausgefüllt ... Werfen Sie einen Blick auf Sender in Ihrer Funktion. – Fosco

+0

Ja, aber im obigen Beispiel wäre'ActDoStuff' der Absender. Ich möchte wissen, ob Button1 oder Button2 gedrückt wurde. –

Antwort

18

Versuchen Sie, die ActionComponent Eigenschaft mit:

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

Mit diesem I "Button1" und "Button2", wenn ich die erste und die zweite Schaltfläche klicken bzw. .

+9

Vorsicht: Was passiert, wenn die Aktion durch eine Tastenkombination ausgelöst wird? –

+0

Großartig, genau das, was ich gesucht habe! –

0

Ok, in der Zwischenzeit Ich glaube, ich eine praktikable Lösung gefunden ..

kann ich alle Steuerelemente die gleiche Aktion verwenden; Ich muss nur ihren OnClick-Event-Handler außer Kraft setzen, und ich brauche nur einen einzigen Handler für alle von ihnen.

Ich bin immer noch daran interessiert zu wissen, ob es möglich ist, die Steuerung der Aktion ausgelöst, um herauszufinden, aber für meine aktuelle Anwendung ich eine Lösung bin mit, die unten an den Code ähnlich ist:

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

Wenn Sie in den Schaltflächen OnClick-Ereignishandler schreiben, heben Sie die Verknüpfung der Aktion vollständig auf. Ernst! –

+0

Sie benötigen die Verknüpfung mit der Aktion, wenn Sie alle Schaltflächen an einer Stelle aktivieren/deaktivieren möchten (der onupdate-Handler der Aktion oder der Aktionsliste). Sie müssen jedoch darauf achten, dass der onclick-Handler bei jeder Aktualisierung der Aktion überschrieben wird. –

8

Zu wissen, was Die Schaltfläche löste die Aktion aus, die gegen den Punkt der Verwendung von Aktionen gerichtet ist - eine Aktion kann durch einen Klick auf die Schaltfläche oder einen Menüklick oder eine beliebige Anzahl anderer Benutzeraktivitäten ausgelöst werden. Es gibt Aktionen, um die Statusverwaltung von enable/disabled zu vereinheitlichen und auf die Handhabung zwischen Schaltflächen und Menüs zu klicken.

Wenn Sie wissen möchten, welche Schaltfläche die Aktion ausgelöst hat, weil Sie eine etwas andere Operation ausführen möchten, oder die Operation anders "aromatisieren", dann ist TAction möglicherweise nicht die richtige Lösung für das, was Sie tun möchten.

+0

Sie schlagen hier vor, dass TAction nicht die richtige Lösung ist, aber Sie schlagen keine Alternative vor. Die globale Deaktivierung von Aktionen ist die einfachste Möglichkeit, Programmfunktionen zu deaktivieren, wenn sie nicht ausgeführt werden können. Oftmals benötigen Sie leicht unterschiedliche Funktionen über verschiedene Fenster hinweg. Daher ist die Implementierung einer eigenen Lösung nicht wirklich praktisch, anstatt vorgefertigte Lösungen wie TAction zu verwenden. Das Deaktivieren der Programmfunktion durch Deaktivieren der Aktion erfordert oft später die geringste Wartung (es deaktiviert alle relevanten Menüs, Symbolleisten usw. automatisch in allen Fenstern, die es verwenden). – Coder12345

+2

Ich bin ein großer Befürworter von TAction. Was ich vorschlage, ist, dass ein Design, das versucht, das Verhalten eines Ereignisses zu ändern, basierend darauf, welches UI-Element zum Auslösen des Ereignisses verwendet wurde, ein fehlerhaftes Design ist. Verwenden Sie TActions, um Aktionen unabhängig vom Trigger einheitlich zu behandeln. Wenn Sie wirklich etwas anderes brauchen, wenn die Schaltfläche anstelle des Menüelements angeklickt wird, erstellen Sie eine andere Aktion. – dthorpe

0

stellen Sie den Tag der Tasten 1, 2, ... usw. und dann:

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

Statt Aktionen, nur ein Click-Ereignis verwenden. Stellen Sie alle Schaltflächen so ein, dass sie denselben Ereignishandler verwenden. Idealerweise NICHT nach der ersten Schaltfläche benannt (Sie können sie umbenennen).

Hier ist der Code:

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

Die Verwendung von OnClick Event-Handlern, sogar ein einzelner Handler für mehrere Schaltflächen, bedeutet, die Fähigkeit zum Aktivieren/Deaktivieren usw. an einem Ort zu verlieren (der onupdate-Handler der Aktion oder der Aktionsliste). Das ist _unless_ Sie kombinieren sie mit einer Aktion. Durch das Zuweisen einer Aktion wird der onclick-Handler jedoch überschrieben, sodass Sie ihn für alle beteiligten Schaltflächen zurücksetzen müssten, und zwar möglicherweise jedes Mal, wenn Sie etwas an der Aktion ändern. –

+0

Natürlich ist das die richtige Antwort! Deshalb ist 'Sender' da. – Vassilis

1

Es gibt Situationen, in denen dieselbe Aktion für ähnliche Steuerelemente gelten sollte. Das Problem mit

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

ist, dass, wenn sich die von einem etwa Popup-Menü aufgerufen wird, können Sie den Namen des Pop-up-Menü. Sie könnten verwenden:

Verwandte Themen