2011-04-26 99 views
15

我是新來的Delphi開發。我必須創建一個事件並傳遞一些屬性作爲參數。有人可以分享一些演示程序,展示如何從頭開始。我幾乎在每個網站上搜索了一下,他們都給了一段代碼,但我需要的是一個簡單易懂的完整的程序。德爾福事件處理,如何創建自己的事件

+4

請解釋一下你實際上是試圖做的,所以提供足夠的信息我們可以建議替代路線;因爲我懷疑你問的實際問題的答案不會幫助你。 >新建 - - > VCL窗體應用程序文件: – 2011-04-26 06:29:54

+0

''要使用事件做得到完全的程序。你有它,這是一個完整的工作示例,說明如何使用事件,完整的源代碼.''。但正如我在之前的評論中提到的,我懷疑這就是你實際需要的。一般來說很難從完整的課程中學習。 – 2011-04-26 06:34:16

+0

謝謝,我其實是一個想在delphi中精心創建事件的小程序。我如何在delphi中創建自己的事件。 – mac 2011-04-26 06:37:03

回答

12

您可以使用一個事件處理反應過來的時候什麼事情發生(例如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; 
+0

參數被OP特別要求... – 2011-04-26 07:04:20

+0

謝謝親愛的,非常有幫助。但仍不能複製粘貼,然後只需更改屬性即可實現不同的結果。 – mac 2011-04-26 07:13:44

+12

@mac,如果代碼對你來說不是複製粘貼友好的,就讓它自己複製粘貼友好。如果您對代碼不瞭解,請要求澄清。只是要求更多的複製粘貼友好代碼,讓你看起來像一個懶惰的[你是否haz德代碼](http://meta.serverfault.com/questions/1039/what-is-do-you-haz-teh-codez )類型。 – 2011-04-26 07:43:53

44

下面是一個簡短但很完整的控制檯應用程序,演示如何創建在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. 
+0

非常感謝,很好的例子,你是否也提供了基於表單的示例,因爲它是基於控制檯的。我需要在表單上創建我自己的事件並獲得一些東西。謝謝你的好例子。 – mac 2011-04-26 07:20:29

+22

@mac不,我不能。這*是一個完整的例子,在表單上做同樣的事情並不需要*任何特殊的*;表單只是像其他任何類一樣的類。做一個基於表單的例子需要至少3個文件(dpr,dfm + pas),並且不添加任何*新的。我仍然懷疑這不是你所需要的,但是因爲你不想回答「爲什麼」這個問題,所以我不能做得更好。 – 2011-04-26 07:29:31

17

完整的項目回答是好。但是,這是一個備選答案,以您已經擁有的形式展示如何去做你想做的事。

進入您的形式,並轉到接口部分,在二類地區,表單的類定義之外,並添加一個類型:

interface 
type 
    TMyEvent = procedure(Sender:TObject;Param1,Param2,Param3:Integer) of object; 

    TMyForm = class(TForm) 
      .... 

這是傳統的,但不是必需的,第一項在你的事件中是發送它的對象,但要使用基類TObject而不是表單的實際類類型。
上面的其他參數完全不需要,但顯示你將如何聲明自己的附加數據。如果你不需要它們,那麼只需使用發件人: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; 
+0

謝謝沃倫;我會嘗試用delphi做一些事情,實際上問題是,程序流程,或者我需要在一個單元中定義和調用事件,或者需要另一個單元來定義事件和分配屬性,然後調用此事件一個按鈕點擊事件。像進度條和百分比計數器一樣。 – mac 2011-04-27 05:49:57

+2

我不知道你的意思。如果你問一個不同的問題,最好還是不清楚。 – 2012-10-23 20:56:08