【问题标题】:Delphi notify events from interfacesDelphi 从接口通知事件
【发布时间】:2016-10-24 03:39:50
【问题描述】:

我又来这里是为了一个关于通知的问题。 我有followinf接口:

unit TblInterface;

interface

uses
  System.TypInfo, Vcl.Forms, RzPanel, Winapi.Windows, Winapi.Messages,
  UserMessages, Vcl.Dialogs, Vcl.Controls;

type

  TFrameType = (ftList, ftDetail);

  TFrameInfo = record
    Frame: TFrame;
    FrameType: TFrameType;
  end;

  TFrameClass = class of TFrame;

  ITabella = interface
  ['{D21924F9-BB41-493B-B06D-0908C0CA73D8}']
    function GetCurrentActiveFrameType: TFrameInfo;
    procedure CreateLstFrame(ParentForm: TForm; Frame: TFrameClass);
    procedure CreateDtlFrame(ParentForm: TForm; Frame: TFrameClass);
    procedure DestroyLstFrame;
    procedure DestroyDtlFrame;
    procedure BringFrameToFront(FrameType: TFrameType);
    procedure OnDoubleClick;
  end;

  TTabella = class(TInterfacedObject, ITabella)
  private
    FLst: TFrame;
    FDtl: TFrame;
    ActFrame: TFrameInfo;
    function GetCurrentActiveFrameType: TFrameInfo;
    procedure CreateLstFrame(ParentForm: TForm; Frame: TFrameClass);
    procedure CreateDtlFrame(ParentForm: TForm; Frame: TFrameClass);
    procedure DestroyLstFrame;
    procedure DestroyDtlFrame;
    procedure BringFrameToFront(FrameType: TFrameType);
    procedure OnDoubleClick;
  end;

implementation

{ TTabella }

{ Creazione frame lista }
procedure TTabella.CreateLstFrame(ParentForm: TForm; Frame: TFrameClass);
begin
  FLst := Frame.Create(ParentForm);
  FLst.Parent := ParentForm;
  FLst.Align := alClient;
end;

{ Creazione frame dettaglio }
procedure TTabella.CreateDtlFrame(ParentForm: TForm; Frame: TFrameClass);
begin
  FDtl := Frame.Create(ParentForm);
  FDtl.Parent := ParentForm;
  FDtl.Align := alClient;
end;

{ Distruzione frame lista }
procedure TTabella.DestroyLstFrame;
begin
  FLst.Free;
end;

{ Distruzione frame dettaglio }
procedure TTabella.DestroyDtlFrame;
begin
  FDtl.Free;
end;

{ Porta in primo piano il frame richiesto }
procedure TTabella.BringFrameToFront(FrameType: TFrameType);
begin
  case FrameType of
    ftList: begin
      FLst.BringToFront;
      ActFrame.Frame := FLst;
    end;
    ftDetail: begin
      FDtl.BringToFront;
      ActFrame.Frame := FDtl;
    end;
  end;
  ActFrame.FrameType := FrameType;
end;

{ Restiruisce il frame attivo }
function TTabella.GetCurrentActiveFrameType: TFrameInfo;
begin
  Result := ActFrame;
end;

procedure TTabella.OnDoubleClick;
begin
  BringFrameToFront(ftList);
end;

end.

在界面中,我创建了两个框架,用于显示一些数据库表的列表和详细信息。 我创建的表单界面,在正确的框架前面并销毁它。 此时我需要将事件通知给创建的框架,但我不知道如何完成这项工作。 例如,我需要通知详细框架在列表框架中按下了一个按钮。

我怎样才能完成这项任务?

【问题讨论】:

  • 您编写“我创建的表单界面,将其放在正确的框架前面并销毁它”。你什么时候毁掉它?在 OnDoubleClick 中?从您的代码中不清楚。框架是否超出您的控制?你管理他们吗?如果是这样,您可以子类化一个 TFrame 并添加一个由 ListFrame 调用的方法
  • 我有两个用于任何表格的框架:一个用于列表记录,一个用于显示记录详细信息。它们是在用户选择要管理的表时动态创建的,所以我不知道框架中包含什么。当用户关闭承载框架的表单时使用 Destory
  • 如果我理解正确,用户选择一个表,并获取列表框架,然后他或她在列表框架中选择一条记录并在详细信息框架中查看详细信息,对吗?跨度>
  • 是的,约翰,你是对的!

