2009-02-06 55 views
5

我有一個窗口,我處理WM_NCLBUTTONUP消息,以處理點擊標題欄中的自定義按鈕。當窗口最大化時,這很好用,但當它不是時,WM_NCLBUTTONUP消息永遠不會到達!雖然我確實收到了WM_NCLBUTTONDOWN消息。奇怪的是WM_NCLBUTTONUP確實到達了,如果我點擊菜單欄的右側,但是在標題欄/窗口框架的任何位置,消息都不會到達。窗口沒有最大化時丟失的WM_NCLBUTTONUP消息的好奇問題

經過一段時間的調試後,我發現如果我在CMainFrame :: OnNcLButtonDown()上設置斷點,單擊標題欄,但不要按住鼠標按鈕,讓調試器在函數中斷開,按F5繼續調試,然後釋放鼠標按鈕 - 神奇的WM_NCLBUTTONUP發送!

我的問題是雙重的,(1)究竟是怎麼回事? (2)我如何解決這個「問題」。

我還注意到,互聯網上還有其他幾個人有同樣的問題(一個快速的谷歌揭示了很多其他人有同樣的問題,但沒有解決方案)。

編輯
謝謝你的前兩個回覆,我已經打過電話ReleaseCapture在NCLButtonDown,但它沒有任何效果(事實上,它返回NULL,表示捕獲不到位)。我只能假設基類(def窗口過程)功能可能會設置捕獲。我將在星期一進行調查......

回答

4

我有這個相同的問題。問題的確是,在窗口標題上單擊左鍵會開始拖動,從而導致鼠標捕獲,從而阻止WM_NCLBUTTONUP到達。

的解決方案是重寫WM_NCHITTEST:

LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (nMsg) 
    { 
     ... 
     case WM_NCHITTEST: 
      Point p(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam); 
      ScreenToClient(p); 
      if (myButtonRect.Contains(p)) 
      { 
       return HTBORDER; 
      } 
      break; 
    } 
    return DefWindowProc(hWnd, nMsg, wParam, lParam); 
} 

所以基本上你通知Windows您的按鈕所佔據的區域不是窗口標題的一部分,但非客戶區的非特異性部分(HTBORDER)。

腳註:如果您在期望WM_NCLBUTTONDOWN消息進入時調用SetCapture()並且尚未調用ReleaseCapture(),則即使進行上述更改也不會到達。這可能會讓人惱火,因爲在與這些自定義按鈕交互過程中捕捉鼠標是正常的,因此如果鼠標離開窗口,您可以取消點擊/高亮顯示。但是,作爲使用捕獲的替代方法,您可能會考慮SetTimer()/ KillTimer()以較短的間隔(例如100毫秒),這將不會導致WM_NCLBUTTONUP消息消失。

2

瘋狂的猜測 - 某些代碼捕獲鼠標,可能會在您抓取標題時促進窗口移動。這也可以解釋爲什麼打破調試器會導致消息出現 - 調試器交互清除鼠標捕獲。

我建議你在該窗口上運行Spy ++,它是孩子們,並試圖找出誰得到了按鈕的消息。

至於如何解決它 - 無法幫助你在那裏沒有看實際的代碼。你必須找出誰是罪魁禍首,並看看他們的代碼。

1

要添加到Franci Penov's answer,標題欄上的單擊將被解釋爲拖動的起點以重新定位窗口。該窗口正在捕獲鼠標,因此它可以執行拖動。由於無法拖動最大化的窗口,捕獲將被跳過,並且消息正常路由。

1

包括WM_NCLBUTTONDOWN中的ReleaseCapture(){code block}