Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2020-04-09 16:10:56 +08:00
parent fe9ee701db
commit ad2f7af71a
1 changed files with 35 additions and 32 deletions

View File

@ -296,6 +296,9 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
if (m_framelessWindows.isEmpty()) {
// Only top level windows can be frameless.
// Try to avoid this case because it will result in strange behavior, use addFramelessWindow if possible.
if (GetWindowLongPtrW(msg->hwnd, GWL_STYLE) & WS_CHILD) {
return false;
}
const HWND parent = GetAncestor(msg->hwnd, GA_PARENT);
if (parent && (parent != GetDesktopWindow())) {
return false;
@ -308,9 +311,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
reinterpret_cast<WINDOW *>(GetWindowLongPtrW(msg->hwnd, GWLP_USERDATA));
if (!data->initialized) {
data->initialized = TRUE;
// The following two lines are necessary to remove the three system buttons (minimize, maximize and close),
// but they will make the Acrylic (available since Win10 1709) unusable.
SetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_LAYERED);
SetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE, GetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(msg->hwnd, RGB(255, 0, 255), 0, LWA_COLORKEY);
// Make sure our window have it's frame shadow.
// The frame shadow is drawn by Desktop Window Manager (DWM), don't draw it yourself.
@ -333,7 +334,8 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
// Sent when the size and position of a window's client area must be calculated. By processing this message, an application can control the content of the window's client area when the size or position of the window changes.
// If wParam is TRUE, lParam points to an NCCALCSIZE_PARAMS structure that contains information an application can use to calculate the new size and position of the client rectangle.
// If wParam is FALSE, lParam points to a RECT structure. On entry, the structure contains the proposed window rectangle for the window. On exit, the structure should contain the screen coordinates of the corresponding window client area.
auto &rect = static_cast<BOOL>(msg->wParam) ? (*reinterpret_cast<LPNCCALCSIZE_PARAMS>(msg->lParam)).rgrc[0] : *reinterpret_cast<LPRECT>(msg->lParam);
const auto mode = static_cast<BOOL>(msg->wParam);
const auto rect = mode ? &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(msg->lParam)->rgrc[0]) : reinterpret_cast<LPRECT>(msg->lParam);
if (IsMaximized(msg->hwnd)) {
const HMONITOR windowMonitor =
MonitorFromWindow(msg->hwnd, MONITOR_DEFAULTTONEAREST);
@ -341,7 +343,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
SecureZeroMemory(&monitorInfo, sizeof(monitorInfo));
monitorInfo.cbSize = sizeof(monitorInfo);
GetMonitorInfoW(windowMonitor, &monitorInfo);
rect = monitorInfo.rcWork;
*rect = monitorInfo.rcWork;
// If the client rectangle is the same as the monitor's
// rectangle, the shell assumes that the window has gone
// fullscreen, so it removes the topmost attribute from any
@ -372,28 +374,27 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
}
}
if (edge == ABE_BOTTOM) {
rect.bottom--;
rect->bottom--;
} else if (edge == ABE_LEFT) {
rect.left++;
rect->left++;
} else if (edge == ABE_TOP) {
rect.top++;
rect->top++;
} else if (edge == ABE_RIGHT) {
rect.right--;
rect->right--;
}
}
}
// We cannot return WVR_REDRAW when there is nonclient area, or Windows
// exhibits bugs where client pixels and child HWNDs are mispositioned by
// the width/height of the upper-left nonclient area.
*result = 0;
return true;
}
// If the wParam parameter is FALSE, the application should return zero.
// If wParam is TRUE and an application returns zero, the old client area is preserved and is aligned with the upper-left corner of the new client area.
// "*result = 0" removes the window frame (including the titlebar).
// Don't use "*result = WVR_REDRAW", although it can also remove
// the window frame, it will cause child widgets have strange behaviors.
// "*result = 0" means we have processed this message and let Windows
// ignore it to avoid Windows process this message again.
// "return true" means we have filtered this message and let Qt ignore
// it, in other words, it'll block Qt's own handling of this message,
// so if you don't know what Qt does internally, don't block it.
*result = 0;
// If the window bounds change, we're going to relayout and repaint anyway.
// Returning WVR_REDRAW avoids an extra paint before that of the old client
// pixels in the (now wrong) location, and thus makes actions like resizing a
// window from the left edge look slightly less broken.
*result = mode ? WVR_REDRAW : 0;
return true;
}
case WM_NCUAHDRAWCAPTION:
@ -585,15 +586,20 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
handleDwmCompositionChanged(data);
break;
}
case WM_THEMECHANGED:
case WM_WINDOWPOSCHANGING:
case WM_WINDOWPOSCHANGED: {
#if 1
case WM_SIZE: {
#if 1
const HWND _hWnd = msg->hwnd;
QTimer::singleShot(50, [this, _hWnd](){
redrawWindow(_hWnd);
});
#else
InvalidateRect(msg->hwnd, nullptr, FALSE);
redrawWindow(msg->hwnd);
#endif
break;
}
#endif
case WM_DPICHANGED: {
// Qt will do the scaling internally and automatically.
// See: qt/qtbase/src/plugins/platforms/windows/qwindowscontext.cpp
@ -642,19 +648,18 @@ void WinNativeEventFilter::handleDwmCompositionChanged(WINDOW *data) {
BOOL enabled = FALSE;
m_lpDwmIsCompositionEnabled(&enabled);
data->dwmCompositionEnabled = enabled;
MARGINS margins = {0, 0, 0, 0};
if (enabled) {
#if 0
// The frame shadow is drawn on the non-client area and thus we have
// to make sure the non-client area rendering is enabled first.
const DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED;
m_lpDwmSetWindowAttribute(data->hWnd, DWMWA_NCRENDERING_POLICY, &ncrp,
sizeof(ncrp));
// Negative margins have special meaning to
// DwmExtendFrameIntoClientArea. Negative margins create the "sheet
// of glass" effect, where the client area is rendered as a solid
// surface with no window border.
const MARGINS margins = {-1, -1, -1, -1};
m_lpDwmExtendFrameIntoClientArea(data->hWnd, &margins);
#endif
margins = {0, 0, 1, 0};
}
m_lpDwmExtendFrameIntoClientArea(data->hWnd, &margins);
redrawWindow(data->hWnd);
}
@ -864,8 +869,6 @@ qreal WinNativeEventFilter::getPreferedNumber(qreal num) {
void WinNativeEventFilter::redrawWindow(HWND handle)
{
if (handle) {
RedrawWindow(handle, nullptr, nullptr,
RDW_INVALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT |
RDW_ERASENOW | RDW_ALLCHILDREN);
RedrawWindow(handle, nullptr, nullptr, RDW_INVALIDATE | RDW_ALLCHILDREN);
}
}