From 57b408ed88154bb8f8bb0dd0de37cd4417fdeb64 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 5 Feb 2024 19:00:56 +0100 Subject: [PATCH] Fix wxButton::GetDefaultSize() in high DPI under MSW Using button size in dialog units doesn't work well in high DPI, as it gives sizes wildly different from those actually used by Windows itself for the buttons (e.g. for those in Explorer dialogs still using Win32 API), so switch to using DIPs, just as it was done for determining the initial size of the buttons when actually creating them in c6d2f6d9fe (Really fix the standard button size in high DPI under MSW, 2019-10-19) See #18528. Closes #24283. --- src/msw/button.cpp | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/msw/button.cpp b/src/msw/button.cpp index 858d48bb1d..b5500e19fa 100644 --- a/src/msw/button.cpp +++ b/src/msw/button.cpp @@ -163,30 +163,19 @@ wxSize wxButtonBase::GetDefaultSize(wxWindow* win) 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; - dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); - base = wxPrivate::GetAverageASCIILetterSize(dc); - } - - // The size of a standard button in the dialog units is 50x14, - // translate this to pixels. + // The "Recommended sizing and spacing" section of MSDN layout article + // documents the default button size as being 50*14 dialog units or + // 75*23 relative pixels (what we call DIPs). But dialog units don't + // work well in high DPI (and not just because of rounding errors, i.e. + // the values differ from the actual default button size used by + // Windows itself in high DPI by too much), so just use DIPs directly. // - // Windows' computes dialog units using average character width over - // upper- and lower-case ASCII alphabet and not using the average - // character width metadata stored in the font; see - // http://support.microsoft.com/default.aspx/kb/145994 for detailed - // discussion. - - s_sizeBtn.SetAtNewDPI(wxRescaleCoord(50, 14).From(4, 8).To(base)); + // Moreover, it looks like the extra 2px borders around the visible + // part of the button are not scaled correctly in higher than normal + // DPI, so add them without scaling. + s_sizeBtn.SetAtNewDPI( + wxWindow::FromDIP(wxSize(73, 21), win) + wxSize(2, 2) + ); } return s_sizeBtn.Get();