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) // returns the old default item (possibly NULL)
virtual wxWindow *SetDefault(); virtual wxWindow *SetDefault();
// returns the default button size for this platform // returns the default button size for this platform, and optionally for a
static wxSize GetDefaultSize(); // specific window when the platform supports per-monitor DPI
static wxSize GetDefaultSize(wxWindow* win = NULL);
protected: protected:
wxDECLARE_NO_COPY_CLASS(wxButtonBase); wxDECLARE_NO_COPY_CLASS(wxButtonBase);

View File

@@ -34,6 +34,7 @@
#endif #endif
class WXDLLIMPEXP_FWD_BASE wxArrayString; class WXDLLIMPEXP_FWD_BASE wxArrayString;
class WXDLLIMPEXP_FWD_CORE wxWindow;
struct WXDLLIMPEXP_FWD_CORE wxNativeEncodingInfo; struct WXDLLIMPEXP_FWD_CORE wxNativeEncodingInfo;
#if defined(_WX_X_FONTLIKE) #if defined(_WX_X_FONTLIKE)
@@ -118,11 +119,16 @@ public:
// set the XFLD // set the XFLD
void SetXFontName(const wxString& xFontName); void SetXFontName(const wxString& xFontName);
#elif defined(__WXMSW__) #elif defined(__WXMSW__)
wxNativeFontInfo(const LOGFONT& lf_) // Preserve compatibility in the semi-public (i.e. private, but still
: lf(lf_), // unfortunately used by some existing code outside of the library) API
pointSize(GetPointSizeAtPPI(lf.lfHeight)) // 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, // MSW-specific: get point size from LOGFONT height using specified DPI,
// or screen DPI when 0. // or screen DPI when 0.

View File

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

View File

@@ -122,6 +122,9 @@ protected:
WXHBRUSH DoMSWControlColor(WXHDC pDC, wxColour colBg, WXHWND hWnd) wxOVERRIDE; 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 // the labels windows, if any
wxSubwindows *m_labels; wxSubwindows *m_labels;

View File

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

View File

@@ -11,6 +11,7 @@
#define _WX_PRIVATE_WINDOW_H_ #define _WX_PRIVATE_WINDOW_H_
#include "wx/gdicmn.h" #include "wx/gdicmn.h"
#include "wx/dynlib.h"
namespace wxPrivate namespace wxPrivate
{ {
@@ -33,6 +34,67 @@ inline wxSize GetAverageASCIILetterSize(const T& of_what)
return s; 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 } // namespace wxPrivate
#endif // _WX_PRIVATE_WINDOW_H_ #endif // _WX_PRIVATE_WINDOW_H_

View File

@@ -120,13 +120,7 @@ public:
// current DPI, do it once (and cache the result) in another function. // current DPI, do it once (and cache the result) in another function.
#define wxNEEDS_BORDER_IN_PX #define wxNEEDS_BORDER_IN_PX
// We don't react to dynamic DPI changes, so we can cache the values of return DoGetDefaultBorderInPx();
// 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;
#endif #endif
#else #else
return 0; return 0;
@@ -230,8 +224,6 @@ public:
private: private:
#ifdef wxNEEDS_BORDER_IN_PX #ifdef wxNEEDS_BORDER_IN_PX
static int DoGetDefaultBorderInPx(); static int DoGetDefaultBorderInPx();
static int ms_defaultBorderInPx;
#endif // wxNEEDS_BORDER_IN_PX #endif // wxNEEDS_BORDER_IN_PX
int m_proportion; int m_proportion;

View File

@@ -179,11 +179,15 @@ public:
/** /**
Returns the default size for the buttons. It is advised to make all the dialog Returns the default size for the buttons. It is advised to make all the
buttons of the same size and this function allows retrieving the (platform and dialog buttons of the same size and this function allows retrieving the
current font dependent size) which should be the best suited for this. (platform, and current font dependent) size which should be the best
suited for this.
The optional @a win argument is new since wxWidgets 3.1.3 and allows to
get a per-monitor DPI specific size.
*/ */
static wxSize GetDefaultSize(); static wxSize GetDefaultSize(wxWindow* win = NULL);
/** /**
Returns the string label for the button. Returns the string label for the button.

View File

@@ -3322,15 +3322,15 @@ public:
/** /**
@class wxDPIChangedEvent @class wxDPIChangedEvent
Event sent when the resolution (measured in dots-per-inch, or DPI) of the Event sent when the display scale factor or pixel density (measured in
monitor a window is on changes. dots-per-inch, or DPI) of the monitor a window is on changes.
The event is sent to each wxTopLevelWindow affected by the change, and all The event is sent to each wxTopLevelWindow affected by the change, and all
its children recursively. For example, this event is sent to the window its children recursively (post-order traversal). For example, this event is
when it is moved, by the user, from a display using some DPI value to sent to the window when it is moved, by the user, from a display using some
another display using a different DPI value. It also sent to all program DPI value to another display using a different DPI value. It also sent to
windows on the given display if its DPI changes due to a change in the all program windows on the given display if its DPI changes due to a change
system settings. in the system settings.
Currently this event is generated by wxMSW port if only and only if the Currently this event is generated by wxMSW port if only and only if the
MSW application runs under Windows 10 Creators Update (v1703) or later and MSW application runs under Windows 10 Creators Update (v1703) or later and
@@ -3359,15 +3359,11 @@ class wxDPIChangedEvent : public wxEvent
public: public:
/** /**
Returns the old DPI. Returns the old DPI.
@since 3.1.3
*/ */
wxSize GetOldDPI() const; wxSize GetOldDPI() const;
/** /**
Returns the new DPI. Returns the new DPI.
@since 3.1.3
*/ */
wxSize GetNewDPI() const; wxSize GetNewDPI() const;
}; };

