我有一个无边框窗口,其唯一的子窗口(总是窗口大小)是第三方组件。该组件希望能够在某些区域发生WM_MOUSEDOWN
时通知我,以便移动窗口或调整窗口大小(就好像它不是无边界的)。它还想决定要使用的事件。
因为窗口是无边框的并且子窗口已经收到鼠标消息,所以我认为我无法覆盖WM_NCHITTEST
,是吗? (换句话说,在我的孩子获得WM_NCHITTEST
之前,父窗口是否总是得到WM_LBUTTONDOWN
?或者只在第一次激活/捕获期间?{/ p>
GTK +曾用DefWindowProc()
调用WM_NCLBUTTONDOWN
来手动触发该模态事件循环。这是这样做的吗?
SC_MOVE
中WM_SYSCOMMAND
怎么样?这仅适用于键盘驱动的窗口移动和调整大小,而不是鼠标驱动的窗口吗?
或者我是否必须手动执行此操作?我知道它是一个自己的模态循环,它使用了一个消息过滤器常量,我知道Aero Snap至少需要手动完成。
我需要在Windows Vista或更高版本上执行此操作。
感谢。
答案 0 :(得分:3)
由于您的父窗口是无边框并且完全由子窗口覆盖,因此默认情况下父窗口不会收到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
消息,设置{{ 1}}到上面提到的值之一,并wParam
到屏幕坐标。
在子窗口的mousedown事件中,拨打lParam
并向父窗口发送ReleaseCapture()
消息,将WM_SYSCOMMAND
设置为wParam
加上下面所需的值,和SC_SIZE
到0:
lParam
无论哪种方式都允许父窗口正常调整大小,以及涉及(鼠标跟踪,捕捉等)的所有内容,除了一件事。 #1欺骗操作系统认为用户已经直接在父窗口上进行了挖掘,因此它允许操作系统提供关于正在使用哪个“大小边界”的视觉反馈。 #2和#3不会提供任何视觉反馈,因此如果需要,您必须通过 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
手动处理。
如果您想允许用户拖动父窗口而不调整其大小,您可以:
将子SetCursor()
消息子类化为在适当的区域中返回WM_NCHITTEST
,然后让父窗口处理HTTRANSPARENT
以返回WM_NCHITTEST
。
在子窗口的mousedown事件中,调用HTCAPTION
并向父窗口发送ReleaseCapture()
消息,将WM_SYSCOMMAND
设置为wParam
(未记录,但其值为SC_DRAGMOVE
,又称$F012
),SC_MOVE + 2
设置为0.