2012-12-17 104 views
0

我想'保護'某個窗口關閉。所以我想掛鉤WM_CLOSE,WM_DESTOY或WM_QUIT。而這正是我試圖這樣做的:鉤窗口消息循環WM_CLOSE

LRESULT CALLBACK WindowHookProc(int nCode, WPARAM wParam, LPARAM lParam) 
{ 
    if (nCode >= 0) 
    { 
     MSG* msg = (MSG*)lParam; 
     //if (msg->hwnd == GetForegroundWindow()) 
     { 
      if (msg->message == WM_CLOSE || msg->message == WM_QUIT || msg->message == WM_DESTROY) 
      { 
       //MessageBox(0, "TEST", "", 0); 
       msg->message = 0; 
       CallNextHookEx(hMsg, nCode, (WPARAM)NULL, (LPARAM)NULL); 
       return TRUE; 
      } 
     } 
    } 

    CallNextHookEx(hMsg, nCode, wParam, lParam); 
} 

我想:

  • 返回TRUE或FALSE
  • 調用CallNextHookEx方法用NULL作爲LPARAM或 編輯MSG->消息爲0

另外我注意到,如果我鉤住WH_GETMESSAGE它不'阻止'消息循環。但它通過掛鉤WH_CALLWNDPROC來實現。當msg->消息等於WM_CLOSE時,我通過提示消息框發現了這一點。

在此先感謝, 此致敬禮。

+0

因此,如果Windows發送您的應用程序的消息關閉它,你會忽略它嗎? – ZippyV

+0

@ZippyV是的,我在「保護」一個特定的hWnd。我想保護一個窗口不點擊關閉按鈕。我不知道我需要阻止WM_QUIT和WM_DESTROY。但我只是試了一下。 – joell

+1

'WM_DESTROY'只是通知你窗口即將被銷燬('DestroyWindow()'已被調用),沒有辦法阻止它。 'WM_QUIT'通知當前的消息循環將被退出,通常不會發送到窗口,而是發送到線程(通常使用'PostQuitMessage()')。不過:當用戶單擊_close_按鈕(或按下Alt-F4)時會調用它,而默認實現只調用DestroyWindow()。 – rodrigo

回答

1

WH_GETMESSAGE爲從消息隊列中檢索的消息安裝鉤子。它確實允許您修改消息。但問題是,WM_CLOSE不會通過PostMessage()發送到消息隊列,而是使用SendMessage()發送。這個鉤子看不到它。

WH_CALLWNDPROC安裝一個在調用窗口過程之前運行的鉤子。這將允許您查看WM_CLOSE。但是,您不允許修改該消息或使其消失。

沒有鉤子可以讓你做你想做的事情。相反,你必須子類窗口程序。這樣你自己的自定義窗口過程在窗口自己的過程之前被調用。現在,只需調用舊窗口過程即可簡單地過濾WM_CLOSE。

請注意,您仍然需要與SetWindowsHookEx()提供的相同類型的管道,您仍然需要在窗口過程中注入一個帶有窗口過程的DLL。最好的方法是仍然使用SetWindowsHookEx來完成一個虛擬鉤子,否則它不會做任何事情。

+0

我將如何繼承?一位朋友告訴我如何,但我們都有的問題是如何獲得原始proc地址返回。由於子類化會覆蓋所有其他WM_ *,因此如何將其返回到其原始過程? – joell

+0

http://msdn.microsoft.com/en-us/library/windows/desktop/ms633570%28v=vs.85%29.aspx#subclassing_window –

1

而不是試圖安裝一個鉤子,只是子類的窗口,並讓您的子類WndProc忽略WM_CLOSE轉發所有其他消息。

你不能也不應該試圖阻止WM_QUIT。正如Rodrigo所指出的那樣,你無法對WM_DESTROY做任何事情。此時,DestroyWindow已被調用,並且無論您是否喜歡,您的窗口都將消失。