View File

@@ -28,11 +28,13 @@
#include "wx/button.h" #include "wx/button.h"
#include "wx/statbox.h" #include "wx/statbox.h"
#include "wx/toplevel.h" #include "wx/toplevel.h"
#include "wx/app.h"
#endif // WX_PRECOMP #endif // WX_PRECOMP
#include "wx/display.h" #include "wx/display.h"
#include "wx/vector.h" #include "wx/vector.h"
#include "wx/listimpl.cpp" #include "wx/listimpl.cpp"
#include "wx/private/window.h"
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -90,8 +92,6 @@ WX_DEFINE_EXPORTED_LIST( wxSizerItemList )
#ifdef wxNEEDS_BORDER_IN_PX #ifdef wxNEEDS_BORDER_IN_PX
int wxSizerFlags::ms_defaultBorderInPx = 0;
/* static */ /* static */
int wxSizerFlags::DoGetDefaultBorderInPx() int wxSizerFlags::DoGetDefaultBorderInPx()
{ {
@@ -103,11 +103,14 @@ int wxSizerFlags::DoGetDefaultBorderInPx()
// between related and unrelated controls, as explained at the above URL, // between related and unrelated controls, as explained at the above URL,
// but we don't have a way to specify this in our API currently. // but we don't have a way to specify this in our API currently.
// //
// We also have to use the DPI for the primary monitor here as we don't // We also have to use the DPI for the monitor showing the top window here
// have any associated window, so this is wrong on systems using multiple // as we don't have any associated window -- but, again, without changes
// monitors with different resolutions too -- but, again, without changes
// in the API, there is nothing we can do about this. // in the API, there is nothing we can do about this.
return wxWindow::FromDIP(5, NULL); const wxWindow* const win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
static wxPrivate::DpiDependentValue<int> s_defaultBorderInPx;
if ( s_defaultBorderInPx.HasChanged(win) )
s_defaultBorderInPx.SetAtNewDPI(wxWindow::FromDIP(5, win));
return s_defaultBorderInPx.Get();
} }
#endif // wxNEEDS_BORDER_IN_PX #endif // wxNEEDS_BORDER_IN_PX

