program Project23;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
// Declare an event type. It looks a lot like a normal method declaration except
// it is suffixed by "of object". That "of object" tells Delphi the variable of this
// type needs to be assigned a method of an object, not just any global function
// with the correct signature.
TMyEventTakingAStringParameter = procedure(const aStrParam:string) of object;
// A class that uses the actual event
TMyDummyLoggingClass = class
public
OnLogMsg: TMyEventTakingAStringParameter; // This will hold the "closure", a pointer to
// the method function itself, plus a pointer to the
// object instance it is intended to work on.
procedure LogMsg(const msg:string);
end;
// A class that provides the required string method to be used as a parameter
TMyClassImplementingTheStringMethod = class
public
procedure WriteLine(const Something:string); // Intentionally using different names for
// method and params; Names don't matter, only the
// signature matters.
end;
procedure TMyDummyLoggingClass.LogMsg(const msg: string);
begin
if Assigned(OnLogMsg) then // tests if the event is assigned
OnLogMsg(msg); // calls the event.
end;
procedure TMyClassImplementingTheStringMethod.WriteLine(const Something: string);
begin
// Simple implementation, writing the string to console
Writeln(Something);
end;
var Logging: TMyDummyLoggingClass; // This has the OnLogMsg variable
LoggingProvider: TMyClassImplementingTheStringMethod; // This provides the method we'll assign to OnLogMsg
begin
try
Logging := TMyDummyLoggingClass.Create;
try
// This does nothing, because there's no OnLogMsg assigned.
Logging.LogMsg('Test 1');
LoggingProvider := TMyClassImplementingTheStringMethod.Create;
try
Logging.OnLogMsg := LoggingProvider.WriteLine; // Assign the event
try
// This will indirectly call LoggingProvider.WriteLine, because that's what's
// assigned to Logging.OnLogMsg
Logging.LogMsg('Test 2');
finally Logging.OnLogMsg := nil; // Since the assigned event includes a pointer to both
// the method itself and to the instance of LoggingProvider,
// we need to make sure the event doesn't out-live the LoggingProvider
end;
finally LoggingProvider.Free;
end;
finally Logging.Free;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
// this goes inside the class definition just before the final closing end
property MyEvent:TMyEvent read FMyEvent write FMyEvent
型 现在转到您希望该事件“触发”的位置(如果设置了它,则会被调用)并编写以下内容:
// this goes inside a procedure or function, where you need to "fire" the event.
procedure TMyForm.DoSomething;
begin
...
if Assigned(FMyEvent) then FMyEvent(Self,Param1,Param2,Param3);
end;
type
TMyClass = class
private
FMyProcEvent : TMyProcEvent;
FMyFuncEvent : TMyFuncEvent;
protected
procedure DoMyProcEvent(const AIdent: string; const AValue: Integer);
function DoMyFuncEvent(const ANumber: Integer): Integer;
public
property MyProcEvent: TMyProcEvent read FMyProcEvent write FMyProcEvent;
property MyFuncEvent: TMyFuncEvent read FMyFuncEvent write FMyFuncEvent;
end;
procedure TMyClass.DoMyProcEvent(const AIdent: string; const AValue: Integer);
begin
if Assigned(FMyProcEvent) then
FMyProcEvent(AIdent, AValue);
// Possibly add more general or default code.
end;
function TMyClass.DoMyFuncEvent(const ANumber: Integer): Integer;
begin
if Assigned(FMyFuncEvent) then
Result := FMyFuncEvent(ANumber)
else
Result := cNotAssignedValue;
end;
4条答案
按热度按时间eiee3dmh1#
下面是一个简短但完整的控制台应用程序,它展示了如何在 Delphi 中创建自己的事件。包括从类型声明到调用事件的所有内容。阅读代码中的注解以了解发生了什么。
字符串
bkhjykvo2#
完整的项目答案是好的。但这是一个替代答案,展示了如何做你想做的,以一种你已经拥有的形式。
进入表单,进入接口部分,在类型区域,在表单的类定义之外,添加一个类型:
字符串
传统上,事件中的第一项是发送事件的对象,但不是必须的,而是使用基类TObject而不是窗体的实际类类型。
上面的其他参数根本不是必需的,但它们向您展示了如何声明自己的附加数据。如果您不需要它们,则只需使用Sender:TObject。在这种情况下,您根本不必定义TMyEvent,只需使用TNotifyEvent类型。
现在在表单中声明一个使用该类型的字段:
型
现在在窗体的属性部分声明一个访问该字段的属性:
型
现在转到您希望该事件“触发”的位置(如果设置了它,则会被调用)并编写以下内容:
型
dwbf0jvd3#
您可以使用事件处理程序在发生其他事件时做出React(例如AfterCreation和关闭之前)。
为了在你自己的类中使用事件,你需要定义事件类型。更改所需参数的类型和数量。
字符串
在类中,您可以添加DoEvent(为适当的事件重命名)。因此您可以在内部调用DoEvent。DoEvent处理未分配事件的可能性。
型
r1zhe5dt4#
在将“事件”放入DLL的上下文中,我描述了一个使用接口的概念,一步一步…也许这会以另一种方式有所帮助:在非GUI环境中使用事件侦听器(DLL)( Delphi )