Fix font size of rich wxTextCtrl when created on display with non-system DPI
Apply a zoom factor based on the active DPI and the system DPI. On the first DPI change, revert the scaling factor.
This commit is contained in:
@@ -244,6 +244,9 @@ protected:
|
|||||||
#if wxUSE_RICHEDIT
|
#if wxUSE_RICHEDIT
|
||||||
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
|
virtual void MSWUpdateFontOnDPIChange(const wxSize& newDPI) wxOVERRIDE;
|
||||||
|
|
||||||
|
// Apply m_richDPIscale zoom to rich control.
|
||||||
|
void MSWSetRichZoom();
|
||||||
|
|
||||||
// Apply the character-related parts of wxTextAttr to the given selection
|
// Apply the character-related parts of wxTextAttr to the given selection
|
||||||
// or the entire control if start == end == -1.
|
// or the entire control if start == end == -1.
|
||||||
//
|
//
|
||||||
@@ -265,6 +268,10 @@ protected:
|
|||||||
// (although not directly: 1 is for 1.0, 2 is for either 2.0 or 3.0 as we
|
// (although not directly: 1 is for 1.0, 2 is for either 2.0 or 3.0 as we
|
||||||
// can't nor really need to distinguish between them and 4 is for 4.1)
|
// can't nor really need to distinguish between them and 4 is for 4.1)
|
||||||
int m_verRichEdit;
|
int m_verRichEdit;
|
||||||
|
|
||||||
|
// Rich text controls need temporary scaling when they are created on a
|
||||||
|
// display with non-system DPI.
|
||||||
|
float m_richDPIscale;
|
||||||
#endif // wxUSE_RICHEDIT
|
#endif // wxUSE_RICHEDIT
|
||||||
|
|
||||||
// number of EN_UPDATE events sent by Windows when we change the controls
|
// number of EN_UPDATE events sent by Windows when we change the controls
|
||||||
|
@@ -339,6 +339,7 @@ void wxTextCtrl::Init()
|
|||||||
{
|
{
|
||||||
#if wxUSE_RICHEDIT
|
#if wxUSE_RICHEDIT
|
||||||
m_verRichEdit = 0;
|
m_verRichEdit = 0;
|
||||||
|
m_richDPIscale = 1;
|
||||||
#endif // wxUSE_RICHEDIT
|
#endif // wxUSE_RICHEDIT
|
||||||
|
|
||||||
#if wxUSE_INKEDIT && wxUSE_RICHEDIT
|
#if wxUSE_INKEDIT && wxUSE_RICHEDIT
|
||||||
@@ -608,6 +609,13 @@ bool wxTextCtrl::MSWCreateText(const wxString& value,
|
|||||||
#endif
|
#endif
|
||||||
if ( !contextMenuConnected )
|
if ( !contextMenuConnected )
|
||||||
Bind(wxEVT_CONTEXT_MENU, &wxTextCtrl::OnContextMenu, this);
|
Bind(wxEVT_CONTEXT_MENU, &wxTextCtrl::OnContextMenu, this);
|
||||||
|
|
||||||
|
// Determine the system DPI and the DPI of the display the rich control
|
||||||
|
// is shown on, and calculate and apply the scaling factor.
|
||||||
|
// When this control is created in a (wxFrame) constructor the zoom is
|
||||||
|
// not correctly applied, use CallAfter to delay setting the zoom.
|
||||||
|
m_richDPIscale = GetDPI().y / (float)::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
|
||||||
|
CallAfter(&wxTextCtrl::MSWSetRichZoom);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif // wxUSE_RICHEDIT
|
#endif // wxUSE_RICHEDIT
|
||||||
@@ -2720,14 +2728,49 @@ wxMenu *wxTextCtrl::MSWCreateContextMenu()
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxTextCtrl::MSWSetRichZoom()
|
||||||
|
{
|
||||||
|
// nothing to scale
|
||||||
|
if ( m_richDPIscale == 1 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get the current zoom ratio
|
||||||
|
UINT num = 1;
|
||||||
|
UINT denom = 1;
|
||||||
|
::SendMessage(GetHWND(), EM_GETZOOM, (WPARAM)&num, (LPARAM)&denom);
|
||||||
|
|
||||||
|
// combine the zoom ratio with the DPI scale factor
|
||||||
|
float ratio = m_richDPIscale;
|
||||||
|
if ( denom > 0 )
|
||||||
|
ratio = ratio * (num / (float)denom);
|
||||||
|
|
||||||
|
// apply the new zoom ratio, Windows uses a default denominator of 100, so
|
||||||
|
// do it here as well
|
||||||
|
num = 100 * ratio;
|
||||||
|
denom = 100;
|
||||||
|
::SendMessage(GetHWND(), EM_SETZOOM, (WPARAM)num, (LPARAM)denom);
|
||||||
|
}
|
||||||
|
|
||||||
void wxTextCtrl::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
|
void wxTextCtrl::MSWUpdateFontOnDPIChange(const wxSize& newDPI)
|
||||||
{
|
{
|
||||||
// Don't do anything for the rich edit controls, they (somehow?) update
|
// Don't use MSWUpdateFontOnDPIChange for the rich edit controls, they
|
||||||
// their appearance on their own and changing their HFONT, as the base
|
// (somehow?) update their appearance on their own and changing their
|
||||||
// class version does, would reset all the styles used by them when the DPI
|
// HFONT, as the base class version does, would reset all the styles used
|
||||||
// changes, which is unwanted.
|
// by them when the DPI changes, which is unwanted.
|
||||||
if ( !IsRich() )
|
if ( !IsRich() )
|
||||||
|
{
|
||||||
wxTextCtrlBase::MSWUpdateFontOnDPIChange(newDPI);
|
wxTextCtrlBase::MSWUpdateFontOnDPIChange(newDPI);
|
||||||
|
}
|
||||||
|
// If the rich control is created on a screen with non-system DPI, an
|
||||||
|
// initial zoom factor was applied. This needs to be reset after the first
|
||||||
|
// DPI change. First invert the scale, then set it to 1 so it is not
|
||||||
|
// applied again.
|
||||||
|
else if ( m_richDPIscale != 1 )
|
||||||
|
{
|
||||||
|
m_richDPIscale = 1 / m_richDPIscale;
|
||||||
|
MSWSetRichZoom();
|
||||||
|
m_richDPIscale = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -2982,7 +3025,7 @@ bool wxTextCtrl::MSWSetCharFormat(const wxTextAttr& style, long start, long end)
|
|||||||
wxFont font(style.GetFont());
|
wxFont font(style.GetFont());
|
||||||
|
|
||||||
LOGFONT lf = font.GetNativeFontInfo()->lf;
|
LOGFONT lf = font.GetNativeFontInfo()->lf;
|
||||||
cf.yHeight = 20*font.GetPointSize(); // 1 pt = 20 twips
|
cf.yHeight = 20 * font.GetFractionalPointSize(); // 1 pt = 20 twips
|
||||||
cf.bCharSet = lf.lfCharSet;
|
cf.bCharSet = lf.lfCharSet;
|
||||||
cf.bPitchAndFamily = lf.lfPitchAndFamily;
|
cf.bPitchAndFamily = lf.lfPitchAndFamily;
|
||||||
wxStrlcpy(cf.szFaceName, lf.lfFaceName, WXSIZEOF(cf.szFaceName));
|
wxStrlcpy(cf.szFaceName, lf.lfFaceName, WXSIZEOF(cf.szFaceName));
|
||||||
@@ -3305,12 +3348,6 @@ bool wxTextCtrl::GetStyle(long position, wxTextAttr& style)
|
|||||||
|
|
||||||
|
|
||||||
LOGFONT lf;
|
LOGFONT lf;
|
||||||
// Convert the height from the units of 1/20th of the point in which
|
|
||||||
// CHARFORMAT stores it to pixel-based units used by LOGFONT.
|
|
||||||
// Note that RichEdit seems to always use standard DPI of 96, even when the
|
|
||||||
// window is a monitor using a higher DPI.
|
|
||||||
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;
|
||||||
@@ -3343,7 +3380,10 @@ bool wxTextCtrl::GetStyle(long position, wxTextAttr& style)
|
|||||||
else
|
else
|
||||||
lf.lfWeight = FW_NORMAL;
|
lf.lfWeight = FW_NORMAL;
|
||||||
|
|
||||||
|
// Determine the pointSize that was used in SetStyle. Don't worry about
|
||||||
|
// lfHeight or PPI, style.SetFont() will lose this information anyway.
|
||||||
wxFont font(wxNativeFontInfo(lf, this));
|
wxFont font(wxNativeFontInfo(lf, this));
|
||||||
|
font.SetFractionalPointSize(cf.yHeight / 20.0f); // 1 pt = 20 twips
|
||||||
if (font.IsOk())
|
if (font.IsOk())
|
||||||
{
|
{
|
||||||
style.SetFont(font);
|
style.SetFont(font);
|
||||||
|
Reference in New Issue
Block a user