diff --git a/winnativeeventfilter.cpp b/winnativeeventfilter.cpp index 1f3ab9c..ca2ba3f 100644 --- a/winnativeeventfilter.cpp +++ b/winnativeeventfilter.cpp @@ -424,33 +424,36 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType, switch (msg->message) { case WM_NCCALCSIZE: { // Windows是根据这个消息的返回值来设置窗口的客户区(窗口中真正显示的内容) - // 和非客户区(标题栏、窗口边框、菜单栏和状态栏等Windows提供的部分,不过对 - // 于Qt来说,除了标题栏和窗口边框,非客户区基本也都是自绘的)的范围的, - // lParam里存放的就是新客户区的几何区域,默认是整个窗口的大小,因此如果我 - // 们在这个消息中,不修改lParam,就可以使客户区充满整个窗口,从而去掉标题 - // 栏和窗口边框(因为这些东西都被客户区盖住了。但边框阴影也会因此而丢失,不 - // 过我们会使用其他方式将其带回)。但有个情况要特别注意,那就是窗口最大化/ - // 全屏后,窗口的实际尺寸会比屏幕的尺寸大一点,从而使用户看不到窗口的边界, - // 这样用户就不能在窗口最大化后调整窗口的大小了(虽然这个做法听起来特别奇怪, - // 但Windows确实就是这样做的),因此如果我们要自行处理窗口的非客户区,就要 - // 在窗口最大化后,将窗口边框的宽度和高度(一般是相等的)裁剪掉,否则我们窗 - // 口所显示的内容就会超出屏幕边界,显示不全。 - // 如果用户开启了任务栏自动隐藏,在窗口最大化后,还要考虑任务栏的位置。如果 - // 窗口最大化后,其尺寸和屏幕的可用尺寸(裁去任务栏后的尺寸)相等,Windows - // 会认为窗口已经进入全屏的状态,从而导致自动隐藏的任务栏无法弹出。要避免这 - // 个状况,就要使窗口的尺寸小于屏幕的可用尺寸。我下面的做法,参考了火狐和 - // Chromium,自己测了几次,没发现什么问题。如果没有开启任务栏自动隐藏,是 - // 没有这个问题的。 + // 和非客户区(标题栏、窗口边框、菜单栏和状态栏等Windows系统自行提供的部分 + // ,不过对于Qt来说,除了标题栏和窗口边框,非客户区基本也都是自绘的)的范 + // 围的,lParam里存放的就是新客户区的几何区域,默认是整个窗口的大小,正常 + // 的程序需要修改这个参数,告知系统窗口的客户区和非客户区的范围(一般来说可 + // 以完全交给Windows,让其自行处理,使用默认的客户区和非客户区),因此如果 + // 我们不修改lParam,就可以使客户区充满整个窗口,从而去掉标题栏和窗口边框 + // (因为这些东西都被客户区给盖住了。但边框阴影也会因此而丢失,不过我们会使 + // 用其他方式将其带回,请参考其他消息的处理,此处不过多提及)。但有个情况要 + // 特别注意,那就是窗口最大化后,窗口的实际尺寸会比屏幕的尺寸大一点,从而使 + // 用户看不到窗口的边界,这样用户就不能在窗口最大化后调整窗口的大小了(虽然 + // 这个做法听起来特别奇怪,但Windows确实就是这样做的),因此如果我们要自行 + // 处理窗口的非客户区,就要在窗口最大化后,将窗口边框的宽度和高度(一般是相 + // 等的)从客户区裁剪掉,否则我们窗口所显示的内容就会超出屏幕边界,显示不全。 + // 如果用户开启了任务栏自动隐藏,在窗口最大化后,还要考虑任务栏的位置。因为 + // 如果窗口最大化后,其尺寸和屏幕尺寸相等(因为任务栏隐藏了,所以窗口最大化 + // 后其实是充满了整个屏幕,变相的全屏了),Windows会认为窗口已经进入全屏的 + // 状态,从而导致自动隐藏的任务栏无法弹出。要避免这个状况,就要使窗口的尺寸 + // 小于屏幕尺寸。我下面的做法,参考了火狐和Chromium。但是如果没有开启任务 + // 栏自动隐藏,是不存在这个问题的,所以要先进行判断。 // 一般情况下,*result设置为0(相当于DefWindowProc的返回值为0)就可以了, // 根据MSDN的说法,返回0意为此消息已经被程序自行处理了,让Windows跳过此消 - // 息,否则Windows会添加对此消息的默认处理,标题栏和窗口边框又会回来,这当 - // 然不是我们想要的结果。根据MSDN,当wParam为FALSE时,只能返回0,但当其为 - // TRUE时,可以返回0,也可以返回一个WVR_XXX常量。根据Chromium的注释,当 - // 存在非客户区时,如果返回WVR_REDRAW会导致子窗口/子控件出现奇怪的bug - // (自绘控件错位或停止刷新),并且Lucas在Windows 10上成功复现,说明这个 - // bug至今都没有解决。因为这个是Windows自身的bug,且已经存在很久,这种情 - // 况下只有返回0才能规避这个问题。但如果不存在非客户区,且wParam为TRUE, - // 最好返回WVR_REDRAW,否则窗口在调整大小可能会产生严重的闪烁现象。 + // 息,否则Windows会添加对此消息的默认处理,对于当前这个消息而言,就意味着 + // 标题栏和窗口边框又会回来,这当然不是我们想要的结果。根据MSDN,当wParam + // 为FALSE时,只能返回0,但当其为TRUE时,可以返回0,也可以返回一个WVR_常 + // 量。根据Chromium的注释,当存在非客户区时,如果返回WVR_REDRAW会导致子 + // 窗口/子控件出现奇怪的bug(自绘控件错位),并且Lucas在Windows 10上成 + // 功复现,说明这个bug至今都没有解决。因为这个是Windows自身的bug,且已经 + // 存在很久,这种情况下只有返回0才能规避这个问题。但如果不存在非客户区,且 + // wParam为TRUE,最好返回WVR_REDRAW,否则窗口在调整大小可能会产生严重的 + // 闪烁现象。 // 虽然对大多数消息来说,返回0都代表让Windows忽略此消息,但实际上不同消息 // 能接受的返回值是不一样的,请注意自行查阅MSDN。