在win32上实现响应WM_NCLBUTTONUP

WM_NCLBUTTONUP,按照msdn的原话:

Posted when the user releases the left mouse button while the cursor is within the nonclient area of a window. This message is posted to the window that contains the cursor. If a window has captured the mouse, this message is not posted.

大概意思就是用户在窗口非客户区,鼠标左键弹起会发送该消息。但是该窗口是当前激活的且鼠标在当前的窗口,左键弹起,则不会发送该消息......?????疑惑,那我要你干啥?????管上一层窗口送下来的WM_NCLBUTTONUP吗??????

后来我查了下资料,发现这是个很玄幻的消息,当你单击鼠标、然后放开,会发现该消息并没有出现。相反,当双击窗口标题栏的时候,该消息出现了。

而这是微软自己的锅,至少到了win10.0.18362还有着这个奇怪的"特性"。事实上,Windows把这个消息变成了WM_MOVE,而不是WM_NCLBUTTONUP。

于是,想了一个权宜之计——重写WM_NCHITTEST。因为我是希望在标题栏某个范围内产生BUTTONUP,那整个非客户区哪里按下不会导致窗口移动呢:边框。因此,得到了这样的一个思路:

switch (msg)
{
// ........
case WM_NCHITTEST: 
{
    int xPos, yPos;
    取得坐标(&xPos, &yPos, lParam);
    if (在希望产生NCLBUTTONUP的区域内(xPos, yPos))
    {
        return HTBORDER;
    }
}
// else : 继续: return DefWindowProc(hWnd, msg, wParam, lParam);
default:
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

将该部分代码放入消息处理回调,经过测试,在我需要该消息的一个固定尺寸的窗口上,它是可用的。因为WM_NCHITTEST会非常频繁的发送,因此对应于取得坐标、以及检测范围的函数应该尽可能的高效。

但是注意,因为我们将部分区域设置为了"边框",这或许会导致一些可调大小的窗口出现问题(我没有验证),在实际应用中应当再进行测试。

猜你喜欢

转载自blog.csdn.net/YanEast/article/details/105797614