【问题标题】:Add function to event runtime向事件运行时添加函数
【发布时间】:2017-06-04 18:32:18
【问题描述】:
procedure TFormOrderAdd.DBEdit1DblClick(Sender: TObject);
var
  FormSelectEmp: TForm;
  SelectEmpDBGrid: TDBGrid;

begin
  FormSelectEmp := TForm.Create(Self);
  SelectEmpDBGrid :=  TDBGrid.Create(Self);
  SelectEmpDBGrid.Parent := FormSelectEmp;
  SelectEmpDBGrid.Align := alClient;
  SelectEmpDBGrid.DataSource := DMl.DataSourceViewEmpList;
  FormSelectEmp.ShowModal;
  SelectEmpDBGrid.OnDblClick := AddSelectedEmp;
  FormSelectEmp.Close;
end;

procedure TFormOrderAdd.AddSelectedEmp;
begin
  DBEdit1.Text := Dml.ADOQueryViewEmpList.FieldByName('ID').Text;
end;

如何将我的程序添加到 OnDblClick 事件? 我尝试分配,但编译器说:[dcc32 Error] OrderAdd.pas(66): E2010 Incompatible types: 'TNotifyEvent' and 'procedure, untyped pointer or untyped parameter'

【问题讨论】:

  • 与分配任何其他属性的方式相同,只需传递处理程序的名称。另外,那不应该在ShowModal 之前吗?你的程序是什么样的?你不能随便通过。
  • 我的意思是,AddSelectedEmp 看起来像什么?实际上,您似乎正在尝试 call 它而不是 assign 它。从中删除(Self)。请Edit您的问题提供这些完整的详细信息。
  • 您似乎没有提供适当的事件处理程序。它必须有正确的签名。 AddSelectedEmp 上面应该有 (Sender: TObject)。请在此处阅读:stackoverflow.com/a/42956399/988445
  • @димасоколов:可能是这样,但您仍然必须分配具有正确签名的程序。你的TFormOrder.AddSelectedEmp 应该是procedure TFormOrder.AddSelectedEmp(Sender: TObject);
  • @Victoria:当然,但我只是用另一条评论回应了他的评论。您的示例很好,但我尝试使用他的代码(使用他的过程名称)而不是您的代码来拼写它。我的印象是他不太明白这一点。

标签: delphi


【解决方案1】:

您必须在一个类中创建一个匹配的事件方法原型,然后将其分配给事件处理程序(对于TDBGrid 控件的OnDblClick 事件,它是TNotifyEvent),因此您可以编写例如:

type
  TForm1 = class(TForm)
    DBEdit1: TDBEdit;
    DBGrid1: TDBGrid;
  private
    procedure Form1Create(Sender: TObject);
    procedure MyGridDblClick(Sender: TObject);
  end;

implementation

procedure TForm1.Form1Create(Sender: TObject);
begin
  { it doesn't matter if you create the component at runtime,
    this is a common principle of assigning event methods at
    runtime - they just have to match the method prototypes }
  DBGrid1.OnDblClick := MyGridDblClick;
end;

procedure TForm1.MyGridDblClick(Sender: TObject);
begin
  { to access the grid instance in case more than one grid
    uses this handler you can use TDBGrid(Sender) or safer
    cast (Sender as TDBGrid) }
  DBEdit1.Text := TDBGrid(Sender).DataSource.Dataset.FieldByName('ID').Text;
end;

【讨论】:

  • 谢谢。现在我有新问题:如果我使用 ShowModal 而不是显示应用程序卡在 vcl 表单模块中:Application.HandleMessage;如果 Application.Terminated 然后 ModalResult := mrCancel else if ModalResult 0 then CloseModal;并且事件未触发
  • 正如在对您的问题的评论中提到的,您必须在调用 ShowModal 之前分配事件处理程序。并在此处阅读另一个答案以解决您遇到的另一个问题(这是正确的,但有点超出您所问的范围)。
  • AddSelectedEmp 执行后如何关闭表单?从 AddSelectedEmp 我无法访问表单。
  • 超出了这个问题的范围,但是如果分配的方法是同一个表单类的一部分(如示例所示),您可以在完成后简单地使用Close; 方法您在该事件处理程序中的工作(或将ModalResult 属性设置为您需要返回的任何模态结果)。如果您从另一个类分配处理程序方法,您通常可以使用它来到达放置网格的表单(GetParentForm(TControl(Sener))).Close; 或在事件方法中完成工作后分别设置ModalResult
  • 不工作,但我发现 Screen.ActiveForm.Close;它工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
  • 1970-01-01
  • 2021-11-29
  • 2022-01-15
  • 1970-01-01
相关资源
最近更新 更多