我是delphi开发的新手。我必须创建一个事件并将一些属性作为参数传递。有人可以分享一些演示程序,演示如何从头开始。我几乎每个网站都搜索过,他们都给了一段代码,但我需要的是一个简单易懂的完整程序。
答案 0 :(得分:49)
这是一个简短但完整的控制台应用程序,它展示了如何在Delphi中创建自己的事件。包括从类型声明到调用事件的所有内容。阅读代码中的注释,了解正在发生的事情。
program Project23;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
// Declare an event type. It looks allot like a normal method declaration except
// it 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 + a pointer to the
// object instance it's supposed 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,
// 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.
答案 1 :(得分:18)
完整的项目答案很好。但这是一个替代答案,展示了如何以你已有的形式做你想做的事。
进入表单,然后转到表单类定义之外的类型区域中的界面部分,并添加一个类型:
interface
type
TMyEvent = procedure(Sender:TObject;Param1,Param2,Param3:Integer) of object;
TMyForm = class(TForm)
....
事件中的第一项是发送它的对象,但使用基类TObject而不是表单的实际类类型是传统的,但不是必需的。 上面的其他参数根本不需要,但是向您展示如何声明自己的附加数据。如果你不需要它们,那么只需使用Sender:TObject。 在这种情况下,您根本不必定义TMyEvent,只需使用TNotifyEvent类型。
现在声明一个在您的表单中使用该类型的字段:
TMyForm = class(TForm)
private
FMyEvent : TMyEvent;
...
现在声明一个访问该字段的属性,在表单的属性部分中:
// 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;
答案 2 :(得分:14)
使用事件处理程序在发生其他事情时做出反应(例如AfterCreation和关闭之前)。
要为自己的类使用事件,您需要定义事件类型。更改所需参数的类型和数量。
type
TMyProcEvent = procedure(const AIdent: string; const AValue: Integer) of object;
TMyFuncEvent = function(const ANumber: Integer): Integer of object;
在课程中,您可以添加DoEvent(为正确的事件重命名)。所以你可以在内部调用DoEvent。 DoEvent处理未分配事件的可能性。
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;
答案 3 :(得分:0)
在放置"事件"的背景下进入一个DLL我用一步一步的接口描述了一个概念......也许这有助于以不同的方式:Using event listeners in a non-gui environment (DLL) (Delphi)