線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1225
推到 Plurk!
推到 Facebook!

如何在自已寫的元件中抓到CM_MOUSELEAVE訊息

尚未結案
iamjsn
初階會員


發表:78
回覆:95
積分:44
註冊:2002-08-16

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-08-31 16:20:22 IP:203.204.xxx.xxx 未訂閱
因為需要寫一個元件,放在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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-08-31 21:00:09 IP:202.39.xxx.xxx 未訂閱
您可以下載 RxLib: http://sourceforge.net/projects/rxlib/ 它有一個 TRxHookWindow 元件(也有 source 可參考) 功能似乎與您描述的相同    -- 歡迎光臨 KTop 研究院!
iamjsn
初階會員


發表:78
回覆:95
積分:44
註冊:2002-08-16

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-09-01 00:11:11 IP:203.204.xxx.xxx 未訂閱
其實我現在的問題是,大部份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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-09-01 11:02:40 IP:202.39.xxx.xxx 未訂閱
這種方式是似乎是沒辦法, 參考:  http://groups.google.com/groups?hl=zh-TW&lr=&ie=UTF-8&th=4ade81a7772c9b00&rnum=1    -- 歡迎光臨 KTop 研究院!
iamjsn
初階會員


發表:78
回覆:95
積分:44
註冊:2002-08-16

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-09-02 14:00:55 IP:203.204.xxx.xxx 未訂閱
聽了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, 害我忙了好幾天,特別寫出來讓有類似問題的人參考一下
系統時間:2024-05-17 9:57:59
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!