View File

@@ -2929,10 +2929,10 @@ wxSize wxWindowBase::GetDlgUnitBase() const
{ {
// Default GUI font is used. This is the most common case, so // Default GUI font is used. This is the most common case, so
// cache the results. // cache the results.
static wxSize s_defFontSize; static wxPrivate::DpiDependentValue<wxSize> s_defFontSize;
if ( s_defFontSize.x == 0 ) if ( s_defFontSize.HasChanged(parent) )
s_defFontSize = wxPrivate::GetAverageASCIILetterSize(*parent); s_defFontSize.SetAtNewDPI(wxPrivate::GetAverageASCIILetterSize(*parent));
return s_defFontSize; return s_defFontSize.Get();
} }
else else
{ {

View File

@@ -165,7 +165,7 @@ wxWindow *wxButton::SetDefault()
} }
/* static */ /* static */
wxSize wxButtonBase::GetDefaultSize() wxSize wxButtonBase::GetDefaultSize(wxWindow* WXUNUSED(win))
{ {
static wxSize size = wxDefaultSize; static wxSize size = wxDefaultSize;
if (size == wxDefaultSize) if (size == wxDefaultSize)

View File

@@ -166,7 +166,7 @@ wxWindow *wxButton::SetDefault()
} }
/* static */ /* static */
wxSize wxButtonBase::GetDefaultSize() wxSize wxButtonBase::GetDefaultSize(wxWindow* WXUNUSED(win))
{ {
return wxSize(80,26); return wxSize(80,26);
} }

View File

