2009-02-06 35 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}