Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2020-03-29 19:33:59 +08:00
parent f5e7990e91
commit 7eab71b126
2 changed files with 30 additions and 1 deletions

View File

@ -11,9 +11,12 @@ Copy *winnativeeventfilter.h* and *winnativeeventfilter.cpp* to your project and
- All traditional Win32 APIs are replaced by their DPI-aware ones, if there is one. - All traditional Win32 APIs are replaced by their DPI-aware ones, if there is one.
- Start from Windows 10, normal windows usually have a one pixel width border line, I don't add it because not everyone like it. You can draw one manually if you really need it. - Start from Windows 10, normal windows usually have a one pixel width border line, I don't add it because not everyone like it. You can draw one manually if you really need it.
- The frame shadow will get lost if the window is full transparent. It can't be solved unless you draw the frame shadow manually. - The frame shadow will get lost if the window is full transparent. It can't be solved unless you draw the frame shadow manually.
- There are some known issues when you draw something manually on widgets using D3D. Don't know why currently. But things work fine if you let Qt do all the job, including painting. - There are some known issues when you draw something manually on widgets using Direct3D or some other graphic frameworks. Don't know why currently. But things work fine if you let Qt do all the job, including painting.
- On Windows 7, if you disabled the Windows Aero, the frame shadow will be disabled as well because it's DWM's resposibility to draw the frame shadow. - On Windows 7, if you disabled the Windows Aero, the frame shadow will be disabled as well because it's DWM's resposibility to draw the frame shadow.
- Only top level windows can be frameless. Applying this code to child windows or widgets will result in unexpected behavior.
- The border width (8 if not scaled), border height (8 if not scaled) and titlebar height (38 if not scaled) are acquired by Win32 APIs and are the same with other standard windows, and thus you should not modify them.
- You can also copy all the code to `[virtual protected] bool QWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)` or `[virtual protected] bool QWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)`, it's the same with install a native event filter to the application. - You can also copy all the code to `[virtual protected] bool QWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)` or `[virtual protected] bool QWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)`, it's the same with install a native event filter to the application.
- If you find the three system buttons (minimize, maximize and close) show up when resizing the window rapidly, copy all the code to the `nativeEvent` function of your widget or window, and they will not appear anymore. Don't know why currently.
- For UNIX platforms, things are much easier. Just use the `startSystemMove` and `startSystemResize` APIs introduced in Qt 5.15. - For UNIX platforms, things are much easier. Just use the `startSystemMove` and `startSystemResize` APIs introduced in Qt 5.15.
## References ## References

View File

@ -1,5 +1,6 @@
#include "winnativeeventfilter.h" #include "winnativeeventfilter.h"
#include <QDebug>
#include <QGuiApplication> #include <QGuiApplication>
#include <QLibrary> #include <QLibrary>
#include <QOperatingSystemVersion> #include <QOperatingSystemVersion>
@ -86,6 +87,23 @@ bool WinNativeEventFilter::nativeEventFilter(const QByteArray &eventType,
{ {
Q_UNUSED(eventType) Q_UNUSED(eventType)
const auto msg = static_cast<LPMSG>(message); const auto msg = static_cast<LPMSG>(message);
if (!msg->hwnd) {
// Why sometimes the window handle is null? Is it designed to be?
// Anyway, we should skip it in this case.
return false;
}
if (GetParent(msg->hwnd)) {
// GetParent only returns NULL if the window is a top level window.
// Only top level windows can be frameless, we should never apply our
// code to child windows or widgets.
return false;
}
#if 0
if (!IsWindowVisible(msg->hwnd)) {
// Skip dummy windows created internally by Qt.
return false;
}
#endif
if (!m_data.contains(msg->hwnd)) { if (!m_data.contains(msg->hwnd)) {
LPWINDOW _data = new WINDOW; LPWINDOW _data = new WINDOW;
_data->hwnd = msg->hwnd; _data->hwnd = msg->hwnd;
@ -169,6 +187,14 @@ void WinNativeEventFilter::init(LPWINDOW data) {
SetLayeredWindowAttributes(data->hwnd, RGB(255, 0, 255), 0, LWA_COLORKEY); SetLayeredWindowAttributes(data->hwnd, RGB(255, 0, 255), 0, LWA_COLORKEY);
// Make sure our window has the frame shadow. // Make sure our window has the frame shadow.
handleDwmCompositionChanged(data); handleDwmCompositionChanged(data);
// For debug purposes.
qDebug().noquote() << "Window handle:" << data->hwnd;
qDebug().noquote() << "Window DPI:" << windowDpi(data->hwnd)
<< "Window DPR:" << windowDpr(data->hwnd);
qDebug().noquote() << "Window border width:" << borderWidth(data->hwnd)
<< "Window border height:" << borderHeight(data->hwnd)
<< "Window titlebar height:"
<< titlebarHeight(data->hwnd);
} }
void WinNativeEventFilter::handleNcCalcSize(LPWINDOW data, WPARAM wParam, void WinNativeEventFilter::handleNcCalcSize(LPWINDOW data, WPARAM wParam,