@@ -160,14 +160,25 @@ WXDWORD wxButton::MSWGetStyle(long style, WXDWORD *exstyle) const
} }
/* static */ /* static */
wxSize wxButtonBase::GetDefaultSize() wxSize wxButtonBase::GetDefaultSize(wxWindow* win)
{ {
static wxSize s_sizeBtn; static wxPrivate::DpiDependentValue<wxSize> s_sizeBtn;
if ( s_sizeBtn.x == 0 ) if ( s_sizeBtn.HasChanged(win) )
{
wxSize base;
if ( win )
{
wxClientDC dc(win);
dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
base = wxPrivate::GetAverageASCIILetterSize(dc);
}
else
{ {
wxScreenDC dc; wxScreenDC dc;
dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
base = wxPrivate::GetAverageASCIILetterSize(dc);
}
// The size of a standard button in the dialog units is 50x14, // The size of a standard button in the dialog units is 50x14,
// translate this to pixels. // translate this to pixels.
@@ -180,12 +191,11 @@ wxSize wxButtonBase::GetDefaultSize()
// //
// NB: wxMulDivInt32() is used, because it correctly rounds the result // NB: wxMulDivInt32() is used, because it correctly rounds the result
const wxSize base = wxPrivate::GetAverageASCIILetterSize(dc); s_sizeBtn.SetAtNewDPI(wxSize(wxMulDivInt32(50, base.x, 4),
s_sizeBtn.x = wxMulDivInt32(50, base.x, 4); wxMulDivInt32(14, base.y, 8)));
s_sizeBtn.y = wxMulDivInt32(14, base.y, 8);
} }
return s_sizeBtn; return s_sizeBtn.Get();
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -28,15 +28,14 @@
#include "wx/checkbox.h" #include "wx/checkbox.h"
#ifndef WX_PRECOMP #ifndef WX_PRECOMP
#include "wx/brush.h"
#include "wx/dcclient.h" #include "wx/dcclient.h"
#include "wx/dcscreen.h"
#include "wx/settings.h" #include "wx/settings.h"
#endif #endif
#include "wx/renderer.h" #include "wx/renderer.h"
#include "wx/msw/uxtheme.h" #include "wx/msw/uxtheme.h"
#include "wx/msw/private/button.h" #include "wx/msw/private/button.h"
#include "wx/private/window.h"
#include "wx/msw/missing.h" #include "wx/msw/missing.h"
// ============================================================================ // ============================================================================
@@ -98,16 +97,17 @@ WXDWORD wxCheckBox::MSWGetStyle(long style, WXDWORD *exstyle) const
wxSize wxCheckBox::DoGetBestClientSize() const wxSize wxCheckBox::DoGetBestClientSize() const
{ {
static int s_checkSize = 0; static wxPrivate::DpiDependentValue<wxCoord> s_checkSize;
if ( !s_checkSize ) if ( s_checkSize.HasChanged(this) )
{ {
wxScreenDC dc; wxClientDC dc(const_cast<wxCheckBox*>(this));
dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
s_checkSize = dc.GetCharHeight(); s_checkSize.SetAtNewDPI(dc.GetCharHeight());
} }
wxCoord& checkSize = s_checkSize.Get();
wxString str = wxGetWindowText(GetHWND()); wxString str = wxGetWindowText(GetHWND());
int wCheckbox, hCheckbox; int wCheckbox, hCheckbox;
@@ -116,7 +116,7 @@ wxSize wxCheckBox::DoGetBestClientSize() const
wxClientDC dc(const_cast<wxCheckBox *>(this)); wxClientDC dc(const_cast<wxCheckBox *>(this));
dc.SetFont(GetFont()); dc.SetFont(GetFont());
dc.GetMultiLineTextExtent(GetLabelText(str), &wCheckbox, &hCheckbox); dc.GetMultiLineTextExtent(GetLabelText(str), &wCheckbox, &hCheckbox);
wCheckbox += s_checkSize + GetCharWidth(); wCheckbox += checkSize + GetCharWidth();
if ( ::GetWindowLong(GetHwnd(), GWL_STYLE) & BS_MULTILINE ) if ( ::GetWindowLong(GetHwnd(), GWL_STYLE) & BS_MULTILINE )
{ {
@@ -128,16 +128,16 @@ wxSize wxCheckBox::DoGetBestClientSize() const
// label appears on 3 lines, not 2, under Windows 2003 using // label appears on 3 lines, not 2, under Windows 2003 using
// classic look and feel (although it works fine under Windows 7, // classic look and feel (although it works fine under Windows 7,
// with or without themes). // with or without themes).
wCheckbox += s_checkSize; wCheckbox += checkSize;
} }
if ( hCheckbox < s_checkSize ) if ( hCheckbox < checkSize )
hCheckbox = s_checkSize; hCheckbox = checkSize;
} }
else else
{ {
wCheckbox = s_checkSize; wCheckbox = checkSize;
hCheckbox = s_checkSize; hCheckbox = checkSize;
} }
return wxSize(wCheckbox, hCheckbox); return wxSize(wCheckbox, hCheckbox);

View File

@@ -63,9 +63,6 @@ public:
private: private:
bool m_destroyCursor; bool m_destroyCursor;
// standard cursor size, computed on first use
static wxSize ms_sizeStd;
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -110,28 +107,17 @@ public:
// wxCursorRefData // wxCursorRefData
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxSize wxCursorRefData::ms_sizeStd;
wxCoord wxCursorRefData::GetStandardWidth() wxCoord wxCursorRefData::GetStandardWidth()
{ {
if ( !ms_sizeStd.x ) const wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
{ return wxSystemSettings::GetMetric(wxSYS_CURSOR_X, win);
wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
ms_sizeStd.x = wxSystemSettings::GetMetric(wxSYS_CURSOR_X, win);
}
return ms_sizeStd.x;
} }
wxCoord wxCursorRefData::GetStandardHeight() wxCoord wxCursorRefData::GetStandardHeight()
{ {
if ( !ms_sizeStd.y ) const wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
{ return wxSystemSettings::GetMetric(wxSYS_CURSOR_Y, win);
wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
ms_sizeStd.y = wxSystemSettings::GetMetric(wxSYS_CURSOR_Y, win);
}
return ms_sizeStd.y;
} }
wxCursorRefData::wxCursorRefData(HCURSOR hcursor, bool destroy) wxCursorRefData::wxCursorRefData(HCURSOR hcursor, bool destroy)

View File

@@ -403,6 +403,11 @@ void wxFontRefData::Free()
// wxNativeFontInfo // wxNativeFontInfo
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxNativeFontInfo::wxNativeFontInfo(const LOGFONT& lf_, const wxWindow* win)
: lf(lf_),
pointSize(GetPointSizeAtPPI(lf.lfHeight, win ? win->GetDPI().y : 0))
{ }
/* static */ /* static */
float wxNativeFontInfo::GetPointSizeAtPPI(int lfHeight, int ppi) float wxNativeFontInfo::GetPointSizeAtPPI(int lfHeight, int ppi)
{ {

View File

@@ -152,7 +152,7 @@ int wxFontDialog::ShowModal()
if ( ChooseFont(&chooseFontStruct) != 0 ) if ( ChooseFont(&chooseFontStruct) != 0 )
{ {
wxRGBToColour(m_fontData.m_fontColour, chooseFontStruct.rgbColors); wxRGBToColour(m_fontData.m_fontColour, chooseFontStruct.rgbColors);
m_fontData.m_chosenFont = wxFont(wxNativeFontInfo(logFont)); m_fontData.m_chosenFont = wxFont(wxNativeFontInfo(logFont, this));
m_fontData.EncodingInfo().facename = logFont.lfFaceName; m_fontData.EncodingInfo().facename = logFont.lfFaceName;
m_fontData.EncodingInfo().charset = logFont.lfCharSet; m_fontData.EncodingInfo().charset = logFont.lfCharSet;

View File

@@ -278,7 +278,7 @@ void wxFillLogFont(LOGFONT *logFont, const wxFont *font)
wxFont wxCreateFontFromLogFont(const LOGFONT *logFont) wxFont wxCreateFontFromLogFont(const LOGFONT *logFont)
{ {
return wxFont(wxNativeFontInfo(*logFont)); return wxFont(wxNativeFontInfo(*logFont, NULL));
} }
#endif // WXWIN_COMPATIBILITY_3_0 #endif // WXWIN_COMPATIBILITY_3_0

View File

@@ -335,6 +335,14 @@ void wxFrame::PositionStatusBar()
//else: no adjustments necessary for the toolbar on top //else: no adjustments necessary for the toolbar on top
#endif // wxUSE_TOOLBAR #endif // wxUSE_TOOLBAR
// GetSize returns the height of the clientSize in which the statusbar
// height is subtracted (see wxFrame::DoGetClientSize). When the DPI of the
// window changes, the statusbar height will likely change so we need to
// account for this difference. If not, the statusbar will be positioned
// too high or low.
int shOld;
m_frameStatusBar->GetSize(NULL, &shOld);
// Resize the status bar to its default height, as it could have been set // Resize the status bar to its default height, as it could have been set
// to a wrong value before by WM_SIZE sent during the frame creation and // to a wrong value before by WM_SIZE sent during the frame creation and
// our status bars preserve their programmatically set size to avoid being // our status bars preserve their programmatically set size to avoid being
@@ -342,8 +350,9 @@ void wxFrame::PositionStatusBar()
// this here, the status bar would retain the possibly wrong current height. // this here, the status bar would retain the possibly wrong current height.
m_frameStatusBar->SetSize(x, h, w, wxDefaultCoord, wxSIZE_AUTO_HEIGHT); m_frameStatusBar->SetSize(x, h, w, wxDefaultCoord, wxSIZE_AUTO_HEIGHT);
int sw, sh; int sh;
m_frameStatusBar->GetSize(&sw, &sh); m_frameStatusBar->GetSize(NULL, &sh);
h += shOld - sh;
// Since we wish the status bar to be directly under the client area, // Since we wish the status bar to be directly under the client area,
// we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS. // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS.

View File

@@ -348,7 +348,7 @@ void MenuDrawData::Init()
wxUxThemeFont themeFont; wxUxThemeFont themeFont;
::GetThemeSysFont(hTheme, TMT_MENUFONT, themeFont.GetPtr()); ::GetThemeSysFont(hTheme, TMT_MENUFONT, themeFont.GetPtr());
Font = wxFont(themeFont.GetLOGFONT()); Font = wxFont(wxNativeFontInfo(themeFont.GetLOGFONT(), window));
Theme = true; Theme = true;
@@ -392,15 +392,7 @@ void MenuDrawData::Init()
Offset = -12; Offset = -12;
wxNativeFontInfo info(metrics.lfMenuFont); Font = wxFont(wxNativeFontInfo(metrics.lfMenuFont, window));
// wxNativeFontInfo constructor calculates the pointSize using the
// main screen DPI. But lfHeight is based on the window DPI.
if ( window )
{
info.pointSize = wxNativeFontInfo::GetPointSizeAtPPI(
info.lf.lfHeight, window->GetDPI().y);
}
Font = wxFont(info);
Theme = false; Theme = false;
} }

View File

@@ -397,15 +397,8 @@ void wxMessageDialog::AdjustButtonLabels()
wxFont wxMessageDialog::GetMessageFont() wxFont wxMessageDialog::GetMessageFont()
{ {
const wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL; const wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
wxNativeFontInfo info(wxMSWImpl::GetNonClientMetrics(win).lfMessageFont); const wxNativeFontInfo
info(wxMSWImpl::GetNonClientMetrics(win).lfMessageFont, win);
// wxNativeFontInfo constructor calculates the pointSize using the
// main screen DPI. But lfHeight is based on the window DPI.
if ( win )
{
info.pointSize = wxNativeFontInfo::GetPointSizeAtPPI(
info.lf.lfHeight, win->GetDPI().y);
}
return info; return info;
} }

View File

@@ -751,6 +751,14 @@ int wxRadioBox::GetItemFromPoint(const wxPoint& pt) const
return wxNOT_FOUND; return wxNOT_FOUND;
} }
void wxRadioBox::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
{
wxStaticBox::MSWUpdateFontOnDPIChange(newDPI);
if ( m_font.IsOk() )
m_radioButtons->SetFont(m_font);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// radio box drawing // radio box drawing
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -29,11 +29,11 @@
#ifndef WX_PRECOMP #ifndef WX_PRECOMP
#include "wx/settings.h" #include "wx/settings.h"
#include "wx/dcscreen.h" #include "wx/dcclient.h"
#include "wx/toplevel.h"
#endif #endif
#include "wx/msw/private.h" #include "wx/msw/private.h"
#include "wx/private/window.h"
#include "wx/renderer.h" #include "wx/renderer.h"
#include "wx/msw/uxtheme.h" #include "wx/msw/uxtheme.h"
@@ -238,31 +238,32 @@ bool wxRadioButton::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
wxSize wxRadioButton::DoGetBestSize() const wxSize wxRadioButton::DoGetBestSize() const
{ {
static int s_radioSize = 0; static wxPrivate::DpiDependentValue<wxCoord> s_radioSize;
if ( !s_radioSize ) if ( s_radioSize.HasChanged(this) )
{ {
wxScreenDC dc; wxClientDC dc(const_cast<wxRadioButton*>(this));
dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
s_radioSize = dc.GetCharHeight(); s_radioSize.SetAtNewDPI(dc.GetCharHeight());
} }
wxCoord& radioSize = s_radioSize.Get();
wxString str = GetLabel(); wxString str = GetLabel();
int wRadio, hRadio; int wRadio, hRadio;
if ( !str.empty() ) if ( !str.empty() )
{ {
GetTextExtent(GetLabelText(str), &wRadio, &hRadio); GetTextExtent(GetLabelText(str), &wRadio, &hRadio);
wRadio += s_radioSize + GetCharWidth(); wRadio += radioSize + GetCharWidth();
if ( hRadio < s_radioSize ) if ( hRadio < radioSize )
hRadio = s_radioSize; hRadio = radioSize;
} }
else else
{ {
wRadio = s_radioSize; wRadio = radioSize;
hRadio = s_radioSize; hRadio = radioSize;
} }
return wxSize(wRadio, hRadio); return wxSize(wRadio, hRadio);

View File

@@ -150,7 +150,7 @@ wxFont wxCreateFontFromStockObject(int index)
LOGFONT lf; LOGFONT lf;
if ( ::GetObject(hFont, sizeof(LOGFONT), &lf) != 0 ) if ( ::GetObject(hFont, sizeof(LOGFONT), &lf) != 0 )
{ {
wxNativeFontInfo info(lf); wxNativeFontInfo info(lf, NULL);
font.Create(info); font.Create(info);
} }
else else
@@ -183,16 +183,8 @@ wxFont wxSystemSettingsNative::GetFont(wxSystemFont index)
// controls may prefer to use lfStatusFont or lfCaptionFont if it // controls may prefer to use lfStatusFont or lfCaptionFont if it
// is more appropriate for them // is more appropriate for them
const wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL; const wxWindow* win = wxTheApp ? wxTheApp->GetTopWindow() : NULL;
wxNativeFontInfo const wxNativeFontInfo
info(wxMSWImpl::GetNonClientMetrics(win).lfMessageFont); info(wxMSWImpl::GetNonClientMetrics(win).lfMessageFont, win);
// wxNativeFontInfo constructor calculates the pointSize using the
// main screen DPI. But lfHeight is based on the window DPI.
if ( win )
{
info.pointSize = wxNativeFontInfo::GetPointSizeAtPPI(
info.lf.lfHeight, win->GetDPI().y);
}
gs_fontDefault = new wxFont(info); gs_fontDefault = new wxFont(info);
} }
@@ -358,7 +350,7 @@ extern wxFont wxGetCCDefaultFont()
win win
) ) ) )
{ {
return wxFont(lf); return wxFont(wxNativeFontInfo(lf, win));
} }
else else
{ {

View File

@@ -163,13 +163,17 @@ bool wxSlider::Create(wxWindow *parent,
m_labels->Set(n, wnd, lblid); m_labels->Set(n, wnd, lblid);
} }
m_labels->SetFont(GetFont());
} }
// now create the main control too // now create the main control too
if ( !MSWCreateControl(TRACKBAR_CLASS, wxEmptyString, pos, size) ) if ( !MSWCreateControl(TRACKBAR_CLASS, wxEmptyString, pos, size) )
return false; return false;
if ( m_labels )
{
m_labels->SetFont(GetFont());
}
// and initialize everything // and initialize everything
SetRange(minValue, maxValue); SetRange(minValue, maxValue);
SetValue(value); SetValue(value);
@@ -183,6 +187,8 @@ bool wxSlider::Create(wxWindow *parent,
SetSize(size); SetSize(size);
} }
Bind(wxEVT_DPI_CHANGED, &wxSlider::OnDPIChanged, this);
return true; return true;
} }
@@ -541,7 +547,7 @@ void wxSlider::DoMoveWindow(int x, int y, int width, int height)
wxSize wxSlider::DoGetBestSize() const wxSize wxSlider::DoGetBestSize() const
{ {
// this value is arbitrary: // this value is arbitrary:
static const int length = FromDIP(100); const int length = FromDIP(100);
const int thumbSize = GetThumbLength(); const int thumbSize = GetThumbLength();
const int tickSize = FromDIP(TICK); const int tickSize = FromDIP(TICK);
@@ -619,6 +625,27 @@ WXHBRUSH wxSlider::DoMSWControlColor(WXHDC pDC, wxColour colBg, WXHWND hWnd)
return hBrush; return hBrush;
} }
void wxSlider::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
{
wxSliderBase::MSWUpdateFontOnDPIChange(newDPI);
if ( m_labels && m_font.IsOk() )
{
m_labels->SetFont(m_font);
}
}
void wxSlider::OnDPIChanged(wxDPIChangedEvent& event)
{
int thumbLen = GetThumbLength();
const double scaleFactor = (double)event.GetNewDPI().x / event.GetOldDPI().x;
const double thumbLenScaled = thumbLen * scaleFactor;
thumbLen = (int)(scaleFactor > 1.0 ? ceil(thumbLenScaled) : floor(thumbLenScaled));
SetThumbLength(thumbLen);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// slider-specific methods // slider-specific methods
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -166,7 +166,8 @@ bool wxStatusBar::SetFont(const wxFont& font)
if (!wxWindow::SetFont(font)) if (!wxWindow::SetFont(font))
return false; return false;
if (m_pDC) m_pDC->SetFont(font); if ( m_pDC )
m_pDC->SetFont(m_font);
return true; return true;
} }
@@ -256,6 +257,14 @@ void wxStatusBar::MSWUpdateFieldsWidths()
delete [] pWidths; delete [] pWidths;
} }
void wxStatusBar::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
{
wxStatusBarBase::MSWUpdateFontOnDPIChange(newDPI);
if ( m_pDC && m_font.IsOk() )
m_pDC->SetFont(m_font);
}
void wxStatusBar::DoUpdateStatusText(int nField) void wxStatusBar::DoUpdateStatusText(int nField)
{ {
if (!m_pDC) if (!m_pDC)

View File

@@ -3207,7 +3207,8 @@ bool wxTextCtrl::GetStyle(long position, wxTextAttr& style)
// CHARFORMAT stores it to pixel-based units used by LOGFONT. // CHARFORMAT stores it to pixel-based units used by LOGFONT.
// Note that RichEdit seems to always use standard DPI of 96, even when the // Note that RichEdit seems to always use standard DPI of 96, even when the
// window is a monitor using a higher DPI. // window is a monitor using a higher DPI.
lf.lfHeight = wxNativeFontInfo::GetLogFontHeightAtPPI(cf.yHeight/20.0f, 96); lf.lfHeight = wxNativeFontInfo::GetLogFontHeightAtPPI(cf.yHeight/20.0f,
GetDPI().y);
lf.lfWidth = 0; lf.lfWidth = 0;
lf.lfCharSet = ANSI_CHARSET; // FIXME: how to get correct charset? lf.lfCharSet = ANSI_CHARSET; // FIXME: how to get correct charset?
lf.lfClipPrecision = 0; lf.lfClipPrecision = 0;
@@ -3240,7 +3241,7 @@ bool wxTextCtrl::GetStyle(long position, wxTextAttr& style)
else else
lf.lfWeight = FW_NORMAL; lf.lfWeight = FW_NORMAL;
wxFont font(lf); wxFont font(wxNativeFontInfo(lf, this));
if (font.IsOk()) if (font.IsOk())
{ {
style.SetFont(font); style.SetFont(font);

View File

@@ -137,7 +137,7 @@ bool wxButton::OSXHandleClicked( double WXUNUSED(timestampsec) )
} }
/* static */ /* static */
wxSize wxButtonBase::GetDefaultSize() wxSize wxButtonBase::GetDefaultSize(wxWindow* WXUNUSED(win))
{ {
return wxAnyButton::GetDefaultSize(); return wxAnyButton::GetDefaultSize();
} }

View File

@@ -61,7 +61,7 @@ wxWindow *wxButton::SetDefault()
} }
/* static */ /* static */
wxSize wxButtonBase::GetDefaultSize() wxSize wxButtonBase::GetDefaultSize(wxWindow* WXUNUSED(win))
{ {
static wxSize size = wxDefaultSize; static wxSize size = wxDefaultSize;
if (size == wxDefaultSize) if (size == wxDefaultSize)

View File

@@ -110,7 +110,7 @@ wxButton::~wxButton()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/* static */ /* static */
wxSize wxButtonBase::GetDefaultSize() wxSize wxButtonBase::GetDefaultSize(wxWindow* WXUNUSED(win))
{ {
static wxSize s_sizeBtn; static wxSize s_sizeBtn;