parent
0411a761e5
commit
729f63faff
15
README.md
15
README.md
|
@ -60,6 +60,8 @@ Notes
|
||||||
- <https://docs.microsoft.com/en-us/archive/blogs/wpfsdk/custom-window-chrome-in-wpf>
|
- <https://docs.microsoft.com/en-us/archive/blogs/wpfsdk/custom-window-chrome-in-wpf>
|
||||||
- <https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize>
|
- <https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize>
|
||||||
- <https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-nchittest>
|
- <https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-nchittest>
|
||||||
|
- <https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-ncactivate>
|
||||||
|
- <https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-erasebkgnd>
|
||||||
- <https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-getminmaxinfo>
|
- <https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-getminmaxinfo>
|
||||||
- <https://docs.microsoft.com/en-us/windows/win32/dwm/customframe>
|
- <https://docs.microsoft.com/en-us/windows/win32/dwm/customframe>
|
||||||
- <https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows>
|
- <https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows>
|
||||||
|
@ -69,6 +71,10 @@ Notes
|
||||||
- <https://github.com/chromium/chromium/blob/master/ui/base/win/hwnd_metrics.cc>
|
- <https://github.com/chromium/chromium/blob/master/ui/base/win/hwnd_metrics.cc>
|
||||||
- <https://github.com/chromium/chromium/blob/master/ui/display/win/screen_win.cc>
|
- <https://github.com/chromium/chromium/blob/master/ui/display/win/screen_win.cc>
|
||||||
- <https://github.com/chromium/chromium/blob/master/ui/views/win/hwnd_message_handler.cc>
|
- <https://github.com/chromium/chromium/blob/master/ui/views/win/hwnd_message_handler.cc>
|
||||||
|
- <https://github.com/chromium/chromium/blob/master/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc>
|
||||||
|
- <https://github.com/chromium/chromium/blob/master/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc>
|
||||||
|
- <https://github.com/chromium/chromium/blob/master/ui/views/widget/native_widget_aura.cc>
|
||||||
|
- <https://github.com/chromium/chromium/blob/master/ui/views/widget/widget.cc>
|
||||||
|
|
||||||
### Mozilla Firefox
|
### Mozilla Firefox
|
||||||
|
|
||||||
|
@ -81,6 +87,15 @@ Notes
|
||||||
- <https://github.com/dfct/TrueFramelessWindow>
|
- <https://github.com/dfct/TrueFramelessWindow>
|
||||||
- <https://github.com/qtdevs/FramelessHelper>
|
- <https://github.com/qtdevs/FramelessHelper>
|
||||||
|
|
||||||
|
### Qt
|
||||||
|
|
||||||
|
- <https://doc.qt.io/qt-5/qcoreapplication.html#installNativeEventFilter>
|
||||||
|
- <https://doc.qt.io/qt-5/qcoreapplication.html#removeNativeEventFilter>
|
||||||
|
- <https://doc.qt.io/qt-5/qobject.html#installEventFilter>
|
||||||
|
- <https://doc.qt.io/qt-5/qobject.html#removeEventFilter>
|
||||||
|
- <https://doc.qt.io/qt-5/qwindow.html#startSystemMove>
|
||||||
|
- <https://doc.qt.io/qt-5/qwindow.html#startSystemResize>
|
||||||
|
|
||||||
## Special Thanks
|
## Special Thanks
|
||||||
|
|
||||||
Thanks **Lucas** for testing this code in many various conditions.
|
Thanks **Lucas** for testing this code in many various conditions.
|
||||||
|
|
|
@ -199,12 +199,39 @@ WNEF_GENERATE_WINAPI(SetWindowPos, BOOL, HWND, HWND, int, int, int, int, UINT)
|
||||||
WNEF_GENERATE_WINAPI(UpdateWindow, BOOL, HWND)
|
WNEF_GENERATE_WINAPI(UpdateWindow, BOOL, HWND)
|
||||||
WNEF_GENERATE_WINAPI(InvalidateRect, BOOL, HWND, CONST LPRECT, BOOL)
|
WNEF_GENERATE_WINAPI(InvalidateRect, BOOL, HWND, CONST LPRECT, BOOL)
|
||||||
WNEF_GENERATE_WINAPI(SetWindowRgn, int, HWND, HRGN, BOOL)
|
WNEF_GENERATE_WINAPI(SetWindowRgn, int, HWND, HRGN, BOOL)
|
||||||
|
WNEF_GENERATE_WINAPI(IsWindow, BOOL, HWND)
|
||||||
|
WNEF_GENERATE_WINAPI(GetWindowInfo, BOOL, HWND, LPWINDOWINFO)
|
||||||
|
WNEF_GENERATE_WINAPI(CreateSolidBrush, HBRUSH, COLORREF)
|
||||||
|
WNEF_GENERATE_WINAPI(FillRect, int, HDC, CONST LPRECT, HBRUSH)
|
||||||
|
WNEF_GENERATE_WINAPI(DeleteObject, BOOL, HGDIOBJ)
|
||||||
|
|
||||||
BOOL isCompositionEnabled() {
|
BOOL IsDwmCompositionEnabled() {
|
||||||
|
// Since Win8, DWM composition is always enabled and can't be disabled.
|
||||||
BOOL enabled = FALSE;
|
BOOL enabled = FALSE;
|
||||||
return SUCCEEDED(m_lpDwmIsCompositionEnabled(&enabled)) && enabled;
|
return SUCCEEDED(m_lpDwmIsCompositionEnabled(&enabled)) && enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL IsFullScreen(HWND handle) {
|
||||||
|
if (handle && m_lpIsWindow(handle)) {
|
||||||
|
WINDOWINFO windowInfo;
|
||||||
|
SecureZeroMemory(&windowInfo, sizeof(windowInfo));
|
||||||
|
windowInfo.cbSize = sizeof(windowInfo);
|
||||||
|
m_lpGetWindowInfo(handle, &windowInfo);
|
||||||
|
MONITORINFO monitorInfo;
|
||||||
|
SecureZeroMemory(&monitorInfo, sizeof(monitorInfo));
|
||||||
|
monitorInfo.cbSize = sizeof(monitorInfo);
|
||||||
|
const HMONITOR monitor =
|
||||||
|
m_lpMonitorFromWindow(handle, MONITOR_DEFAULTTONEAREST);
|
||||||
|
m_lpGetMonitorInfoW(monitor, &monitorInfo);
|
||||||
|
// The only way to judge whether a window is fullscreened or not
|
||||||
|
// is to compare it's size with the screen's size, there is no official
|
||||||
|
// Win32 API to do this for us.
|
||||||
|
return m_lpEqualRect(&windowInfo.rcWindow, &monitorInfo.rcMonitor) ||
|
||||||
|
m_lpEqualRect(&windowInfo.rcClient, &monitorInfo.rcMonitor);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
// The thickness of an auto-hide taskbar in pixels.
|
// The thickness of an auto-hide taskbar in pixels.
|
||||||
const int kAutoHideTaskbarThicknessPx = 2;
|
const int kAutoHideTaskbarThicknessPx = 2;
|
||||||
const int kAutoHideTaskbarThicknessPy = kAutoHideTaskbarThicknessPx;
|
const int kAutoHideTaskbarThicknessPy = kAutoHideTaskbarThicknessPx;
|
||||||
|
@ -288,7 +315,7 @@ int WinNativeEventFilter::borderWidth(HWND handle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_borderWidth > 0) {
|
if (m_borderWidth > 0) {
|
||||||
return m_borderWidth;
|
return std::round(m_borderWidth * getDevicePixelRatioForWindow(handle));
|
||||||
}
|
}
|
||||||
return getSystemMetricsForWindow(handle, SM_CXFRAME) +
|
return getSystemMetricsForWindow(handle, SM_CXFRAME) +
|
||||||
getSystemMetricsForWindow(handle, SM_CXPADDEDBORDER);
|
getSystemMetricsForWindow(handle, SM_CXPADDEDBORDER);
|
||||||
|
@ -306,7 +333,8 @@ int WinNativeEventFilter::borderHeight(HWND handle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_borderHeight > 0) {
|
if (m_borderHeight > 0) {
|
||||||
return m_borderHeight;
|
return std::round(m_borderHeight *
|
||||||
|
getDevicePixelRatioForWindow(handle));
|
||||||
}
|
}
|
||||||
return getSystemMetricsForWindow(handle, SM_CYFRAME) +
|
return getSystemMetricsForWindow(handle, SM_CYFRAME) +
|
||||||
getSystemMetricsForWindow(handle, SM_CXPADDEDBORDER);
|
getSystemMetricsForWindow(handle, SM_CXPADDEDBORDER);
|
||||||
|
@ -324,7 +352,8 @@ int WinNativeEventFilter::titlebarHeight(HWND handle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_titlebarHeight > 0) {
|
if (m_titlebarHeight > 0) {
|
||||||
return m_titlebarHeight;
|
return std::round(m_titlebarHeight *
|
||||||
|
getDevicePixelRatioForWindow(handle));
|
||||||
}
|
}
|
||||||
return borderHeight(handle) +
|
return borderHeight(handle) +
|
||||||
getSystemMetricsForWindow(handle, SM_CYCAPTION);
|
getSystemMetricsForWindow(handle, SM_CYCAPTION);
|
||||||
|
@ -377,8 +406,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
// The frame shadow is drawn by Desktop Window Manager (DWM), don't draw
|
// The frame shadow is drawn by Desktop Window Manager (DWM), don't draw
|
||||||
// it yourself. The frame shadow will get lost if DWM composition is
|
// it yourself. The frame shadow will get lost if DWM composition is
|
||||||
// disabled, it's designed to be, don't force the window to draw a frame
|
// disabled, it's designed to be, don't force the window to draw a frame
|
||||||
// shadow in that case. According to MSDN, DWM composition is always
|
// shadow in that case.
|
||||||
// enabled and can't be disabled since Win8.
|
|
||||||
updateGlass(msg->hwnd);
|
updateGlass(msg->hwnd);
|
||||||
// For debug purposes.
|
// For debug purposes.
|
||||||
qDebug().noquote() << "Window handle:" << msg->hwnd;
|
qDebug().noquote() << "Window handle:" << msg->hwnd;
|
||||||
|
@ -413,8 +441,8 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
int frameThickness_y =
|
int frameThickness_y =
|
||||||
getSystemMetricsForWindow(_hWnd, SM_CYSIZEFRAME) +
|
getSystemMetricsForWindow(_hWnd, SM_CYSIZEFRAME) +
|
||||||
getSystemMetricsForWindow(_hWnd, SM_CXPADDEDBORDER);
|
getSystemMetricsForWindow(_hWnd, SM_CXPADDEDBORDER);
|
||||||
// TODO: Chromium: HWNDMessageHandlerDelegate::HasFrame()
|
const bool removeStandardFrame = true;
|
||||||
const bool hasFrame = false;
|
const bool hasFrame = !removeStandardFrame;
|
||||||
if (!hasFrame) {
|
if (!hasFrame) {
|
||||||
frameThickness_x -= 1;
|
frameThickness_x -= 1;
|
||||||
frameThickness_y -= 1;
|
frameThickness_y -= 1;
|
||||||
|
@ -493,11 +521,11 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case WM_NCPAINT: {
|
case WM_NCPAINT: {
|
||||||
if (isCompositionEnabled()) {
|
if (IsDwmCompositionEnabled()) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// Only block WM_NCPAINT when composition is disabled. If it's
|
// Only block WM_NCPAINT when DWM composition is disabled. If it's
|
||||||
// blocked when composition is enabled, the frame shadow won't
|
// blocked when DWM composition is enabled, the frame shadow won't
|
||||||
// be drawn.
|
// be drawn.
|
||||||
*result = 0;
|
*result = 0;
|
||||||
return true;
|
return true;
|
||||||
|
@ -676,9 +704,8 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_ERASEBKGND: {
|
case WM_ERASEBKGND: {
|
||||||
// Prevent the system from erasing the background of our window
|
// Needed to prevent resize flicker.
|
||||||
// to avoid weired flashing problems.
|
*result = 1;
|
||||||
*result = 1; // Any non-zero value is OK.
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
@ -690,7 +717,7 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
|
||||||
|
|
||||||
void WinNativeEventFilter::updateGlass(HWND handle) {
|
void WinNativeEventFilter::updateGlass(HWND handle) {
|
||||||
MARGINS margins = {0, 0, 0, 0};
|
MARGINS margins = {0, 0, 0, 0};
|
||||||
if (isCompositionEnabled()) {
|
if (IsDwmCompositionEnabled()) {
|
||||||
// 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;
|
||||||
|
@ -820,6 +847,9 @@ 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, FillRect)
|
||||||
|
WNEF_RESOLVE_WINAPI(User32, GetWindowInfo)
|
||||||
|
WNEF_RESOLVE_WINAPI(User32, IsWindow)
|
||||||
WNEF_RESOLVE_WINAPI(User32, SetWindowRgn)
|
WNEF_RESOLVE_WINAPI(User32, SetWindowRgn)
|
||||||
WNEF_RESOLVE_WINAPI(User32, InvalidateRect)
|
WNEF_RESOLVE_WINAPI(User32, InvalidateRect)
|
||||||
WNEF_RESOLVE_WINAPI(User32, UpdateWindow)
|
WNEF_RESOLVE_WINAPI(User32, UpdateWindow)
|
||||||
|
@ -846,6 +876,8 @@ void WinNativeEventFilter::initWin32Api() {
|
||||||
WNEF_RESOLVE_WINAPI(User32, MonitorFromWindow)
|
WNEF_RESOLVE_WINAPI(User32, MonitorFromWindow)
|
||||||
WNEF_RESOLVE_WINAPI(User32, GetMonitorInfoW)
|
WNEF_RESOLVE_WINAPI(User32, GetMonitorInfoW)
|
||||||
WNEF_RESOLVE_WINAPI(Gdi32, GetDeviceCaps)
|
WNEF_RESOLVE_WINAPI(Gdi32, GetDeviceCaps)
|
||||||
|
WNEF_RESOLVE_WINAPI(Gdi32, CreateSolidBrush)
|
||||||
|
WNEF_RESOLVE_WINAPI(Gdi32, DeleteObject)
|
||||||
// Available since Windows XP.
|
// Available since Windows XP.
|
||||||
WNEF_RESOLVE_WINAPI(Shell32, SHAppBarMessage)
|
WNEF_RESOLVE_WINAPI(Shell32, SHAppBarMessage)
|
||||||
// Available since Windows Vista.
|
// Available since Windows Vista.
|
||||||
|
|
Loading…
Reference in New Issue