Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2020-04-09 21:57:45 +08:00
parent bffcc2829a
commit e6f0822175
2 changed files with 29 additions and 63 deletions

View File

@ -101,6 +101,12 @@
#define WM_DPICHANGED 0x02E0 #define WM_DPICHANGED 0x02E0
#endif #endif
#ifdef IsMinimized
#undef IsMinimized
#endif
#define IsMinimized m_lpIsIconic
#ifdef IsMaximized #ifdef IsMaximized
#undef IsMaximized #undef IsMaximized
#endif #endif
@ -189,6 +195,11 @@ WNEF_GENERATE_WINAPI(MonitorFromWindow, HMONITOR, HWND, DWORD)
WNEF_GENERATE_WINAPI(GetMonitorInfoW, BOOL, HMONITOR, LPMONITORINFO) WNEF_GENERATE_WINAPI(GetMonitorInfoW, BOOL, HMONITOR, LPMONITORINFO)
WNEF_GENERATE_WINAPI(GetAncestor, HWND, HWND, UINT) WNEF_GENERATE_WINAPI(GetAncestor, HWND, HWND, UINT)
WNEF_GENERATE_WINAPI(GetDesktopWindow, HWND) WNEF_GENERATE_WINAPI(GetDesktopWindow, HWND)
WNEF_GENERATE_WINAPI(SendMessageW, LRESULT, HWND, UINT, WPARAM, LPARAM)
WNEF_GENERATE_WINAPI(SetWindowPos, BOOL, HWND, HWND, int, int, int, int, UINT)
WNEF_GENERATE_WINAPI(UpdateWindow, BOOL, HWND)
WNEF_GENERATE_WINAPI(InvalidateRect, BOOL, HWND, CONST LPRECT, BOOL)
WNEF_GENERATE_WINAPI(SetWindowRgn, int, HWND, HRGN, BOOL)
const UINT m_defaultDotsPerInch = USER_DEFAULT_SCREEN_DPI; const UINT m_defaultDotsPerInch = USER_DEFAULT_SCREEN_DPI;
@ -344,7 +355,11 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
const auto data = reinterpret_cast<WINDOW *>( const auto data = reinterpret_cast<WINDOW *>(
m_lpGetWindowLongPtrW(msg->hwnd, GWLP_USERDATA)); m_lpGetWindowLongPtrW(msg->hwnd, GWLP_USERDATA));
if (!data->initialized) { if (!data->initialized) {
// Avoid initializing a same window twice.
data->initialized = TRUE; data->initialized = TRUE;
// The following two lines can help us get rid of the three system
// buttons (minimize, maximize and close). But they also break the
// Arcylic effect (introduced in Win10 1709), don't know why.
m_lpSetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE, m_lpSetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE,
m_lpGetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE) | m_lpGetWindowLongPtrW(msg->hwnd, GWL_EXSTYLE) |
WS_EX_LAYERED); WS_EX_LAYERED);
@ -456,7 +471,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
break; break;
} else { } else {
// Only block WM_NCPAINT when composition is disabled. If it's // Only block WM_NCPAINT when composition is disabled. If it's
// blocked when composition is enabled, the window shadow won't // blocked when composition is enabled, the frame shadow won't
// be drawn. // be drawn.
*result = 0; *result = 0;
return true; return true;
@ -640,55 +655,6 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
handleDwmCompositionChanged(data); handleDwmCompositionChanged(data);
break; break;
} }
#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
const auto dpiX = LOWORD(msg->wParam);
const auto dpiY = HIWORD(msg->wParam);
// dpiX and dpiY are identical. Just to silence a compiler warning.
const auto dpi = dpiX == dpiY ? dpiY : dpiX;
qDebug().noquote() << "Window DPI changed: new DPI -->" << dpi
<< ", new DPR -->"
<< getPreferedNumber(qreal(dpi) /
qreal(m_defaultDotsPerInch));
// Record the window handle now, don't use msg->hwnd directly because
// when we finally execute the function, it has changed.
const HWND _hWnd = msg->hwnd;
// Wait some time for Qt to adjust the window size, but don't wait too
// long, we want to refresh the window as soon as possible.
// We can intercept Qt's handling of this message and resize the window
// ourself, but after reading Qt's source code, I found that Qt does
// more than resizing, so it's safer to let Qt do the scaling.
QTimer::singleShot(50, [this, _hWnd]() {
RECT rect = {0, 0, 0, 0};
m_lpGetWindowRect(_hWnd, &rect);
const int x = rect.left;
const int y = rect.top;
const int width = std::abs(rect.right - rect.left);
const int height = std::abs(rect.bottom - rect.top);
// Don't increase the window size too much, otherwise it would be
// too obvious for the user and the experience is not good.
m_lpMoveWindow(_hWnd, x, y, width + 1, height + 1, TRUE);
// Re-paint the window after resizing.
redrawWindow(_hWnd);
// Restore and repaint.
m_lpMoveWindow(_hWnd, x, y, width, height, TRUE);
redrawWindow(_hWnd);
});
break;
}
default: { default: {
break; break;
} }
@ -702,17 +668,20 @@ void WinNativeEventFilter::handleDwmCompositionChanged(WINDOW *data) {
data->dwmCompositionEnabled = enabled; data->dwmCompositionEnabled = enabled;
MARGINS margins = {0, 0, 0, 0}; MARGINS margins = {0, 0, 0, 0};
if (enabled) { if (enabled) {
#if 0
// The frame shadow is drawn on the non-client area and thus we have // 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. // to make sure the non-client area rendering is enabled first.
const DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED; const DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED;
m_lpDwmSetWindowAttribute(data->hWnd, DWMWA_NCRENDERING_POLICY, &ncrp, m_lpDwmSetWindowAttribute(data->hWnd, DWMWA_NCRENDERING_POLICY, &ncrp,
sizeof(ncrp)); sizeof(ncrp));
#endif // Negative margins have special meaning to
margins = {0, 0, 1, 0}; // DwmExtendFrameIntoClientArea. Negative margins create the "sheet of
// glass" effect, where the client area is rendered as a solid surface
// with no window border.
// Use positive margins have similar appearance, but the window
// background will be transparent, we don't want that.
margins = {-1, -1, -1, -1};
} }
m_lpDwmExtendFrameIntoClientArea(data->hWnd, &margins); m_lpDwmExtendFrameIntoClientArea(data->hWnd, &margins);
redrawWindow(data->hWnd);
} }
UINT WinNativeEventFilter::getDotsPerInchForWindow(HWND handle) { UINT WinNativeEventFilter::getDotsPerInchForWindow(HWND handle) {
@ -823,6 +792,11 @@ void WinNativeEventFilter::createUserData(HWND handle, const WINDOWDATA *data) {
void WinNativeEventFilter::initWin32Api() { void WinNativeEventFilter::initWin32Api() {
// Available since Windows 2000. // Available since Windows 2000.
WNEF_RESOLVE_WINAPI(User32, SetWindowRgn)
WNEF_RESOLVE_WINAPI(User32, InvalidateRect)
WNEF_RESOLVE_WINAPI(User32, UpdateWindow)
WNEF_RESOLVE_WINAPI(User32, SetWindowPos)
WNEF_RESOLVE_WINAPI(User32, SendMessageW)
WNEF_RESOLVE_WINAPI(User32, GetDesktopWindow) WNEF_RESOLVE_WINAPI(User32, GetDesktopWindow)
WNEF_RESOLVE_WINAPI(User32, GetAncestor) WNEF_RESOLVE_WINAPI(User32, GetAncestor)
WNEF_RESOLVE_WINAPI(User32, DefWindowProcW) WNEF_RESOLVE_WINAPI(User32, DefWindowProcW)
@ -940,10 +914,3 @@ qreal WinNativeEventFilter::getPreferedNumber(qreal num) {
#endif #endif
return result; return result;
} }
void WinNativeEventFilter::redrawWindow(HWND handle) {
if (handle) {
m_lpRedrawWindow(handle, nullptr, nullptr,
RDW_INVALIDATE | RDW_ALLCHILDREN);
}
}

View File

@ -101,7 +101,6 @@ public:
private: private:
static void initWin32Api(); static void initWin32Api();
void redrawWindow(HWND handle);
static void createUserData(HWND handle, const WINDOWDATA *data = nullptr); static void createUserData(HWND handle, const WINDOWDATA *data = nullptr);
void handleDwmCompositionChanged(WINDOW *data); void handleDwmCompositionChanged(WINDOW *data);
static qreal getPreferedNumber(qreal num); static qreal getPreferedNumber(qreal num);