标签: delphi interface


【解决方案1】:

至少有两种方法可以做到这一点。 首先,我会推荐使用另一个接口;第二种方法是使用我们处理事件的对象过程。 让我们把手放在面糊里!

  1. 在 ITabella 之前使用要通知的方法声明一个新接口

    IProcessor=Interface
    {Shift+Ctrl+G}
    procedure Select; 
    procedure Search();
    

一个非常基本的例子来处理 Click 事件和相同的 Search 事件,调用框架 ftList 然后我们在后代类中实现方法

TProcessTabellaPeople=class(TnterfacedObject,IProcessor)
procedure Select; virtual; abstract;
procedure Search; virtual; abstract;
..
end;
TProcessTabellaCustomer=class(TProcessTabellaPeople)
procedure Select; virtual; abstract;
procedure Search; virtual; abstract;
..
end;
{remove abstract clause to implement the methods using Shift+Ctrl+C,
or keep them to late binding in descendant Classes}

在 ITabella 中添加对 IProcessor 的引用

ITabella = interface
  ['{D21924F9-BB41-493B-B06D-0908C0CA73D8}']
    fProc:IProcessor ;
    function GetCurrentActiveFrameType: TFrameInfo;
    procedure CreateLstFrame(ParentForm: TForm; Frame: TFrameClass);
    procedure CreateDtlFrame(ParentForm: TForm; Frame: TFrameClass);
    procedure DestroyLstFrame;
    procedure DestroyDtlFrame;
    procedure BringFrameToFront(FrameType: TFrameType);
    procedure OnDoubleClick;
    **procedure clickSelect;**
    **property Proc:IProcessor read fProc write fProc;**
  end;

为相应的 IProcessor 方法传播 TTabela.OnDoubleClick

procedure TTabella.OnDoubleClick;
begin
  BringFrameToFront(ftList);
  If Assigned(fProc) then Proc.Search(); {Call IProcessorMethod}
end;
procedure TTabella.ClickSelect;
begin
If Assigned(fProc) then Proc.Select(); {Call IProcessorMethod}
end;

正确使用界面 在创建 TTabela 时传递处理器,例如

Var Tabella1: ITabella;
Begin
Tabela1:=TTabela.create();
Tabela1.proc:=TProcessor
end;

此时我会建议你实现构造函数 create 传递 IProcessTabellaCustomer.create; {不需要使用接口 vartype 释放}

对于TButton 的 onClick 这样做:

Tabela1.ClickSelect;
  1. 对象内容的使用过程或TNotify类方法 你可以像这样声明 ClassMethods

    TSelectMethod = procedure(name:String; Sender:TObject) of object;
    ITabella = interface
    ['{D21924F9-BB41-493B-B06D-0908C0CA73D8}']
    property Select:TSelectMethod read fSelect write fSelect;
    property Search:TNotifyEvent;
    end;
    

注意TNotifyEvent 标志

TNotifyEvent= procedure (Sender:TObject)of Object;

虽然在表单中创建了一些具有相同事件处理程序标志的方法,

procedure TForm1.btnSearchClick(Sender:TObject)of Object; //*the same sign of TButtonClick, for example*
begin
end;
procedure TForm1.ShowSelected(name:String; Sender:TObject) of object;//*customized sign with new parameters
begin
showmessage(Format('Selected name%s',[name]));
end;

您可以在运行时为字段的过程归因

Tabella1:=TTabela.create();
Tabella1.Select:=Form1.btnSelectClick;
Tabella1.Search:=Form1.btnSearchClick;

【讨论】:

  • 第二种方式,属性“Select:TSelectMethod read fSelect write fSelect;”给出编译器错误(应为 E2168 字段或方法标识符),并且不允许在接口处使用字段。我想这是一个模拟示例,而不是真实示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-13
  • 1970-01-01
  • 2015-11-06
  • 2019-08-31
  • 1970-01-01
  • 1970-01-01
  • 2010-11-28
相关资源
最近更新 更多