請教一下有關callback function的用法(與event的不同)? |
答題得分者是:jow
|
macchen
初階會員 發表:66 回覆:102 積分:33 註冊:2006-07-07 發送簡訊給我 |
請問一下,有關於我的問題描述一下,我有看過vc寫的event方式,是被觸發後才會被執行,然後我需要在delphi上做這種方式的實現,然後上網查了一下callback function,大多數人的說明都是說要被執行時才會被call到,而不用像使用像是while(反正就是程式卡在那邊等的意思,thread好像也是在那等哦)的方式一直等,這樣cpu好像會被吃掉資源一樣,而像vc上使用event的方式,好像沒什麼佔cpu,並且只會在被觸發時才會被執行,這樣與我查的callback function說明很相似,但是問題來了,為什麼很多人解釋callback function都是指傳入function pointer的方式在解釋,因為我需要是像有一個長駐在系統上的一個程式(有點像是activex或是像service這種東西,如果觀念不對請糾正,謝謝),然後我的程式(指ap端)會做我正常軟體要執行的程式,但是一旦有事件(我不知這樣叫對不對)被觸發後,會有訊息告知我的ap程式,然後ap才會去處理這個事件,不然就不管這個事件(指不用一直去等),請問這樣子方式可以利用什麼方法實現呢,目前到在google中,但沒有一個局體的方向,請各位有這方面的知識,可以教導一下,謝謝你的收看。
------
DELPHI初學者 |
DelphiJob
一般會員 發表:1 回覆:4 積分:6 註冊:2009-12-22 發送簡訊給我 |
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
你問的是很深的根基問題,很深喔! 許多人不了解很深也是可以寫程式的,但就是無法寫到純青。
我認為,相信應該沒錯, event 與 callback 其實是很"等值"的東西或"說詞"或"技術" windows 被稱叫 event drive 的作業系統 ,event drive 就是指由事件來驅動程式被執行。 event 這個詞是用來說明,「當程式收到某訊息後才被執行」。而callback這個詞則是「實現事件驅動程式的方法」。 event 是一種概念,一種結構。而callback就是為了達成這樣結構的實作方式。 你必須先了解winodws是如何把鍵盤,mouse等訊息queue住,然後windows"主動"去執行對應的程式。簡單的講是應用程式一開始會向系統註冊一些資訊,其中就含有一個function pointer (叫 windproc)… 當使用者在該應用程式上做了一些輸入時,先產生訊息的結構送到系統,系統比對後知道是某註冊過的程式,於是例用當時告知的function pointer來 主動的呼叫該程式。 mouse等行為就產生了event,而有了這個event後就例用callback的方式來呼叫。 再深入下去有更多的東西要說,都和作業系統有關…一時半刻也無從講。你就朝這方向去查或去想吧! 註: 你說的vc的event寫法其實和delphi/bcb裡把某button按二下,然後開始寫其中的程式碼是一樣的。只是vc的寫法很接近windows api的層級,你要了解ui上的button等id與資源,然後自己把message"接入"自己的程式(使用macro)。但這些東西delphi/bcb通通幫你做掉了,所以你沒感覺,所以你很方便,所以…許多人因此無法真的了解底層,因為不了解也可以按二下就寫 ^_^ 。 good luck!
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2009-12-23 23:31:15, 註解 無‧
|
DelphiJob
一般會員 發表:1 回覆:4 積分:6 註冊:2009-12-22 發送簡訊給我 |
Event drive 說詞 若使用 Message drive 會更貼切嗎? 因Win32 SDK 並無Event 這個東西嗎? MFC 才出現嗎? ===================引 用 aftcast 文 章=================== 你問的是很深的根基問題,很深喔! 許多人不了解很深也是可以寫程式的,但就是無法寫到純青。 我認為,相信應該沒錯, event 與 callback 其實是很"等值"的東西或"說詞"或"技術" windows 被稱叫 event drive 的作業系統 ,event drive 就是指由事件來驅動程式被執行。 event 這個詞是用來說明,「當程式收到某訊息後才被執行」。而callback這個詞則是「實現事件驅動程式的方法」。 event 是一種概念,一種結構。而callback就是為了達成這樣結構的實作方式。 你必須先了解winodws是如何把鍵盤,mouse等訊息queue住,然後windows"主動"去執行對應的程式。簡單的講是應用程式一開始會向系統註冊一些資訊,其中就含有一個function pointer (叫 windproc)… 當使用者在該應用程式上做了一些輸入時,先產生訊息的結構送到系統,系統比對後知道是某註冊過的程式,於是例用當時告知的function pointer來 主動的呼叫該程式。 mouse等行為就產生了event,而有了這個event後就例用callback的方式來呼叫。 再深入下去有更多的東西要說,都和作業系統有關…一時半刻也無從講。你就朝這方向去查或去想吧! 註: 你說的vc的event寫法其實和delphi/bcb裡把某button按二下,然後開始寫其中的程式碼是一樣的。只是vc的寫法很接近windows api的層級,你要了解ui上的button等id與資源,然後自己把message"接入"自己的程式(使用macro)。但這些東西delphi/bcb通通幫你做掉了,所以你沒感覺,所以你很方便,所以…許多人因此無法真的了解底層,因為不了解也可以按二下就寫 ^_^ 。 good luck! |
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
嗯,認同delphijob說的詞句。 Message Drive 應該是更多人使用的詞! 但概念上講的是同一回事。 win32 sdk 上的確是沒用到event,而用message…
但這二詞有那麼一點互用,比如說: message handler 訊息處理的函式。 event handler 事件處理函式。 這種情形下,event的用法就比較多。 總之,概念吧,概念的理解比用詞重要些。謝謝 delphijob 的提供 ^_^ 此外,覺得event 的用詞比message的用詞來的更 "高階" 或說更"抽象"一點的概念用語。message比較具體點。
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
以下程式提供你參考
希望有幫助... [code delphi] unit fMain; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, StdCtrls; const //User-Define Windows Message WM_GEN_RANDOM = WM_USER 10000; type //User-Define Windows Message Record TWMGenRandom = record Msg: Cardinal; Counter: Integer; RndNumber: Integer; Result: Longint; end; //User-Define Callback Function TMyGetFontColor = function: TColor of object; //User-Define Enevt Type TMyOnGetSeedEvent = procedure(Sender: TObject; var Seed: Integer) of object; { TMyWinControl } //User-Define TWinControl (with Window Handle) TMyWinControl = class(TCustomControl) private FCounter: Integer; FRndNumber: Integer; function GET_FONT_COLOR: TColor;//CALLBACK FUNCTION procedure WMGenRandom(var Message: TWMGenRandom); message WM_GEN_RANDOM; public procedure Paint; override; end; { TMyGraphicControl } //User-Define TGraphicControl (without Window Handle) TMyGraphicControl = class(TGraphicControl) private FCounter: Integer; FRndNumber: Integer; function GET_FONT_COLOR: TColor;//CALLBACK FUNCTION //TGraphicControl cannot receive any Message... procedure WMGenRandom(var Message: TWMGenRandom); message WM_GEN_RANDOM; public procedure Paint; override; end; TfrmMain = class; { TMyEventThread } //Random Number Generator... TMyEventThread = class(TThread) private FCounter: Integer; FOnGetSeed: TMyOnGetSeedEvent; FOwner: TfrmMain; FRndNumber: Integer; FSeed: Integer; protected procedure Execute; override; public constructor Create(AOwner: TfrmMain); reintroduce; property OnGetSeed: TMyOnGetSeedEvent read FOnGetSeed write FOnGetSeed; end; { TfrmMain } TfrmMain = class(TForm) CheckBox1: TCheckBox; procedure CheckBox1Click(Sender: TObject); private FMyEventThread: TMyEventThread; procedure DO_OnGetSeed(Sender: TObject; var Seed: Integer); procedure WMGenRandom(var Message: TWMGenRandom); message WM_GEN_RANDOM; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; end; //public function with Callback procedure PaintTest(Canvas: TCanvas; ClientRect: TRect; ClassName: string; GetFontColor: TMyGetFontColor; Counter, RndNumber: Integer); var frmMain: TfrmMain; implementation {$R *.dfm} procedure PaintTest(Canvas: TCanvas; ClientRect: TRect; ClassName: string; GetFontColor: TMyGetFontColor; Counter, RndNumber: Integer); begin Canvas.Brush.Color := clBlack; Canvas.Brush.Style := bsSolid; Canvas.FillRect(ClientRect); Canvas.Font.Name := 'Arial'; Canvas.Font.Height := 24; Canvas.Font.Color := GetFontColor; Canvas.TextOut(5,00,ClassName); Canvas.Font.Color := GetFontColor; Canvas.TextOut(5,25,'Counter = ' IntToStr(Counter)); Canvas.Font.Color := GetFontColor; Canvas.TextOut(5,50,'RanNumber = ' IntToStr(RndNumber)); end; { TMyWinControl } function TMyWinControl.GET_FONT_COLOR: TColor; begin Result := RGB(Random($100),Random($100),Random($100)); end; procedure TMyWinControl.Paint; begin PaintTest(Canvas,ClientRect,ClassName,GET_FONT_COLOR,FCounter,FRndNumber); end; procedure TMyWinControl.WMGenRandom(var Message: TWMGenRandom); begin FCounter := Message.Counter; FRndNumber := Message.RndNumber; Invalidate; end; { TMyGraphicControl } function TMyGraphicControl.GET_FONT_COLOR: TColor; begin case (FRndNumber div 10) mod 3 of 0: Result := clYellow; 1: Result := clRed; else Result := clWhite; end; end; procedure TMyGraphicControl.Paint; begin PaintTest(Canvas,ClientRect,ClassName,GET_FONT_COLOR,FCounter,FRndNumber); end; procedure TMyGraphicControl.WMGenRandom(var Message: TWMGenRandom); begin FCounter := Message.Counter; FRndNumber := Message.RndNumber; Invalidate; end; { TMyEventThread } constructor TMyEventThread.Create(AOwner: TfrmMain); begin inherited Create(True); FOwner := AOwner; FreeOnTerminate := True; Resume; end; procedure TMyEventThread.Execute; var Delay: Cardinal; begin FCounter := 0; while not Terminated do begin Delay := GetTickCount 100; Inc(FCounter); if Assigned(FOnGetSeed) then FOnGetSeed(Self,FSeed) else FSeed := 10; FRndNumber := Random(FSeed); PostMessage(FOwner.Handle,WM_GEN_RANDOM,FCounter,FRndNumber); while GetTickCount < Delay do Application.ProcessMessages; end; end; { TfrmMain } constructor TfrmMain.Create(AOwner: TComponent); begin inherited; CheckBox1.BoundsRect := Rect(0,0,100,20); with TMyWinControl.Create(Self) do begin Parent := Self; BoundsRect := Rect(10,25,300,100); end; with TMyGraphicControl.Create(Self) do begin Parent := Self; BoundsRect := Rect(10,135,300,210); end; FMyEventThread := TMyEventThread.Create(Self); Width := 350; Height := 300; end; destructor TfrmMain.Destroy; begin FMyEventThread.Terminate; inherited; end; procedure TfrmMain.DO_OnGetSeed(Sender: TObject; var Seed: Integer); begin Seed := Random( MaxInt); end; procedure TfrmMain.WMGenRandom(var Message: TWMGenRandom); var I: Integer; begin for I := 0 to ComponentCount-1 do begin if Components[I] is TWinControl then begin //Owner post received message to owned TWinControls PostMessage( TWinControl(Components[I]).Handle, Message.Msg, Message.Counter, Message.RndNumber); end else if Components[I] is TMyGraphicControl then begin //Owner call to owned TMyGraphicControl's function TMyGraphicControl(Components[I]).WMGenRandom(Message); end; end; end; procedure TfrmMain.CheckBox1Click(Sender: TObject); begin //Dynamic hooking event handler... if Assigned(FMyEventThread) then begin if CheckBox1.Checked then FMyEventThread.OnGetSeed := DO_OnGetSeed else FMyEventThread.OnGetSeed := nil; end; end; end. [/code] 謹供參考... |
macchen
初階會員 發表:66 回覆:102 積分:33 註冊:2006-07-07 發送簡訊給我 |
真奇怪,總算可以回覆了,先試試一下,有關念上問題再來請教大大,謝謝。
===================引 用 jow 文 章=================== 以下程式提供你參考 希望有幫助... [code delphi] unit fMain; interface uses ? Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, StdCtrls; const ? //User-Define Windows Message ? WM_GEN_RANDOM = WM_USER 10000; type ? //User-Define Windows Message Record ? TWMGenRandom = record ??? Msg: Cardinal; ??? Counter: Integer; ??? RndNumber: Integer; ??? Result: Longint; ? end; ? //User-Define Callback Function ? TMyGetFontColor = function: TColor of object; ? ? //User-Define Enevt Type ? TMyOnGetSeedEvent = procedure(Sender: TObject; var Seed: Integer) of object; { TMyWinControl } ? //User-Define TWinControl (with Window Handle) ? TMyWinControl = class(TCustomControl) ? private ??? FCounter: Integer; ??? FRndNumber: Integer; ??? function GET_FONT_COLOR: TColor;//CALLBACK FUNCTION ??? procedure WMGenRandom(var Message: TWMGenRandom); message WM_GEN_RANDOM; ? public ??? procedure Paint; override; ? end; { TMyGraphicControl } ? //User-Define TGraphicControl (without Window Handle) ? TMyGraphicControl = class(TGraphicControl) ? private ??? FCounter: Integer; ??? FRndNumber: Integer; ??? function GET_FONT_COLOR: TColor;//CALLBACK FUNCTION ??? //TGraphicControl cannot receive any Message... ??? procedure WMGenRandom(var Message: TWMGenRandom); message WM_GEN_RANDOM; ? public ??? procedure Paint; override; ? end; ? TfrmMain = class; { TMyEventThread } ? //Random Number Generator... ? TMyEventThread = class(TThread) ? private ??? FCounter: Integer; ??? FOnGetSeed: TMyOnGetSeedEvent; ??? FOwner: TfrmMain; ??? FRndNumber: Integer; ??? FSeed: Integer; ? protected ??? procedure Execute; override; ? public ??? constructor Create(AOwner: TfrmMain); reintroduce; ??? property OnGetSeed: TMyOnGetSeedEvent read FOnGetSeed write FOnGetSeed; ? end; { TfrmMain } ? TfrmMain = class(TForm) ??? CheckBox1: TCheckBox; ??? procedure CheckBox1Click(Sender: TObject); ? private ??? FMyEventThread: TMyEventThread; ??? procedure DO_OnGetSeed(Sender: TObject; var Seed: Integer); ??? procedure WMGenRandom(var Message: TWMGenRandom); message WM_GEN_RANDOM; ? public ??? constructor Create(AOwner: TComponent); override; ??? destructor Destroy; override; ? end; ? //public function with Callback ? procedure PaintTest(Canvas: TCanvas; ClientRect: TRect; ??? ClassName: string; GetFontColor: TMyGetFontColor; Counter, RndNumber: Integer); var ? frmMain: TfrmMain; implementation {$R *.dfm} procedure PaintTest(Canvas: TCanvas; ClientRect: TRect; ClassName: string; ? GetFontColor: TMyGetFontColor; Counter, RndNumber: Integer); begin ? Canvas.Brush.Color := clBlack; ? Canvas.Brush.Style := bsSolid; ? Canvas.FillRect(ClientRect); ? Canvas.Font.Name := 'Arial'; ? Canvas.Font.Height := 24; ? Canvas.Font.Color := GetFontColor; ? Canvas.TextOut(5,00,ClassName); ? Canvas.Font.Color := GetFontColor; ? Canvas.TextOut(5,25,'Counter = ' IntToStr(Counter)); ? Canvas.Font.Color := GetFontColor; ? Canvas.TextOut(5,50,'RanNumber = ' IntToStr(RndNumber)); end; { TMyWinControl } function TMyWinControl.GET_FONT_COLOR: TColor; begin ? Result := RGB(Random($100),Random($100),Random($100)); end; procedure TMyWinControl.Paint; begin ? PaintTest(Canvas,ClientRect,ClassName,GET_FONT_COLOR,FCounter,FRndNumber); end; procedure TMyWinControl.WMGenRandom(var Message: TWMGenRandom); begin ? FCounter := Message.Counter; ? FRndNumber := Message.RndNumber; ? Invalidate; end; { TMyGraphicControl } function TMyGraphicControl.GET_FONT_COLOR: TColor; begin ? case (FRndNumber div 10) mod 3 of ??? 0: Result := clYellow; ??? 1: Result := clRed; ??? else Result := clWhite; ? end; end; procedure TMyGraphicControl.Paint; begin ? PaintTest(Canvas,ClientRect,ClassName,GET_FONT_COLOR,FCounter,FRndNumber); end; procedure TMyGraphicControl.WMGenRandom(var Message: TWMGenRandom); begin ? FCounter := Message.Counter; ? FRndNumber := Message.RndNumber; ? Invalidate; end; { TMyEventThread } constructor TMyEventThread.Create(AOwner: TfrmMain); begin ? inherited Create(True); ? FOwner := AOwner; ? FreeOnTerminate := True; ? Resume; end; procedure TMyEventThread.Execute; var ? Delay: Cardinal; begin ? FCounter := 0; ? while not Terminated do ? begin ??? Delay := GetTickCount 100; ??? Inc(FCounter); ??? if Assigned(FOnGetSeed) ??? then FOnGetSeed(Self,FSeed) ??? else FSeed := 10; ??? FRndNumber := Random(FSeed); ??? PostMessage(FOwner.Handle,WM_GEN_RANDOM,FCounter,FRndNumber); ??? while GetTickCount < Delay do Application.ProcessMessages; ? end; end; { TfrmMain } constructor TfrmMain.Create(AOwner: TComponent); begin ? inherited; ? ? CheckBox1.BoundsRect := Rect(0,0,100,20); ? with TMyWinControl.Create(Self) do ? begin ??? Parent := Self; ??? BoundsRect := Rect(10,25,300,100); ? end; ? with TMyGraphicControl.Create(Self) do ? begin ??? Parent := Self; ??? BoundsRect := Rect(10,135,300,210); ? end; ? FMyEventThread := TMyEventThread.Create(Self); ? Width := 350; ? Height := 300; ? end; destructor TfrmMain.Destroy; begin ? FMyEventThread.Terminate; ? inherited; end; procedure TfrmMain.DO_OnGetSeed(Sender: TObject; var Seed: Integer); begin ? Seed := Random( MaxInt); end; procedure TfrmMain.WMGenRandom(var Message: TWMGenRandom); var ? I: Integer; begin ? for I := 0 to ComponentCount-1 do ? begin ??? if Components[I] is TWinControl then ??? begin ? //Owner post received message to owned TWinControls ? PostMessage( ??? TWinControl(Components[I]).Handle, ??? Message.Msg, ??? Message.Counter, ??? Message.RndNumber); ??? end ??? else if Components[I] is TMyGraphicControl then ??? begin ? //Owner call to owned TMyGraphicControl's function ? TMyGraphicControl(Components[I]).WMGenRandom(Message); ??? end; ? end; end; procedure TfrmMain.CheckBox1Click(Sender: TObject); begin ? //Dynamic hooking event handler... ? if Assigned(FMyEventThread) then ? begin ??? if CheckBox1.Checked ??? then FMyEventThread.OnGetSeed := DO_OnGetSeed ??? else FMyEventThread.OnGetSeed := nil; ? end; end; end. [/code] 謹供參考... ?
------
DELPHI初學者 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |