当事件发生在子窗口时,如何在无边界窗口上启动用户鼠标驱动的移动或调整自定义窗口边框的大小



我有一个无边界窗口,其唯一的子窗口(始终是窗口的大小)是第三方组件。该组件希望能够通知我,当一个WM_MOUSEDOWN发生在某些区域,这是由它的自由裁量权,移动或调整窗口的大小(如果它不是无边界的)。它还想决定要使用的事件。

因为窗口是无边界的,子窗口已经收到了鼠标消息,我认为我不能覆盖WM_NCHITTEST,是吗?(或者换句话说,父窗口总是在我的孩子得到WM_LBUTTONDOWN之前得到WM_NCHITTEST吗?)还是只在第一次激活/捕获期间?)

GTK+使用WM_NCLBUTTONDOWN调用DefWindowProc()手动触发模态事件循环。这是正确的做法吗?

WM_SYSCOMMAND中的SC_MOVE呢?这只适用于键盘驱动的窗口移动和大小调整,而不是鼠标驱动的?

还是我必须手动执行?我知道它是一个自己的模态循环,使用一个消息过滤器常量,我知道Aero Snap需要手动完成,至少。

我需要在Windows Vista或更高版本上执行此操作。

谢谢。

由于父窗口是无边框的,并且完全被子窗口覆盖,父窗口默认不会接收WM_NCHITTEST。所有WM_NCHITTEST消息将首先由子节点接收。

但是,您仍然可以允许用户通过一些额外的编码正常地调整父窗口的大小。有几种不同的方法可以处理这个问题:

  1. 子类化子窗口来拦截WM_NCHITTEST消息。当收到消息时,首先将消息传递给子消息的默认消息处理程序,如果它返回HTCLIENT,并且lParam中提供的屏幕坐标在父窗口的一个区域内,您想要用于调整大小,则返回HTTRANSPARENT。这将导致WM_NCHITTEST接下来被发送到父窗口,然后父窗口可以处理WM_NCHITTEST并根据您想要的大小调整类型返回以下值之一:

    HTBOTTOM
    HTBOTTOMLEFT
    HTBOTTOMRIGHT
    HTLEFT
    HTRIGHT
    HTTOP
    HTTOPLEFT
    HTTOPRIGHT
    
  2. 在子窗口的mousedown事件中,将提供的鼠标客户端坐标转换为屏幕坐标,然后调用ReleaseCapture()并向父窗口发送WM_NCLBUTTONDOWN消息,将wParam设置为上述值之一,将lParam设置为屏幕坐标。

  3. 在子窗口的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()手动处理。

如果你想允许用户拖动父窗口而不调整它的大小,你可以:

  1. 子类化子WM_NCHITTEST消息返回相应区域的HTTRANSPARENT,然后让父窗口处理WM_NCHITTEST返回HTCAPTION

  2. 在子窗口的mousedown事件中,调用ReleaseCapture()并向父窗口发送WM_SYSCOMMAND消息,将wParam设置为SC_DRAGMOVE(未记录,但其值为$F012,即SC_MOVE + 2),将lParam设置为0。

最新更新