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

时间:2016-10-25 21:22:55

标签: winapi events user32

我有一个无边框窗口,其唯一的子窗口(总是窗口大小)是第三方组件。该组件希望能够在某些区域发生WM_MOUSEDOWN时通知我,以便移动窗口或调整窗口大小(就好像它不是无边界的)。它还想决定要使用的事件。

因为窗口是无边框的并且子窗口已经收到鼠标消息,所以我认为我无法覆盖WM_NCHITTEST,是吗? (换句话说,在我的孩子获得WM_NCHITTEST之前,父窗口是否总是得到WM_LBUTTONDOWN?或者只在第一次激活/捕获期间?{/ p>

GTK +曾用DefWindowProc()调用WM_NCLBUTTONDOWN来手动触发该模态事件循环。这是这样做的吗?

SC_MOVEWM_SYSCOMMAND怎么样?这仅适用于键盘驱动的窗口移动和调整大小,而不是鼠标驱动的窗口吗?

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

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

感谢。

1 个答案:

答案 0 :(得分:3)

由于您的父窗口是无边框并且完全由子窗口覆盖,因此默认情况下父窗口不会收到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消息,设置{{ 1}}到上面提到的值之一,并wParam到屏幕坐标。

  3. 在子窗口的mousedown事件中,拨打lParam并向父窗口发送ReleaseCapture()消息,将WM_SYSCOMMAND设置为wParam加上下面所需的值,和SC_SIZE到0:

    lParam
  4. 无论哪种方式都允许父窗口正常调整大小,以及涉及(鼠标跟踪,捕捉等)的所有内容,除了一件事。 #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 手动处理。

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

    1. 将子SetCursor()消息子类化为在适当的区域中返回WM_NCHITTEST,然后让父窗口处理HTTRANSPARENT以返回WM_NCHITTEST

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