From e57139bb21128ae0a873589b2179725f4d5d6932 Mon Sep 17 00:00:00 2001 From: Maarten Bent Date: Thu, 6 Oct 2016 23:46:28 +0200 Subject: [PATCH] Use system DPI for some native Windows dialogs Some native dialogs do not scale correctly (color picker, font picker, open file with custom controls). ALl other native dialogs do scale correctly (open file, open directory, find replace, print). Change the DPI Awareness Context temporarily to SystemAware, so Windows handles the scaling. --- include/wx/msw/private/dpiaware.h | 72 +++++++++++++++++++++++++++++++ src/msw/colordlg.cpp | 3 ++ src/msw/filedlg.cpp | 7 +++ src/msw/fontdlg.cpp | 3 ++ 4 files changed, 85 insertions(+) create mode 100644 include/wx/msw/private/dpiaware.h diff --git a/include/wx/msw/private/dpiaware.h b/include/wx/msw/private/dpiaware.h new file mode 100644 index 0000000000..2ff769fc35 --- /dev/null +++ b/include/wx/msw/private/dpiaware.h @@ -0,0 +1,72 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/msw/private/dpiaware.h +// Purpose: AutoSystemDpiAware class +// Author: Maarten Bent +// Created: 10/6/2016 +// Copyright: (c) Maarten Bent +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_MSW_DPI_AWARE_H_ +#define _WX_MSW_DPI_AWARE_H_ + +#ifndef WX_PRECOMP + #include "wx/msw/missing.h" +#endif + +#include "wx/dynlib.h" + +#if wxUSE_DYNLIB_CLASS + +// ---------------------------------------------------------------------------- +// Temporarily change the DPI Awareness context to System +// ---------------------------------------------------------------------------- + +class AutoSystemDpiAware +{ + #define WXDPI_AWARENESS_CONTEXT_UNAWARE ((WXDPI_AWARENESS_CONTEXT)-1) + #define WXDPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((WXDPI_AWARENESS_CONTEXT)-2) + typedef WXDPI_AWARENESS_CONTEXT + (WINAPI *SetThreadDpiAwarenessContext_t)(WXDPI_AWARENESS_CONTEXT); + +public: + AutoSystemDpiAware() + : m_prevContext(WXDPI_AWARENESS_CONTEXT_UNAWARE), + m_pfnSetThreadDpiAwarenessContext((SetThreadDpiAwarenessContext_t)-1) + { + if ( m_pfnSetThreadDpiAwarenessContext == (SetThreadDpiAwarenessContext_t)-1) + { + wxLoadedDLL dllUser32("user32.dll"); + wxDL_INIT_FUNC(m_pfn, SetThreadDpiAwarenessContext, dllUser32); + } + + if ( m_pfnSetThreadDpiAwarenessContext ) + { + m_prevContext = m_pfnSetThreadDpiAwarenessContext( + WXDPI_AWARENESS_CONTEXT_SYSTEM_AWARE); + } + + } + + ~AutoSystemDpiAware() + { + if ( m_pfnSetThreadDpiAwarenessContext ) + { + m_pfnSetThreadDpiAwarenessContext(m_prevContext); + } + } + +private: + WXDPI_AWARENESS_CONTEXT m_prevContext; + + SetThreadDpiAwarenessContext_t m_pfnSetThreadDpiAwarenessContext; +}; + +#else // !wxUSE_DYNLIB_CLASS + +// Just a stub to avoid littering the code with wxUSE_DYNLIB_CLASS checks. +class AutoSystemDpiAware { }; + +#endif // wxUSE_DYNLIB_CLASS/!wxUSE_DYNLIB_CLASS + +#endif // _WX_MSW_DPI_AWARE_H_ diff --git a/src/msw/colordlg.cpp b/src/msw/colordlg.cpp index ab9a671525..38fac558cc 100644 --- a/src/msw/colordlg.cpp +++ b/src/msw/colordlg.cpp @@ -40,6 +40,7 @@ #include "wx/scopeguard.h" #include "wx/msw/private.h" +#include "wx/msw/private/dpiaware.h" #include #include @@ -216,6 +217,8 @@ int wxColourDialog::ShowModal() gs_activeDialog = this; wxON_BLOCK_EXIT_NULL(gs_activeDialog); + AutoSystemDpiAware dpiAwareness; + // do show the modal dialog if ( !::ChooseColor(&chooseColorStruct) ) { diff --git a/src/msw/filedlg.cpp b/src/msw/filedlg.cpp index ec0529c47d..1801adcbd3 100644 --- a/src/msw/filedlg.cpp +++ b/src/msw/filedlg.cpp @@ -47,6 +47,7 @@ #include "wx/scopeguard.h" #include "wx/tokenzr.h" #include "wx/modalhook.h" +#include "wx/msw/private/dpiaware.h" // ---------------------------------------------------------------------------- // constants @@ -375,6 +376,12 @@ void wxFileDialog::MSWOnTypeChange(WXHWND WXUNUSED(hDlg), int nFilterIndex) // err is filled with the CDERR_XXX constant static bool DoShowCommFileDialog(OPENFILENAME *of, long style, DWORD *err) { + // Extra controls do not handle per-monitor DPI, fall back to system DPI + // so entire file-dialog is resized. + wxScopedPtr dpiAwareness; + if ( of->Flags & OFN_ENABLEHOOK ) + dpiAwareness.reset(new AutoSystemDpiAware()); + if ( style & wxFD_SAVE ? GetSaveFileName(of) : GetOpenFileName(of) ) return true; diff --git a/src/msw/fontdlg.cpp b/src/msw/fontdlg.cpp index 610b2c21b1..29d62d2a19 100644 --- a/src/msw/fontdlg.cpp +++ b/src/msw/fontdlg.cpp @@ -37,6 +37,7 @@ #endif #include "wx/fontutil.h" +#include "wx/msw/private/dpiaware.h" #include #include @@ -149,6 +150,8 @@ int wxFontDialog::ShowModal() chooseFontStruct.Flags = flags; + AutoSystemDpiAware dpiAwareness; + if ( ChooseFont(&chooseFontStruct) != 0 ) { wxRGBToColour(m_fontData.m_fontColour, chooseFontStruct.rgbColors);