Merge branch 'per-monitor-dpi-aware-controls-1' of https://github.com/MaartenBent/wxWidgets

Update the font of some buddy controls when the DPI changes. Fix the
position of the statusbar after a DPI change. Add some changes that were
suggested in https://github.com/wxWidgets/wxWidgets/pull/1499 but left
out from it.

Some sizes are cached to improve the speed of the library. These sizes
become incorrect when the DPI changes. And are incorrect when a window
is created on a display with a different DPI. Fix this by checking if
the current DPI is the same as the DPI that was used when calculating
the size, otherwise recalculate the size.

Closes https://github.com/wxWidgets/wxWidgets/pull/1530
This commit is contained in:
Vadim Zeitlin
2019-09-07 14:53:26 +02:00
31 changed files with 241 additions and 137 deletions

View File

@@ -39,8 +39,9 @@ public:
// returns the old default item (possibly NULL)
virtual wxWindow *SetDefault();
// returns the default button size for this platform
static wxSize GetDefaultSize();
// returns the default button size for this platform, and optionally for a
// specific window when the platform supports per-monitor DPI
static wxSize GetDefaultSize(wxWindow* win = NULL);
protected:
wxDECLARE_NO_COPY_CLASS(wxButtonBase);

View File

@@ -34,6 +34,7 @@
#endif
class WXDLLIMPEXP_FWD_BASE wxArrayString;
class WXDLLIMPEXP_FWD_CORE wxWindow;
struct WXDLLIMPEXP_FWD_CORE wxNativeEncodingInfo;
#if defined(_WX_X_FONTLIKE)
@@ -118,11 +119,16 @@ public:
// set the XFLD
void SetXFontName(const wxString& xFontName);
#elif defined(__WXMSW__)
wxNativeFontInfo(const LOGFONT& lf_)
: lf(lf_),
pointSize(GetPointSizeAtPPI(lf.lfHeight))
{
}
// Preserve compatibility in the semi-public (i.e. private, but still
// unfortunately used by some existing code outside of the library) API
// by allowing to create wxNativeFontInfo from just LOGFONT, but ensure
// that we always specify the window, to use the correct DPI, when creating
// fonts inside the library itself.
wxNativeFontInfo(const LOGFONT& lf_, const wxWindow* win
#ifndef WXBUILDING
= NULL
#endif
);
// MSW-specific: get point size from LOGFONT height using specified DPI,
// or screen DPI when 0.

View File

@@ -162,6 +162,8 @@ protected:
virtual WXHRGN MSWGetRegionWithoutChildren() wxOVERRIDE;
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
// resolve ambiguity in base classes
virtual wxBorder GetDefaultBorder() const wxOVERRIDE { return wxRadioBoxBase::GetDefaultBorder(); }

View File

@@ -122,6 +122,9 @@ protected:
WXHBRUSH DoMSWControlColor(WXHDC pDC, wxColour colBg, WXHWND hWnd) wxOVERRIDE;
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
void OnDPIChanged(wxDPIChangedEvent& event);
// the labels windows, if any
wxSubwindows *m_labels;

View File

@@ -72,6 +72,8 @@ protected:
// implementation of the public SetStatusWidths()
void MSWUpdateFieldsWidths();
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
// used by DoUpdateStatusText()
wxClientDC *m_pDC;

View File

@@ -11,6 +11,7 @@
#define _WX_PRIVATE_WINDOW_H_
#include "wx/gdicmn.h"
#include "wx/dynlib.h"
namespace wxPrivate
{
@@ -33,6 +34,67 @@ inline wxSize GetAverageASCIILetterSize(const T& of_what)
return s;
}
namespace
{
inline bool SupportsPerMonitorDPI()
{
static bool s_checkDPI =
#if defined(__WXMSW__) && wxUSE_DYNLIB_CLASS
// Only check the DPI when GetDpiForWindow is available because the old
// method (GetDeviceCaps) is a lot slower (about 1500 times).
// And when GetDpiForWindow is not available (for example older Windows
// versions), per-monitor DPI (V2) is also not available.
wxLoadedDLL("user32.dll").HasSymbol("GetDpiForWindow");
#else
false;
#endif
return s_checkDPI;
}
}
template <typename T>
class DpiDependentValue
{
public:
// Explicit initialization is needed if T is a primitive type.
DpiDependentValue()
: m_value(), m_dpi()
{ }
bool HasChanged(const wxWindowBase* win)
{
if ( win && SupportsPerMonitorDPI() )
{
const wxSize dpi = win->GetDPI();
if ( dpi != m_dpi )
{
m_dpi = dpi;
return true;
}
}
// Ensure that we return true the first time we're called,
// asuming that the value will always be set to a non-default value.
return m_value == T();
}
void SetAtNewDPI(const T& value)
{
m_value = value;
}
T& Get()
{
return m_value;
}
private:
T m_value;
wxSize m_dpi;
};
} // namespace wxPrivate
#endif // _WX_PRIVATE_WINDOW_H_

View File

@@ -120,13 +120,7 @@ public:
// current DPI, do it once (and cache the result) in another function.
#define wxNEEDS_BORDER_IN_PX
// We don't react to dynamic DPI changes, so we can cache the values of
// the border in on-screen pixels after computing it once. This
// could/should change in the future.
if ( !ms_defaultBorderInPx )
ms_defaultBorderInPx = DoGetDefaultBorderInPx();
return ms_defaultBorderInPx;
return DoGetDefaultBorderInPx();
#endif
#else
return 0;
@@ -230,8 +224,6 @@ public:
private:
#ifdef wxNEEDS_BORDER_IN_PX
static int DoGetDefaultBorderInPx();
static int ms_defaultBorderInPx;
#endif // wxNEEDS_BORDER_IN_PX
int m_proportion;