BCB轉Delphi語法:有關CallBack function 內的指標參數轉型問題 |
尚未結案
|
chris_shieh
高階會員 發表:46 回覆:308 積分:240 註冊:2004-04-26 發送簡訊給我 |
我嘗試改寫以下BCB為Delphi 可是一直無法成功
BCB // TIMECALLBACK function void __stdcall TimerProc(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD_PTR dw1, DWORD_PTR dw2) { // 呼叫使用者定義的函式 ((TMMTimer *)dwUser)->OnTimer(); } void __fastcall TMMTimer::SetEnabled(bool value) { ... FTImerID = timeSetEvent(FInterval, // 觸發間隔時間(ms) FResolution, // 容忍解析度時間(ms) TimerProc, // 回呼函式(callback function)位址 (DWORD)this, // 使用者定義資料,傳給callback function的dwUser參數 TIME_PERIODIC); // 觸發方式:週期觸發 ... } Delphi // TIMECALLBACK function procedure TimerProc(uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD) stdcall; var ttimer:TMMTimer; begin ttimer:=TMMTimer(dwUser); //dwUser 就是在timeSetEvent中傳過來的Cardinal(@self) // 呼叫使用者定義的函式 if Assigned(ttimer) then ttimer.FOnTimer(ttimer); //錯誤 access violoation at 0x00000000 //Form1.Timer1Timer(ttimer);利用偷吃步取用實際物件可以正確運作 end; procedure TMMTimer.SetEnabled(value:Boolean); begin ... ... FTImerID := timeSetEvent(FInterval, // 觸發間隔時間(ms) FResolution, // 容忍解析度時間(ms) TimerProc, // 回呼函式(callback function)位址 DWORD(@self), // 使用者定義資料,傳給callback function的dwUser參數 TIME_PERIODIC); // 觸發方式:週期觸發 ... ... end; 我在這裡設置了一個timeEvent 並 給與 觸發事件的Callback function:TimerProc , 並將@self 當作user defined data 一起傳過去 可是TimerProc中一直都無法正確呼叫到FOnTimer 我確定已經在使用元件前指定 TMMTimer.OnTImer=Timer1Timer; tracr 也發現 timerSetEvent 中 Cardinal(@self) 與 TimerProc 中的 dwUser兩者確實位址相同 可是取出來的 TMMTimer 物件property內容卻不同 我想應該沒有取到正確的物件 所以我想FOnTimer想當然爾會Access Violation but WHY ? |
Zard
尊榮會員 發表:24 回覆:396 積分:539 註冊:2003-11-26 發送簡訊給我 |
別忘了你所傳的是指標, 所以要這樣改
// 新加一個指向TMMTimer的指標定義 type PTMMTimer = ^TMMTimer; procedure TimerProc(uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD) stdcall; var ttimer:TMMTimer; begin //ttimer:=TMMTimer(dwUser); //dwUser 就是在timeSetEvent中傳過來的Cardinal(@self) // 首先用PTMMTimer(dwUser)把dwUser轉回它原來的型態, 在用^ 來取得內容 ttimer := PTMMTimer(dwUser)^; // 呼叫使用者定義的函式 if Assigned(ttimer) then ttimer.FOnTimer(ttimer); end;下面是我用來測試的小程式, 你可以參考一下. unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; pOnClick = Procedure (Sender: TObject); TestClass = Class Public OnClick: pOnClick; end; PTestClass = ^TestClass; var Form1: TForm1; CTest: TestClass; implementation {$R *.DFM} procedure ClickTest(Sender: TObject); begin ShowMessage('Test'); end; Procedure PassTest(iAddr: UINT); var TestClassTmp: TestClass; begin TestClassTmp := PTestClass(iAddr)^; TestClassTmp.OnClick(nil); // 或是直接這樣用 //PTestClass(iAddr)^.OnClick(nil); end; procedure TForm1.Button1Click(Sender: TObject); begin ClickTest(Sender); end; procedure TForm1.FormCreate(Sender: TObject); begin CTest := TestClass.Create; CTest.OnClick := @ClickTest; end; procedure TForm1.FormDestroy(Sender: TObject); begin CTest.Free; end; procedure TForm1.Button2Click(Sender: TObject); begin PassTest(Cardinal(@CTest)); end; end. |
chris_shieh
高階會員 發表:46 回覆:308 積分:240 註冊:2004-04-26 發送簡訊給我 |
謝謝您的回應
您設計的解說範例是可以正確執行的 概念也很清楚
但是我把 Callback function 內改成您說的方式 卻一樣無法正常執行
var ttimer:TMMTimer; begin // 首先用PTMMTimer(dwUser)把dwUser轉回它原來的型態, 在用^ 來取得內容 ttimer := PTMMTimer(dwUser)^; // 呼叫使用者定義的函式 if Assigned(ttimer) then ttimer.FOnTimer(ttimer);我也是覺得很奇怪 PS. timerSetEvent 中傳的參數 一樣是 Cardinal(@self) 後來因為我記得在Delphi中 物件本身就是Pointer 所以我試著把 timeSetEvent中的參數改成 Cardinal(self) , Callback function 中 改用 TMMTimer(dwUser).FOnTimer(nil) 結果就可以正常執行 真的很奇怪 範例可以正常執行, 不知道問題到底是出在哪? |
Zard
尊榮會員 發表:24 回覆:396 積分:539 註冊:2003-11-26 發送簡訊給我 |
引言: 謝謝您的回應 您設計的解說範例是可以正確執行的 概念也很清楚 但是我把 Callback function 內改成您說的方式 卻一樣無法正常執行真的很奇怪, 可否整理一份會出問題的測試程式放上來讓大家參考一下var ttimer:TMMTimer; begin // 首先用PTMMTimer(dwUser)把dwUser轉回它原來的型態, 在用^ 來取得內容 ttimer := PTMMTimer(dwUser)^; // 呼叫使用者定義的函式 if Assigned(ttimer) then ttimer.FOnTimer(ttimer);我也是覺得很奇怪 PS. timerSetEvent 中傳的參數 一樣是 Cardinal(@self) 後來因為我記得在Delphi中 物件本身就是Pointer 所以我試著把 timeSetEvent中的參數改成 Cardinal(self) , Callback function 中 改用 TMMTimer(dwUser).FOnTimer(nil) 結果就可以正常執行 真的很奇怪 範例可以正常執行, 不知道問題到底是出在哪? |
chris_shieh
高階會員 發表:46 回覆:308 積分:240 註冊:2004-04-26 發送簡訊給我 |
這是 參考 其他網友 TMMTimer 的 Delphi 版
http://delphi.ktop.com.tw/loadfile.php?TOPICID=19612906&CC=438634 發表人 - chris_shieh 於 2004/12/31 18:37:28
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |