如何在自已寫的元件中抓到CM_MOUSELEAVE訊息 |
尚未結案
|
iamjsn
初階會員 發表:78 回覆:95 積分:44 註冊:2002-08-16 發送簡訊給我 |
因為需要寫一個元件,放在FORM上,去改變form預設的一些訊息處理。但前題是程式碼不能加在原有的專案之中,因此用了subClass去換了預設的視窗處理程序WndProc, 但要處理CM_MOUSELEAVE訊息時發現攔不到這個訊息。不知在我這個元件中,如何才能改寫這個訊息的處理方法呢謝謝 元件程式碼大致如下
//要貼在form上的元件----------------------------------------------- THookMouseLeave = class(TComponent) public Procedure HookWndProc; procedure WndProc(var Message : TMessage); end; implementation Procedure THookMouseLeave.HookWndProc; begin //這裏換掉FORM原來的視窗程序 FDefWndProc:=TFarProc(SetWindowLong(FhOwner, GWL_WNDPROC, longint(MakeObjectInstance(WndProc)) )); end; procedure THccSkinCtrl.WndProc(var Message : TMessage); begin With Message do begin if (csDesigning in ComponentState) then begin Result:=CallWindowProc (FDefWndProc,FhOwner,Msg,wParam,lParam); Exit; end; case Msg of CM_MOUSELEAVE:CMMOUSELEAVE(Message); WM_NCPAINT: WMNCPaint(Message); else Result:=CallWindowProc(FDefWndProc,FhOwner,Msg, wParam,lParam); end; end; end; |
hagar
版主 發表:143 回覆:4056 積分:4445 註冊:2002-04-14 發送簡訊給我 |
|
iamjsn
初階會員 發表:78 回覆:95 積分:44 註冊:2002-08-16 發送簡訊給我 |
其實我現在的問題是,大部份wm_開頭的訊息我都攔的到,但是不知為何cm_開頭的CM_MOUSELEAVE抓不到呢,還是開頭的訊息不能在這抓嗎?如果把中斷點設在TCONTROL.CMMOUSELEAVE裏,發現當滑鼠離開Form時, 確實有觸發這個訊息,而且也查出訊息是在tapplication發出的,但是這個訊息似乎不會跑進wndPROC中,不知是那裏弄錯了
function TApplication.DoMouseIdle: TControl; var CaptureControl: TControl; P: TPoint; begin GetCursorPos(P); Result := FindDragTarget(P, True); CaptureControl := GetCaptureControl; if FMouseControl <> Result then begin if ((FMouseControl <> nil) and (CaptureControl = nil)) or ((CaptureControl <> nil) and (FMouseControl = CaptureControl)) then FMouseControl.Perform(CM_MOUSELEAVE, 0, 0);//這裏送出的訊息 FMouseControl := Result; if ((FMouseControl <> nil) and (CaptureControl = nil)) or ((CaptureControl <> nil) and (FMouseControl = CaptureControl)) then FMouseControl.Perform(CM_MOUSEENTER, 0, 0); end; end; |
hagar
版主 發表:143 回覆:4056 積分:4445 註冊:2002-04-14 發送簡訊給我 |
|
iamjsn
初階會員 發表:78 回覆:95 積分:44 註冊:2002-08-16 發送簡訊給我 |
聽了hagar大大這麼回答,真的是粉偒心,看來這個問題也粉多人遇到,似乎無解。失望之餘又回去仔細的看了一下CM_MOUSELEAVE訊息 整個呼叫的流程。
發現這個訊息是經由Perform發出去的,而實際是去執行windowproc這個程序
但windowproc在TCONTROL.CREATE時,已經設定成winproc
所以perform實際是呼叫winproc,忽然才發現為什麼用SetWindowLong去換掉callback函式,仍然抓不到CM_MOUSELEAVE,因為Perform發出的訊息是直接發給原來winproc位址,沒有經過新的callback函式,這樣當然抓不到了,所以解決方法就是…。想不到也出奇的簡單
就先把form的 WindowProc換成自已的 NewWindowProc
然後在NewWindowProc 攔CM_MOUSELEAVE就行了
//...........................................
FOldWindowProc:=form1.windowProc;
form1..WindowProc:=NewWindowProc;
//...........................................
procedure Ttest.NewWindowProc(var Message: TMessage);
begin case Message.Msg of
CM_MOUSELEAVE:MouseLeave(message);
end; FOldWindowProc(message);
end; 因為抓不到 CM_MOUSELEAVE, 害我忙了好幾天,特別寫出來讓有類似問題的人參考一下
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |