我有一个无边界窗口,其唯一的子窗口(始终是窗口的大小)是第三方组件。该组件希望能够通知我,当一个WM_MOUSEDOWN
发生在某些区域,这是由它的自由裁量权,移动或调整窗口的大小(如果它不是无边界的)。它还想决定要使用的事件。
因为窗口是无边界的,子窗口已经收到了鼠标消息,我认为我不能覆盖WM_NCHITTEST
,是吗?(或者换句话说,父窗口总是在我的孩子得到WM_LBUTTONDOWN
之前得到WM_NCHITTEST
吗?)还是只在第一次激活/捕获期间?)
GTK+使用WM_NCLBUTTONDOWN
调用DefWindowProc()
手动触发模态事件循环。这是正确的做法吗?
WM_SYSCOMMAND
中的SC_MOVE
呢?这只适用于键盘驱动的窗口移动和大小调整,而不是鼠标驱动的?
还是我必须手动执行?我知道它是一个自己的模态循环,使用一个消息过滤器常量,我知道Aero Snap需要手动完成,至少。
我需要在Windows Vista或更高版本上执行此操作。
谢谢。
由于父窗口是无边框的,并且完全被子窗口覆盖,父窗口默认不会接收WM_NCHITTEST
。所有WM_NCHITTEST
消息将首先由子节点接收。
但是,您仍然可以允许用户通过一些额外的编码正常地调整父窗口的大小。有几种不同的方法可以处理这个问题:
-
子类化子窗口来拦截
WM_NCHITTEST
消息。当收到消息时,首先将消息传递给子消息的默认消息处理程序,如果它返回HTCLIENT
,并且lParam
中提供的屏幕坐标在父窗口的一个区域内,您想要用于调整大小,则返回HTTRANSPARENT
。这将导致WM_NCHITTEST
接下来被发送到父窗口,然后父窗口可以处理WM_NCHITTEST
并根据您想要的大小调整类型返回以下值之一:HTBOTTOM HTBOTTOMLEFT HTBOTTOMRIGHT HTLEFT HTRIGHT HTTOP HTTOPLEFT HTTOPRIGHT
-
在子窗口的mousedown事件中,将提供的鼠标客户端坐标转换为屏幕坐标,然后调用
ReleaseCapture()
并向父窗口发送WM_NCLBUTTONDOWN
消息,将wParam
设置为上述值之一,将lParam
设置为屏幕坐标。 -
在子窗口的mousedown事件中,调用
ReleaseCapture()
并向父窗口发送WM_SYSCOMMAND
消息,将wParam
设置为SC_SIZE
加上下面所需的值,将lParam
设置为0:SC_SIZE_HTLEFT = 1 SC_SIZE_HTRIGHT = 2 SC_SIZE_HTTOP = 3 SC_SIZE_HTTOPLEFT = 4 SC_SIZE_HTTOPRIGHT = 5 SC_SIZE_HTBOTTOM = 6 SC_SIZE_HTBOTTOMLEFT = 7 SC_SIZE_HTBOTTOMRIGHT = 8
无论哪种方式都允许父窗口正常调整大小,以及涉及的所有内容(鼠标跟踪,捕捉等),除了一件事。#1让操作系统误以为用户直接将鼠标移到了父窗口上,因此它允许操作系统提供关于正在使用的"大小边界"的视觉反馈。#2和#3不会提供任何视觉反馈,所以如果需要的话,你必须通过SetCursor()
手动处理。
如果你想允许用户拖动父窗口而不调整它的大小,你可以:
-
子类化子
WM_NCHITTEST
消息返回相应区域的HTTRANSPARENT
,然后让父窗口处理WM_NCHITTEST
返回HTCAPTION
。 -
在子窗口的mousedown事件中,调用
ReleaseCapture()
并向父窗口发送WM_SYSCOMMAND
消息,将wParam
设置为SC_DRAGMOVE
(未记录,但其值为$F012
,即SC_MOVE + 2
),将lParam
设置为0。