From c733ed50ffd4209fd78ffa888fa302f38cb22952 Mon Sep 17 00:00:00 2001 From: jules Date: Sun, 16 Mar 2014 21:08:11 +0000 Subject: [PATCH] Began adding some win8.1 DPI functionality. --- .../native/juce_win32_Windowing.cpp | 102 ++++++++++++++---- 1 file changed, 84 insertions(+), 18 deletions(-) diff --git a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index 9b3682049b..67d8097671 100644 --- a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -102,17 +102,38 @@ bool Desktop::canUseSemiTransparentWindows() noexcept #endif +#ifndef MONITOR_DPI_TYPE + enum Monitor_DPI_Type + { + MDT_Effective_DPI = 0, + MDT_Angular_DPI = 1, + MDT_Raw_DPI = 2, + MDT_Default = MDT_Effective_DPI + }; + + enum Process_DPI_Awareness + { + Process_DPI_Unaware = 0, + Process_System_DPI_Aware = 1, + Process_Per_Monitor_DPI_Aware = 2 + }; +#endif + typedef BOOL (WINAPI* RegisterTouchWindowFunc) (HWND, ULONG); typedef BOOL (WINAPI* GetTouchInputInfoFunc) (HTOUCHINPUT, UINT, TOUCHINPUT*, int); typedef BOOL (WINAPI* CloseTouchInputHandleFunc) (HTOUCHINPUT); typedef BOOL (WINAPI* GetGestureInfoFunc) (HGESTUREINFO, GESTUREINFO*); typedef BOOL (WINAPI* SetProcessDPIAwareFunc)(); +typedef BOOL (WINAPI* SetProcessDPIAwarenessFunc) (Process_DPI_Awareness); +typedef HRESULT (WINAPI* GetDPIForMonitorFunc) (HMONITOR, Monitor_DPI_Type, UINT*, UINT*); -static RegisterTouchWindowFunc registerTouchWindow = nullptr; -static GetTouchInputInfoFunc getTouchInputInfo = nullptr; -static CloseTouchInputHandleFunc closeTouchInputHandle = nullptr; -static GetGestureInfoFunc getGestureInfo = nullptr; -static SetProcessDPIAwareFunc setProcessDPIAware = nullptr; +static RegisterTouchWindowFunc registerTouchWindow = nullptr; +static GetTouchInputInfoFunc getTouchInputInfo = nullptr; +static CloseTouchInputHandleFunc closeTouchInputHandle = nullptr; +static GetGestureInfoFunc getGestureInfo = nullptr; +static SetProcessDPIAwareFunc setProcessDPIAware = nullptr; +static SetProcessDPIAwarenessFunc setProcessDPIAwareness = nullptr; +static GetDPIForMonitorFunc getDPIForMonitor = nullptr; static bool hasCheckedForMultiTouch = false; @@ -158,17 +179,33 @@ static void setDPIAwareness() { if (JUCEApplicationBase::isStandaloneApp()) { - if (setProcessDPIAware == nullptr) + if (setProcessDPIAwareness == nullptr) { - setProcessDPIAware = (SetProcessDPIAwareFunc) getUser32Function ("SetProcessDPIAware"); + HMODULE shcoreModule = GetModuleHandleA ("SHCore.dll"); - if (setProcessDPIAware != nullptr) - setProcessDPIAware(); + if (shcoreModule != 0) + { + setProcessDPIAwareness = (SetProcessDPIAwarenessFunc) GetProcAddress (shcoreModule, "SetProcessDpiAwareness"); + getDPIForMonitor = (GetDPIForMonitorFunc) GetProcAddress (shcoreModule, "GetDpiForMonitor"); + + if (setProcessDPIAwareness != nullptr && getDPIForMonitor != nullptr +// && SUCCEEDED (setProcessDPIAwareness (Process_Per_Monitor_DPI_Aware))) + && SUCCEEDED (setProcessDPIAwareness (Process_System_DPI_Aware))) // (keep using this mode temporarily..) + return; + } + + if (setProcessDPIAware == nullptr) + { + setProcessDPIAware = (SetProcessDPIAwareFunc) getUser32Function ("SetProcessDPIAware"); + + if (setProcessDPIAware != nullptr) + setProcessDPIAware(); + } } } } -static double getDPI() +static double getGlobalDPI() { setDPIAwareness(); @@ -181,7 +218,7 @@ static double getDPI() double Desktop::getDefaultMasterScale() { - return JUCEApplicationBase::isStandaloneApp() ? getDPI() / 96.0 + return JUCEApplicationBase::isStandaloneApp() ? getGlobalDPI() / 96.0 : 1.0; } @@ -2246,6 +2283,10 @@ private: } } + void handleDPIChange() // happens when a window moves to a screen with a different DPI. + { + } + //============================================================================== public: static LRESULT CALLBACK windowProc (HWND h, UINT message, WPARAM wParam, LPARAM lParam) @@ -2488,6 +2529,10 @@ private: doSettingChange(); break; + case 0x2e0: // WM_DPICHANGED + handleDPIChange(); + break; + case WM_INITMENU: initialiseSysMenu ((HMENU) wParam); break; @@ -3183,10 +3228,12 @@ void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDis //============================================================================== struct MonitorInfo { - MonitorInfo (Rectangle rect, bool main) noexcept : isMain (main), bounds (rect) {} + MonitorInfo (Rectangle rect, bool main, double d) noexcept + : isMain (main), bounds (rect), dpi (d) {} Rectangle bounds; bool isMain; + double dpi; }; static BOOL CALLBACK enumMonitorsProc (HMONITOR hm, HDC, LPRECT r, LPARAM userInfo) @@ -3195,7 +3242,17 @@ static BOOL CALLBACK enumMonitorsProc (HMONITOR hm, HDC, LPRECT r, LPARAM userIn info.cbSize = sizeof (info); GetMonitorInfo (hm, &info); const bool isMain = (info.dwFlags & 1 /* MONITORINFOF_PRIMARY */) != 0; - ((Array*) userInfo)->add (MonitorInfo (rectangleFromRECT (*r), isMain)); + double dpi = 0; + + if (getDPIForMonitor != nullptr) + { + UINT dpiX = 0, dpiY = 0; + + if (SUCCEEDED (getDPIForMonitor (hm, MDT_Default, &dpiX, &dpiY))) + dpi = (dpiX + dpiY) / 2.0; + } + + ((Array*) userInfo)->add (MonitorInfo (rectangleFromRECT (*r), isMain, dpi)); return TRUE; } @@ -3207,8 +3264,10 @@ void Desktop::Displays::findDisplays (float masterScale) Array monitors; EnumDisplayMonitors (0, 0, &enumMonitorsProc, (LPARAM) &monitors); + const double globalDPI = getGlobalDPI(); + if (monitors.size() == 0) - monitors.add (MonitorInfo (rectangleFromRECT (getWindowRect (GetDesktopWindow())), true)); + monitors.add (MonitorInfo (rectangleFromRECT (getWindowRect (GetDesktopWindow())), true, globalDPI)); // make sure the first in the list is the main monitor for (int i = 1; i < monitors.size(); ++i) @@ -3218,15 +3277,22 @@ void Desktop::Displays::findDisplays (float masterScale) RECT workArea; SystemParametersInfo (SPI_GETWORKAREA, 0, &workArea, 0); - const double dpi = getDPI(); // (this has only one value for all monitors) - for (int i = 0; i < monitors.size(); ++i) { Display d; d.userArea = d.totalArea = monitors.getReference(i).bounds / masterScale; d.isMain = monitors.getReference(i).isMain; - d.scale = masterScale; - d.dpi = dpi; + d.dpi = monitors.getReference(i).dpi; + + if (d.dpi == 0) + { + d.scale = masterScale; + d.dpi = globalDPI; + } + else + { + d.scale = d.dpi / 96.0; + } if (d.isMain) d.userArea = d.userArea.getIntersection (rectangleFromRECT (workArea) / masterScale);