2010-07-21 30 views
12

Khi một hành động thậm chí kích hoạt, "người gửi" luôn là hành động. Thông thường đó là cách hữu ích nhất, nhưng bằng cách nào đó nó có thể tìm ra ai đã kích hoạt sự kiện không thể thực hiện của hành động?Làm thế nào tôi có thể thấy ai đã kích hoạt một hành động trong Delphi?

Ví dụ

Hãy nói rằng bạn có một hình thức như sau:

  • 2 nút, gọi Button1Button2
  • 1 TAction gọi actDoStuff

Các hành động tương tự được gán cho cả hai nút. Có thể hiển thị nút nào tôi đã nhấp không?

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. 

Giải pháp duy nhất tôi nhìn thấy vào lúc này là không sử dụng bất động sản hoạt động của các nút, nhưng có một eventhandler cho mỗi nút và gọi hàm actDoStuffExecute() từ đó, nhưng loại đó ngăn cản toàn bộ mục đích của việc sử dụng các hành động ngay từ đầu.

Tôi cũng không muốn có hành động riêng cho từng điều khiển riêng biệt. Ví dụ trên là một phiên bản đơn giản của vấn đề mà tôi đang gặp phải. Tôi có một menu với một số lượng các mục menu (tên tập tin), và mỗi mục menu về cơ bản phải làm điều tương tự, ngoại trừ việc tải một tập tin khác. Có hành động cho mỗi mục trình đơn sẽ là một chút ngớ ngẩn.

+0

Hãy xem thông số "Người gửi: TObject" ... Đó là điền trước cho bạn ... Hãy thử xem Người gửi bên trong chức năng của bạn. – Fosco

+0

Vâng, nhưng trong ví dụ trên, 'actDoStuff' sẽ là người gửi. Tôi muốn biết liệu button1 hay button2 đã được nhấn. –

Trả lời

18

Hãy thử sử dụng ActionComponent tài sản:

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

Sử dụng này, tôi nhận được "Button1" và "Button2" khi tôi nhấp vào nút đầu tiên và thứ hai lần lượt là .

+9

Hãy coi chừng: Điều gì xảy ra khi hành động được kích hoạt bằng phím tắt? –

+0

Tuyệt vời, chính xác những gì tôi đang tìm kiếm! –

0

Ok, trong khi đó tôi nghĩ rằng tôi đã tìm được giải pháp khả thi ..

Tôi có thể có tất cả các điều khiển sử dụng cùng một hành động; Tôi chỉ cần ghi đè lên trình xử lý sự kiện OnClick của họ và tôi chỉ cần một trình xử lý duy nhất cho tất cả chúng.

tôi vẫn quan tâm để biết nếu nó có thể tìm ra các kiểm soát kích hoạt hành động, nhưng đối với ứng dụng hiện tại của tôi Tôi đang sử dụng một giải pháp đó là tương tự như mã bên dưới:

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

Nếu bạn đang viết trình xử lý sự kiện OnClick trong các nút, vui lòng bỏ liên kết khỏi hành động hoàn toàn. Nghiêm túc! –

+0

Bạn cần liên kết với hành động nếu bạn muốn bật/tắt tất cả các nút ở một nơi (trình xử lý cập nhật của tác vụ hoặc hành động). Bạn _do_ tuy nhiên cần phải cẩn thận vì trình xử lý onclick có thể bị ghi đè ở mỗi lần cập nhật cho hành động. –

8

Biết gì nút kích hoạt loại hành động đi ngược lại điểm của việc sử dụng các hành động - một hành động có thể được kích hoạt bằng cách nhấp vào nút hoặc nhấp vào menu hoặc bất kỳ số hoạt động nào khác của người dùng. Các hành động tồn tại để thống nhất việc quản lý trạng thái bật/tắt và xử lý nhấp chuột giữa các nút và menu.

Nếu bạn muốn biết nút nào đã kích hoạt hành động vì bạn muốn thực hiện một thao tác hơi khác hoặc hoạt động "hương vị" khác nhau, thì có lẽ TAction không phải là giải pháp phù hợp với những gì bạn muốn làm.

+0

Bạn đề xuất ở đây rằng TAction không phải là giải pháp đúng, nhưng bạn không đề xuất phương án thay thế. Việc vô hiệu hóa hành động trên toàn cầu là cách dễ nhất để vô hiệu hóa các chức năng của chương trình khi chúng không được phép thực hiện và khá thường xuyên, bạn cần một chức năng hơi khác nhau trên các cửa sổ khác nhau để thực hiện giải pháp riêng không thực sự thay vì sử dụng giải pháp được tạo sẵn như TAction. Vô hiệu hóa chức năng chương trình thông qua việc vô hiệu hóa hành động thường yêu cầu bảo trì ít nhất sau đó (nó vô hiệu hóa tất cả các menu, thanh công cụ có liên quan, vv tự động trong tất cả các cửa sổ sử dụng nó). – Coder12345

+2

Tôi là một người đề xuất rất lớn của TAction. Điều tôi gợi ý là thiết kế tìm cách thay đổi hành vi của một sự kiện dựa trên yếu tố giao diện người dùng nào được sử dụng để kích hoạt sự kiện là một thiết kế thiếu sót. Sử dụng TActions để xử lý các hành động thống nhất bất kể kích hoạt. Nếu bạn thực sự thực sự cần một cái gì đó khác nhau xảy ra khi nút được nhấp thay vì mục menu, sau đó tạo một hành động khác. – dthorpe

0

thiết lập các Tag của các nút như 1, 2, ... vv và sau đó:

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

Thay vì hành động, chỉ cần sử dụng một sự kiện click. Đặt tất cả các nút để sử dụng cùng một trình xử lý sự kiện. Lý tưởng nhất, KHÔNG được đặt tên sau nút đầu tiên (bạn có thể đổi tên nó).

Dưới đây là các mã:

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

Sử dụng trình xử lý sự kiện OnClick, thậm chí là một trình xử lý đơn cho nhiều nút, có nghĩa là mất khả năng bật/tắt tất cả chúng ở một nơi (trình xử lý cập nhật của hành động hoặc hành động). Đó là _unless_ bạn kết hợp chúng với một hành động. Gán một hành động sẽ ghi đè lên trình xử lý onclick tuy nhiên, vì vậy bạn sẽ phải đặt lại nó cho tất cả các nút có liên quan và có thể làm điều đó mỗi khi bạn thay đổi một cái gì đó trong hành động. –

+0

Tất nhiên đây là ** câu trả lời đúng! ** Đó là lý do tại sao 'Người gửi' ở đó. – Vassilis

1

Có những trường hợp mà cùng một hành động sẽ áp dụng cho các điều khiển tương tự. Sự cố với

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

là khi hành động được gọi bằng menu bật lên, bạn sẽ nhận được tên menu bật lên. Bạn có thể sử dụng:

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; 
Các vấn đề liên quan