Add some comments in Chinese.

有些东西用英文不会写,感觉还是用中文写得明白些,不过可能要辛苦国际友人了。

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2020-04-18 13:43:24 +08:00
parent 4e1d324100
commit 835e14aa04
1 changed files with 32 additions and 0 deletions

View File

@ -420,6 +420,31 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
} }
switch (msg->message) { switch (msg->message) {
case WM_NCCALCSIZE: { case WM_NCCALCSIZE: {
// Windows 是根据这个消息的返回值来设置窗口的客户区(窗口中真正显示的内容)和非客
// 户区(标题栏、窗口边框、菜单栏和状态栏等 Windows 提供的部分,不过对于 Qt 来说
// 除了标题栏和窗口边框非客户区基本也都是自绘的的范围的lParam里存放的就是
// 新客户区的几何区域,默认是整个窗口的大小,因此如果我们在这个消息中,不修改
// lParam就可以使客户区充满整个窗口从而去掉标题栏和窗口边框因为这些东西都被
// 客户区盖住了。但边框阴影也会因此而丢失,不过我们会使用其他方式将其带回)。但有个
// 情况要特别注意,那就是窗口最大化/全屏后,窗口的实际尺寸会比屏幕的尺寸大一点,从
// 而使用户看不到窗口的边界,这样用户就不能在窗口最大化后调整窗口的大小了(虽然这个
// 做法听起来特别奇怪,但 Windows 确实就是这样做的),因此如果我们要自行处理窗口
// 的非客户区,就要在窗口最大化后,将窗口边框的宽度和高度(一般是相等的)裁剪掉,
// 否则我们窗口所显示的内容就会超出屏幕边界,显示不全。
// 如果用户开启了任务栏自动隐藏,在窗口最大化后,还要考虑任务栏的位置。如果窗口最大
// 化后其尺寸和屏幕的可用尺寸裁去任务栏后的尺寸相等Windows 会认为窗口已经
// 进入全屏的状态,从而导致自动隐藏的任务栏无法弹出。要避免这个状况,就要使窗口的尺
// 寸小于屏幕的可用尺寸。我下面的做法参考了火狐和Chromium自己测了几次没发现
// 什么问题。如果没有开启任务栏自动隐藏,是没有这个问题的。
// 一般情况下,*result设置为0即DefWindowProcW的返回值为0就可以了根据MSDN
// 的说法返回0意为此消息已经被处理了让 Windows 跳过此消息,否则 Windows 会添
// 加对此消息的默认处理这当然不是我们想要的结果。根据MSDN当wParam为FALSE时
// 只能返回0当其为TRUE时可以返回0也可以返回一个WVR_XXX常量。根据Chromium
// 的注释,当存在非客户区时,如果返回 WVR_REDRAW 会导致子窗口/子控件出现奇怪的bug
// (自绘控件错位),并且 Lucas 在 Windows 10 上成功复现说明这个bug至今都没有
// 解决。这种情况下只有返回0才能规避这个问题。如果不存在非客户区且wParam为TRUE
// 最好返回WVR_REDRAW否则窗口在调整大小可能会产生严重的闪烁现象。
// Sent when the size and position of a window's client area must be // Sent when the size and position of a window's client area must be
// calculated. By processing this message, an application can control // calculated. By processing this message, an application can control
// the content of the window's client area when the size or position of // the content of the window's client area when the size or position of
@ -550,6 +575,8 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
return true; return true;
} }
case WM_NCPAINT: { case WM_NCPAINT: {
// 边框阴影处于非客户区的范围,因此如果直接阻止非客户区的绘制,会导致边框阴影丢失
if (IsDwmCompositionEnabled()) { if (IsDwmCompositionEnabled()) {
break; break;
} else { } else {
@ -569,6 +596,11 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
return true; return true;
} }
case WM_NCHITTEST: { case WM_NCHITTEST: {
// 测试了一下原生 Win32 窗口发现只有顶边是在窗口内部resize的其余三边都是
// 在窗口外部进行resize的但 WM_NCHITTEST 这个消息只有在鼠标进入窗口的范围
// 内才会被触发因此没法在这个消息里实现窗口外部的resize。火狐和Chromium是
// 怎么做到的Hook鼠标事件
if (data->windowData.mouseTransparent) { if (data->windowData.mouseTransparent) {
// Mouse events will be passed to the parent window. // Mouse events will be passed to the parent window.
*result = HTTRANSPARENT; *result = HTTRANSPARENT;