diff --git a/examples/QQPlayer-demo/CMakeLists.txt b/examples/QQPlayer-demo/CMakeLists.txt index bd92edb..94c4489 100644 --- a/examples/QQPlayer-demo/CMakeLists.txt +++ b/examples/QQPlayer-demo/CMakeLists.txt @@ -12,15 +12,9 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -if(WIN32) - set(CMAKE_DEBUG_POSTFIX "d") -else() - set(CMAKE_DEBUG_POSTFIX "_debug") -endif() +find_package(Qt5 COMPONENTS Quick REQUIRED) -find_package(Qt5 COMPONENTS Core Quick QuickCompiler REQUIRED) - -set(source_files images.qrc main.cpp ../../framelessquickhelper.h ../../framelessquickhelper.cpp) +set(source_files qml.qrc images.qrc main.cpp ../../framelessquickhelper.h ../../framelessquickhelper.cpp) if(WIN32) enable_language(RC) @@ -29,24 +23,11 @@ else() list(APPEND source_files ../../framelesshelper.h ../../framelesshelper.cpp) endif() -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - list(APPEND source_files qml.qrc) -else() - set(qml_files "") - qtquick_compiler_add_resources(qml_files qml.qrc) - list(APPEND source_files ${qml_files}) -endif() - -if(WIN32) - # Without WIN32, a console window will show. - add_executable(QQPlayer WIN32 ${source_files}) -else() - add_executable(QQPlayer ${source_files}) -endif() +add_executable(QQPlayer WIN32 ${source_files}) if(MSVC) # Silence a compiler warning caused by the Chinese comments in the source file. target_compile_options(QQPlayer PRIVATE -utf-8) endif() target_compile_definitions(QQPlayer PRIVATE $<$,$>:QT_QML_DEBUG>) -target_link_libraries(QQPlayer PRIVATE Qt::Core Qt::Quick Qt::GuiPrivate) +target_link_libraries(QQPlayer PRIVATE Qt::Quick Qt::GuiPrivate) diff --git a/winnativeeventfilter.cpp b/winnativeeventfilter.cpp index d9dfe76..623e2b7 100644 --- a/winnativeeventfilter.cpp +++ b/winnativeeventfilter.cpp @@ -53,6 +53,7 @@ #include #endif #ifdef WNEF_LINK_SYSLIB +#include #include #include #include @@ -327,6 +328,22 @@ using BP_PAINTPARAMS = struct _BP_PAINTPARAMS CONST BLENDFUNCTION *pBlendFunction; }; +using D2D1_FACTORY_TYPE = enum _D2D1_FACTORY_TYPE { D2D1_FACTORY_TYPE_SINGLE_THREADED = 0 }; + +using D2D1_DEBUG_LEVEL = enum _D2D1_DEBUG_LEVEL { + D2D1_DEBUG_LEVEL_NONE = 0, + D2D1_DEBUG_LEVEL_ERROR = 1, + D2D1_DEBUG_LEVEL_WARNING = 2, + D2D1_DEBUG_LEVEL_INFORMATION = 3, + D2D1_DEBUG_LEVEL_FORCE_DWORD = 0xffffffff + +}; + +using D2D1_FACTORY_OPTIONS = struct _D2D1_FACTORY_OPTIONS +{ + D2D1_DEBUG_LEVEL debugLevel; +}; + // Some of the following functions are not used by this code anymore, // but we don't remove them completely because we may still need them later. WNEF_GENERATE_WINAPI(DwmExtendFrameIntoClientArea, HRESULT, HWND, CONST MARGINS *) @@ -394,10 +411,8 @@ WNEF_GENERATE_WINAPI(BeginPaint, HDC, HWND, LPPAINTSTRUCT) WNEF_GENERATE_WINAPI(EndPaint, BOOL, HWND, CONST PAINTSTRUCT *) WNEF_GENERATE_WINAPI(GetCurrentProcess, HANDLE) WNEF_GENERATE_WINAPI(IsProcessDPIAware, BOOL) -#if 0 -WNEF_GENERATE_WINAPI(D2D1CreateFactory, HRESULT, D2D1_FACTORY_TYPE, REFIID, - CONST D2D1_FACTORY_OPTIONS *, void **) -#endif +WNEF_GENERATE_WINAPI( + D2D1CreateFactory, HRESULT, D2D1_FACTORY_TYPE, REFIID, CONST D2D1_FACTORY_OPTIONS *, void **) WNEF_GENERATE_WINAPI(AdjustWindowRectEx, BOOL, LPRECT, DWORD, BOOL, DWORD) WNEF_GENERATE_WINAPI(DwmDefWindowProc, BOOL, HWND, UINT, WPARAM, LPARAM, LRESULT *) WNEF_GENERATE_WINAPI(DwmGetWindowAttribute, HRESULT, HWND, DWORD, PVOID, DWORD) @@ -547,9 +562,7 @@ void ResolveWin32APIs() WNEF_RESOLVE_WINAPI(UxTheme, EndBufferedPaint) WNEF_RESOLVE_WINAPI(UxTheme, BeginBufferedPaint) // Available since Windows 7. -#if 0 WNEF_RESOLVE_WINAPI(D2D1, D2D1CreateFactory) -#endif loadDPIFunctions(); } @@ -653,15 +666,18 @@ UINT GetDotsPerInchForSystem() // Using Direct2D to get the screen DPI. // Available since Windows 7. ID2D1Factory *m_pDirect2dFactory = nullptr; - if (SUCCEEDED(m_lpD2D1CreateFactory( - D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory), - nullptr, reinterpret_cast(&m_pDirect2dFactory))) && - m_pDirect2dFactory) { + if (SUCCEEDED(WNEF_EXECUTE_WINAPI_RETURN(D2D1CreateFactory, + E_FAIL, + D2D1_FACTORY_TYPE_SINGLE_THREADED, + __uuidof(ID2D1Factory), + nullptr, + reinterpret_cast(&m_pDirect2dFactory))) + && m_pDirect2dFactory) { m_pDirect2dFactory->ReloadSystemMetrics(); FLOAT dpiX = defaultValue, dpiY = defaultValue; m_pDirect2dFactory->GetDesktopDpi(&dpiX, &dpiY); // The values of *dpiX and *dpiY are identical. - return qRound(dpiX); + return qRound(dpiX == dpiY ? dpiY : dpiX); } } #endif @@ -953,17 +969,7 @@ QScopedPointer m_instance; QList m_framelessWindows = {}; -} // namespace - -WinNativeEventFilter::WinNativeEventFilter() -{ - ResolveWin32APIs(); - qCoreAppFixup(); -} - -WinNativeEventFilter::~WinNativeEventFilter() = default; - -void WinNativeEventFilter::install() +void install() { qCoreAppFixup(); if (m_instance.isNull()) { @@ -972,7 +978,8 @@ void WinNativeEventFilter::install() } } -void WinNativeEventFilter::uninstall() +#if 0 +void uninstall() { if (!m_instance.isNull()) { qApp->removeNativeEventFilter(m_instance.data()); @@ -982,6 +989,41 @@ void WinNativeEventFilter::uninstall() m_framelessWindows.clear(); } } +#endif + +void updateQtFrame_internal(const HWND handle) +{ + Q_ASSERT(handle); + ResolveWin32APIs(); + if (WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, handle)) { + const int tbh = WinNativeEventFilter::getSystemMetric( + handle, WinNativeEventFilter::SystemMetric::TitleBarHeight); +#ifdef QT_WIDGETS_LIB + const QWidget *widget = QWidget::find(reinterpret_cast(handle)); + if (widget && widget->isTopLevel()) { + QWindow *window = widget->windowHandle(); + if (window) { + WinNativeEventFilter::updateQtFrame(window, tbh); + return; + } + } +#endif + QWindow *window = findQWindowFromRawHandle(handle); + if (window) { + WinNativeEventFilter::updateQtFrame(window, tbh); + } + } +} + +} // namespace + +WinNativeEventFilter::WinNativeEventFilter() +{ + ResolveWin32APIs(); + qCoreAppFixup(); +} + +WinNativeEventFilter::~WinNativeEventFilter() = default; void WinNativeEventFilter::addFramelessWindow(void *window, const WINDOWDATA *data, @@ -2036,30 +2078,6 @@ void WinNativeEventFilter::updateQtFrame(QWindow *window, const int titleBarHeig } } -void WinNativeEventFilter::updateQtFrame_internal(void *handle) -{ - Q_ASSERT(handle); - ResolveWin32APIs(); - const auto hwnd = reinterpret_cast(handle); - if (WNEF_EXECUTE_WINAPI_RETURN(IsWindow, FALSE, hwnd)) { - const int tbh = getSystemMetric(handle, SystemMetric::TitleBarHeight); -#ifdef QT_WIDGETS_LIB - const QWidget *widget = QWidget::find(reinterpret_cast(handle)); - if (widget && widget->isTopLevel()) { - QWindow *window = widget->windowHandle(); - if (window) { - updateQtFrame(window, tbh); - return; - } - } -#endif - QWindow *window = findQWindowFromRawHandle(hwnd); - if (window) { - updateQtFrame(window, tbh); - } - } -} - bool WinNativeEventFilter::displaySystemMenu(void *handle, const bool isRtl, const int x, diff --git a/winnativeeventfilter.h b/winnativeeventfilter.h index 92174cb..9f00cf8 100644 --- a/winnativeeventfilter.h +++ b/winnativeeventfilter.h @@ -50,9 +50,9 @@ class FRAMELESSHELPER_EXPORT WinNativeEventFilter : public QAbstractNativeEventF public: using WINDOWDATA = struct _WINDOWDATA { - bool initialized = false, fixedSize = false, mouseTransparent = false, - restoreDefaultWindowStyle = false, enableLayeredWindow = false, - disableTitleBar = false; + bool initialized = false /* Internal use only, don't modify it from outside */, + fixedSize = false, mouseTransparent = false, restoreDefaultWindowStyle = false, + enableLayeredWindow = false, disableTitleBar = false; int borderWidth = -1, borderHeight = -1, titleBarHeight = -1; QList ignoreAreas = {}, draggableAreas = {}; QList> ignoreObjects = {}, draggableObjects = {}; @@ -68,7 +68,7 @@ public: // The width and height will be scaled automatically according to DPI. Don't // scale them yourself. Just pass the original value. If you don't want to // change them, pass negative values to the parameters. - static void addFramelessWindow(void *window, + static void addFramelessWindow(void *window /* HWND */, const WINDOWDATA *data = nullptr, const bool center = false, const int x = -1, @@ -82,7 +82,7 @@ public: const int y = -1, const int width = -1, const int height = -1); - static void removeFramelessWindow(void *window); + static void removeFramelessWindow(void *window /* HWND */); static void removeFramelessWindow(QObject *window); static void clearFramelessWindows(); @@ -90,11 +90,11 @@ public: // restore default behavior. // Note that it can only affect one specific window. // If you want to change these values globally, use setBorderWidth instead. - static void setWindowData(void *window, const WINDOWDATA *data); + static void setWindowData(void *window /* HWND */, const WINDOWDATA *data); static void setWindowData(QObject *window, const WINDOWDATA *data); // You can modify the given window's data directly, it's the same with using // setWindowData. - static WINDOWDATA *windowData(void *window); + static WINDOWDATA *windowData(void *window /* HWND */); static WINDOWDATA *windowData(QObject *window); // Change settings globally, not a specific window. @@ -106,12 +106,14 @@ public: // System metric value of the given window (if the pointer is null, // return the system's standard value). - static int getSystemMetric(void *handle, const SystemMetric metric, const bool dpiAware = false); + static int getSystemMetric(void *handle /* HWND */, + const SystemMetric metric, + const bool dpiAware = false); // Use this function to trigger a frame change event or redraw a // specific window. Useful when you want to let some changes // in effect immediately. - static void updateWindow(void *handle, + static void updateWindow(void *handle /* HWND */, const bool triggerFrameChange = true, const bool redraw = true); @@ -119,29 +121,28 @@ public: // The width and height will be scaled automatically according to DPI. So // just pass the original value. static void setWindowGeometry( - void *handle, const int x, const int y, const int width, const int height); + void *handle /* HWND */, const int x, const int y, const int width, const int height); // Move the window to the center of the desktop. - static void moveWindowToDesktopCenter(void *handle); + static void moveWindowToDesktopCenter(void *handle /* HWND */); // Update Qt's internal data about the window frame, otherwise Qt will // take the size of the window frame into account when anyone is trying to // change the geometry of the window. That's not what we want. static void updateQtFrame(QWindow *window, const int titleBarHeight); - static bool displaySystemMenu(void *handle, const bool isRtl, const int x, const int y); + // Display the system context menu. + static bool displaySystemMenu(void *handle /* HWND */, + const bool isRtl, + const int x, + const int y); + /////////////////////////////////////////////// + /// CORE FUNCTION - THE SOUL OF THIS CODE + /////////////////////////////////////////////// #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override; #else bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override; #endif - -private: - // Do not call these two functions directly, otherwise strange things - // will happen. - static void install(); - static void uninstall(); - - static void updateQtFrame_internal(void *handle); };