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.
This commit is contained in:
Vadim Zeitlin 2024-02-05 19:00:56 +01:00
parent 36583f13e1
commit 57b408ed88

View file

@ -163,30 +163,19 @@ wxSize wxButtonBase::GetDefaultSize(wxWindow* win)
if ( s_sizeBtn.HasChanged(win) ) if ( s_sizeBtn.HasChanged(win) )
{ {
wxSize base; // The "Recommended sizing and spacing" section of MSDN layout article
if ( win ) // 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
wxClientDC dc(win); // work well in high DPI (and not just because of rounding errors, i.e.
dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); // the values differ from the actual default button size used by
base = wxPrivate::GetAverageASCIILetterSize(dc); // Windows itself in high DPI by too much), so just use DIPs directly.
}
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.
// //
// Windows' computes dialog units using average character width over // Moreover, it looks like the extra 2px borders around the visible
// upper- and lower-case ASCII alphabet and not using the average // part of the button are not scaled correctly in higher than normal
// character width metadata stored in the font; see // DPI, so add them without scaling.
// http://support.microsoft.com/default.aspx/kb/145994 for detailed s_sizeBtn.SetAtNewDPI(
// discussion. wxWindow::FromDIP(wxSize(73, 21), win) + wxSize(2, 2)
);
s_sizeBtn.SetAtNewDPI(wxRescaleCoord(50, 14).From(4, 8).To(base));
} }
return s_sizeBtn.Get(); return s_sizeBtn.Get();