当事件发生在 child 上时,我如何启动用户 mouse-driven 移动或调整 Windows 上的自定义 window 边框在无边框 window 上?
How do I initiate a user mouse-driven move or resize for custom window borders on Windows on a borderless window when the event comes to a child?
我有一个无边框的 window,其唯一的 child 始终是 window 的大小,是第三方组件。该组件希望能够通知我,当 WM_MOUSEDOWN
发生在某些区域时,由它自行决定移动或调整 window 的大小(就像它不是无边界的一样)。它还想决定要使用的事件。
因为window是无边框的,而childwindow已经收到了鼠标消息,我想我无法覆盖WM_NCHITTEST
,我可以吗? (或者换句话说,parent window 总是在我的 child 获得 WM_LBUTTONDOWN
之前获得 WM_NCHITTEST
吗?还是仅在第一次 activation/during 捕获?)
GTK+ 过去常常用 WM_NCLBUTTONDOWN
调用 DefWindowProc()
来手动触发模态事件循环。这是方法吗?
WM_SYSCOMMAND
中的SC_MOVE
呢?这是否仅适用于 keyboard-driven window 移动和调整大小,而不适用于 mouse-driven 移动和调整大小?
还是我必须手动执行此操作?我知道它自己是一个模态循环,它使用消息过滤器常量之一,而且我知道 Aero Snap 至少需要手动完成。
我需要在 Windows Vista 或更高版本上执行此操作。
谢谢。
由于你的 parent window 是 border-less 并且完全被 child window 覆盖,parent 将不会收到 WM_NCHITTEST
默认。 child 将首先收到所有 WM_NCHITTEST
条消息。
但是,您仍然可以允许用户通过一些额外的编码正常调整 parent window 的大小。您可以通过几种不同的方式处理此问题:
子类 child window 以拦截 WM_NCHITTEST
消息。收到后,先将消息传递给child的默认消息处理程序,如果returns HTCLIENT
和lParam
中提供的屏幕坐标在一个区域内要用于调整大小的 parent window,改为 return HTTRANSPARENT
。这将导致 WM_NCHITTEST
接下来被发送到 parent window,然后它可以根据类型处理 WM_NCHITTEST
和 return 以下值之一调整大小:
HTBOTTOM
HTBOTTOMLEFT
HTBOTTOMRIGHT
HTLEFT
HTRIGHT
HTTOP
HTTOPLEFT
HTTOPRIGHT
在childwindow的mousedown事件中,将提供的鼠标客户端坐标转换成屏幕坐标,然后调用ReleaseCapture()
发送一个WM_NCLBUTTONDOWN
消息到 parent window,将 wParam
设置为上述值之一,并将 lParam
设置为屏幕坐标。
在childwindow的mousedown事件中,调用ReleaseCapture()
发送WM_SYSCOMMAND
消息给parentwindow,将 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
任何一种方式都将允许 parent window 正常调整大小,以及涉及的所有内容(鼠标跟踪、捕捉等),除了一件事。 #1 欺骗 OS 认为用户直接将鼠标悬停在 parent window 上,因此它允许 OS 提供有关 "sizing border" 的视觉反馈正在被使用。 #2 和 #3 不会提供任何视觉反馈,因此如果需要,您必须通过 SetCursor()
手动处理。
如果您希望允许用户拖动 parent window 而不调整它的大小,您可以:
子类 child WM_NCHITTEST
消息到 return HTTRANSPARENT
在适当的区域,然后有 parent window 处理 WM_NCHITTEST
到 return HTCAPTION
.
在childwindow的mousedown事件中,调用ReleaseCapture()
发送WM_SYSCOMMAND
消息给parentwindow,将 wParam
设置为 SC_DRAGMOVE
(未记录,但其值为 $F012
,又名 SC_MOVE + 2
),并将 lParam
设置为 0。
我有一个无边框的 window,其唯一的 child 始终是 window 的大小,是第三方组件。该组件希望能够通知我,当 WM_MOUSEDOWN
发生在某些区域时,由它自行决定移动或调整 window 的大小(就像它不是无边界的一样)。它还想决定要使用的事件。
因为window是无边框的,而childwindow已经收到了鼠标消息,我想我无法覆盖WM_NCHITTEST
,我可以吗? (或者换句话说,parent window 总是在我的 child 获得 WM_LBUTTONDOWN
之前获得 WM_NCHITTEST
吗?还是仅在第一次 activation/during 捕获?)
GTK+ 过去常常用 WM_NCLBUTTONDOWN
调用 DefWindowProc()
来手动触发模态事件循环。这是方法吗?
WM_SYSCOMMAND
中的SC_MOVE
呢?这是否仅适用于 keyboard-driven window 移动和调整大小,而不适用于 mouse-driven 移动和调整大小?
还是我必须手动执行此操作?我知道它自己是一个模态循环,它使用消息过滤器常量之一,而且我知道 Aero Snap 至少需要手动完成。
我需要在 Windows Vista 或更高版本上执行此操作。
谢谢。
由于你的 parent window 是 border-less 并且完全被 child window 覆盖,parent 将不会收到 WM_NCHITTEST
默认。 child 将首先收到所有 WM_NCHITTEST
条消息。
但是,您仍然可以允许用户通过一些额外的编码正常调整 parent window 的大小。您可以通过几种不同的方式处理此问题:
子类 child window 以拦截
WM_NCHITTEST
消息。收到后,先将消息传递给child的默认消息处理程序,如果returnsHTCLIENT
和lParam
中提供的屏幕坐标在一个区域内要用于调整大小的 parent window,改为 returnHTTRANSPARENT
。这将导致WM_NCHITTEST
接下来被发送到 parent window,然后它可以根据类型处理WM_NCHITTEST
和 return 以下值之一调整大小:HTBOTTOM HTBOTTOMLEFT HTBOTTOMRIGHT HTLEFT HTRIGHT HTTOP HTTOPLEFT HTTOPRIGHT
在childwindow的mousedown事件中,将提供的鼠标客户端坐标转换成屏幕坐标,然后调用
ReleaseCapture()
发送一个WM_NCLBUTTONDOWN
消息到 parent window,将wParam
设置为上述值之一,并将lParam
设置为屏幕坐标。在childwindow的mousedown事件中,调用
ReleaseCapture()
发送WM_SYSCOMMAND
消息给parentwindow,将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
任何一种方式都将允许 parent window 正常调整大小,以及涉及的所有内容(鼠标跟踪、捕捉等),除了一件事。 #1 欺骗 OS 认为用户直接将鼠标悬停在 parent window 上,因此它允许 OS 提供有关 "sizing border" 的视觉反馈正在被使用。 #2 和 #3 不会提供任何视觉反馈,因此如果需要,您必须通过 SetCursor()
手动处理。
如果您希望允许用户拖动 parent window 而不调整它的大小,您可以:
子类 child
WM_NCHITTEST
消息到 returnHTTRANSPARENT
在适当的区域,然后有 parent window 处理WM_NCHITTEST
到 returnHTCAPTION
.在childwindow的mousedown事件中,调用
ReleaseCapture()
发送WM_SYSCOMMAND
消息给parentwindow,将wParam
设置为SC_DRAGMOVE
(未记录,但其值为$F012
,又名SC_MOVE + 2
),并将lParam
设置为 0。