Merge branch 'dpi-textctrl' of https://github.com/MaartenBent/wxWidgets
Improvements for wxTextCtrl, wxSearchCtrl, wxButton when using non-default DPI. See https://github.com/wxWidgets/wxWidgets/pull/1634
This commit is contained in:
@@ -91,12 +91,13 @@ WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
|
||||
// Return the height of a native text control corresponding to the given
|
||||
// character height (as returned by GetCharHeight() or wxGetCharSize()).
|
||||
//
|
||||
// The wxWindow parameter must be valid and used for getting the DPI.
|
||||
inline int wxGetEditHeightFromCharHeight(int cy, const wxWindow* w)
|
||||
// The wxWindow parameter is currently not used but should still be valid.
|
||||
inline int wxGetEditHeightFromCharHeight(int cy, const wxWindow* WXUNUSED(w))
|
||||
{
|
||||
// The value 8 here is empiric, i.e. it's not necessarily correct, but
|
||||
// seems to work relatively well.
|
||||
return cy + w->FromDIP(8);
|
||||
// Don't use FromDIP(8), this seems not needed.
|
||||
return cy + 8;
|
||||
}
|
||||
|
||||
// Compatibility macro used in the existing code. It assumes that it's called
|
||||
|
@@ -244,6 +244,9 @@ protected:
|
||||
#if wxUSE_RICHEDIT
|
||||
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
|
||||
// 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
|
||||
// can't nor really need to distinguish between them and 4 is for 4.1)
|
||||
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
|
||||
|
||||
// number of EN_UPDATE events sent by Windows when we change the controls
|
||||
|
@@ -111,9 +111,6 @@ protected:
|
||||
// (re)create the wxButton
|
||||
void CreateButton();
|
||||
|
||||
// add m_button to m_sizerButton using current value of m_chkFit
|
||||
void AddButtonToSizer();
|
||||
|
||||
// helper function: create a bitmap for wxBitmapButton
|
||||
wxBitmap CreateBitmap(const wxString& label, const wxArtID& type);
|
||||
|
||||
@@ -315,7 +312,7 @@ void ButtonWidgetsPage::CreateContent()
|
||||
sizerLeft->AddSpacer(5);
|
||||
|
||||
wxButton *btn = new wxButton(this, ButtonPage_Reset, "&Reset");
|
||||
sizerLeft->Add(btn, wxSizerFlags().CentreHorizontal().Border(wxALL, 15));
|
||||
sizerLeft->Add(btn, wxSizerFlags().CentreHorizontal().TripleBorder(wxALL));
|
||||
|
||||
// middle pane
|
||||
wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY, "&Operations");
|
||||
@@ -340,15 +337,15 @@ void ButtonWidgetsPage::CreateContent()
|
||||
|
||||
// right pane
|
||||
m_sizerButton = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_sizerButton->SetMinSize(150, 0);
|
||||
m_sizerButton->SetMinSize(FromDIP(150), 0);
|
||||
|
||||
// the 3 panes panes compose the window
|
||||
sizerTop->Add(sizerLeft,
|
||||
wxSizerFlags(0).Expand().Border((wxALL & ~wxLEFT), 10));
|
||||
wxSizerFlags(0).Expand().DoubleBorder(wxALL & ~wxLEFT));
|
||||
sizerTop->Add(sizerMiddle,
|
||||
wxSizerFlags(1).Expand().Border(wxALL, 10));
|
||||
wxSizerFlags(1).Expand().DoubleBorder(wxALL));
|
||||
sizerTop->Add(m_sizerButton,
|
||||
wxSizerFlags(1).Expand().Border((wxALL & ~wxRIGHT), 10));
|
||||
wxSizerFlags(1).Expand().DoubleBorder((wxALL & ~wxRIGHT)));
|
||||
|
||||
// do create the main control
|
||||
Reset();
|
||||
@@ -364,7 +361,7 @@ void ButtonWidgetsPage::CreateContent()
|
||||
void ButtonWidgetsPage::Reset()
|
||||
{
|
||||
m_chkBitmapOnly->SetValue(false);
|
||||
m_chkFit->SetValue(true);
|
||||
m_chkFit->SetValue(false);
|
||||
m_chkAuthNeeded->SetValue(false);
|
||||
m_chkTextAndBitmap->SetValue(false);
|
||||
m_chkDefault->SetValue(false);
|
||||
@@ -453,6 +450,11 @@ void ButtonWidgetsPage::CreateButton()
|
||||
break;
|
||||
}
|
||||
|
||||
if ( m_chkFit->GetValue() )
|
||||
{
|
||||
flags |= wxBU_EXACTFIT;
|
||||
}
|
||||
|
||||
bool showsBitmap = false;
|
||||
if ( m_chkBitmapOnly->GetValue() )
|
||||
{
|
||||
@@ -557,25 +559,13 @@ void ButtonWidgetsPage::CreateButton()
|
||||
|
||||
m_button->Enable(!m_chkDisable->IsChecked());
|
||||
|
||||
AddButtonToSizer();
|
||||
m_sizerButton->AddStretchSpacer();
|
||||
m_sizerButton->Add(m_button, wxSizerFlags().Centre().Border());
|
||||
m_sizerButton->AddStretchSpacer();
|
||||
|
||||
m_sizerButton->Layout();
|
||||
}
|
||||
|
||||
void ButtonWidgetsPage::AddButtonToSizer()
|
||||
{
|
||||
if ( m_chkFit->GetValue() )
|
||||
{
|
||||
m_sizerButton->AddStretchSpacer(1);
|
||||
m_sizerButton->Add(m_button, wxSizerFlags(0).Centre().Border());
|
||||
m_sizerButton->AddStretchSpacer(1);
|
||||
}
|
||||
else // take up the entire space
|
||||
{
|
||||
m_sizerButton->Add(m_button, wxSizerFlags(1).Expand().Border());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// event handlers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@@ -156,13 +156,13 @@ void SearchCtrlWidgetsPage::CreateContent()
|
||||
|
||||
m_searchBtnCheck->SetValue(true);
|
||||
|
||||
box->Add(m_searchBtnCheck, 0, wxALL, 5);
|
||||
box->Add(m_cancelBtnCheck, 0, wxALL, 5);
|
||||
box->Add(m_menuBtnCheck, 0, wxALL, 5);
|
||||
box->Add(m_searchBtnCheck, wxSizerFlags().Border());
|
||||
box->Add(m_cancelBtnCheck, wxSizerFlags().Border());
|
||||
box->Add(m_menuBtnCheck, wxSizerFlags().Border());
|
||||
|
||||
wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(box, 0, wxALL|wxEXPAND, 15);
|
||||
sizer->Add(m_srchCtrl, 0, wxALL|wxALIGN_CENTER, 15);
|
||||
sizer->Add(box, wxSizerFlags().Expand().TripleBorder());
|
||||
sizer->Add(m_srchCtrl, wxSizerFlags().Centre().TripleBorder());
|
||||
|
||||
SetSizer(sizer);
|
||||
}
|
||||
|
@@ -132,7 +132,8 @@ protected:
|
||||
// can't use wxBORDER_NONE to calculate a good height, in which case we just have to
|
||||
// assume a border in the code above and then subtract the space that would be taken up
|
||||
// by a themed border (the thin blue border and the white internal border).
|
||||
size.y -= FromDIP(4);
|
||||
// Don't use FromDIP(4), this seems not needed.
|
||||
size.y -= 4;
|
||||
|
||||
self->SetWindowStyleFlag(flags);
|
||||
|
||||
@@ -451,28 +452,21 @@ wxString wxSearchCtrl::GetDescriptiveText() const
|
||||
|
||||
wxSize wxSearchCtrl::DoGetBestClientSize() const
|
||||
{
|
||||
wxSize sizeText = m_text->GetBestSize();
|
||||
wxSize sizeSearch(0,0);
|
||||
wxSize sizeCancel(0,0);
|
||||
int searchMargin = 0;
|
||||
int cancelMargin = 0;
|
||||
wxSize size = m_text->GetBestSize();
|
||||
|
||||
if ( IsSearchButtonVisible() )
|
||||
{
|
||||
sizeSearch = m_searchButton->GetBestSize();
|
||||
searchMargin = FromDIP(MARGIN);
|
||||
size.x += m_searchButton->GetBestSize().x + FromDIP(MARGIN);
|
||||
}
|
||||
if ( IsCancelButtonVisible() )
|
||||
{
|
||||
sizeCancel = m_cancelButton->GetBestSize();
|
||||
cancelMargin = FromDIP(MARGIN);
|
||||
size.x += m_cancelButton->GetBestSize().x + FromDIP(MARGIN);
|
||||
}
|
||||
|
||||
int horizontalBorder = FromDIP(1) + ( sizeText.y - sizeText.y * 14 / 21 ) / 2;
|
||||
int horizontalBorder = FromDIP(1) + (size.y - size.y * 14 / 21 ) / 2;
|
||||
size.x += 2 * horizontalBorder;
|
||||
|
||||
// buttons are square and equal to the height of the text control
|
||||
int height = sizeText.y;
|
||||
return wxSize(sizeSearch.x + searchMargin + sizeText.x + cancelMargin + sizeCancel.x + 2*horizontalBorder,
|
||||
height);
|
||||
return size;
|
||||
}
|
||||
|
||||
void wxSearchCtrl::LayoutControls()
|
||||
@@ -533,7 +527,7 @@ void wxSearchCtrl::LayoutControls()
|
||||
// of the white border that's part of the theme border. We can also remove a pixel from
|
||||
// the height to fit the text control in, because the padding in EDIT_HEIGHT_FROM_CHAR_HEIGHT
|
||||
// is already generous.
|
||||
int textY = FromDIP(2);
|
||||
int textY = FromDIP(1);
|
||||
#else
|
||||
int textY = 0;
|
||||
#endif
|
||||
|
@@ -437,16 +437,16 @@ wxSize wxMSWButton::IncreaseToStdSizeAndCache(wxControl *btn, const wxSize& size
|
||||
|
||||
sizeBtn.IncTo(sizeDef);
|
||||
}
|
||||
else // wxBU_EXACTFIT case
|
||||
{
|
||||
// Such buttons are typically used alongside a text control or similar,
|
||||
// so make them as high as it.
|
||||
int yText;
|
||||
wxGetCharSize(GetHwndOf(btn), NULL, &yText, btn->GetFont());
|
||||
yText = wxGetEditHeightFromCharHeight(yText, btn);
|
||||
|
||||
sizeBtn.IncTo(wxSize(-1, yText));
|
||||
}
|
||||
// wxBU_EXACTFIT is typically used alongside a text control or similar,
|
||||
// so make them as high as it.
|
||||
// The standard height is generally higher than this, but if not (e.g. when
|
||||
// using a larger font) increase the button height as well.
|
||||
int yText;
|
||||
wxGetCharSize(GetHwndOf(btn), NULL, &yText, btn->GetFont());
|
||||
yText = wxGetEditHeightFromCharHeight(yText, btn);
|
||||
|
||||
sizeBtn.IncTo(wxSize(-1, yText));
|
||||
|
||||
btn->CacheBestSize(sizeBtn);
|
||||
|
||||
|
@@ -339,6 +339,7 @@ void wxTextCtrl::Init()
|
||||
{
|
||||
#if wxUSE_RICHEDIT
|
||||
m_verRichEdit = 0;
|
||||
m_richDPIscale = 1;
|
||||
#endif // wxUSE_RICHEDIT
|
||||
|
||||
#if wxUSE_INKEDIT && wxUSE_RICHEDIT
|
||||
@@ -608,6 +609,13 @@ bool wxTextCtrl::MSWCreateText(const wxString& value,
|
||||
#endif
|
||||
if ( !contextMenuConnected )
|
||||
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
|
||||
#endif // wxUSE_RICHEDIT
|
||||
@@ -2538,8 +2546,10 @@ wxSize wxTextCtrl::DoGetBestSize() const
|
||||
|
||||
wxSize wxTextCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const
|
||||
{
|
||||
int cx, cy;
|
||||
wxGetCharSize(GetHWND(), &cx, &cy, GetFont());
|
||||
int cy;
|
||||
wxFont font = GetFont();
|
||||
font.WXAdjustToPPI(GetDPI());
|
||||
wxGetCharSize(GetHWND(), NULL, &cy, font);
|
||||
|
||||
DWORD wText = FromDIP(1);
|
||||
::SystemParametersInfo(SPI_GETCARETWIDTH, 0, &wText, 0);
|
||||
@@ -2718,14 +2728,49 @@ wxMenu *wxTextCtrl::MSWCreateContextMenu()
|
||||
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)
|
||||
{
|
||||
// Don't do anything for the rich edit controls, they (somehow?) update
|
||||
// their appearance on their own and changing their HFONT, as the base
|
||||
// class version does, would reset all the styles used by them when the DPI
|
||||
// changes, which is unwanted.
|
||||
// Don't use MSWUpdateFontOnDPIChange for the rich edit controls, they
|
||||
// (somehow?) update their appearance on their own and changing their
|
||||
// HFONT, as the base class version does, would reset all the styles used
|
||||
// by them when the DPI changes, which is unwanted.
|
||||
if ( !IsRich() )
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -2890,7 +2935,7 @@ bool wxTextCtrl::SetFont(const wxFont& font)
|
||||
{
|
||||
// Native text control sends EN_CHANGE when the font changes, producing
|
||||
// a wxEVT_TEXT event as if the user changed the value. This is not
|
||||
// the case, so supress the event.
|
||||
// the case, so suppress the event.
|
||||
wxEventBlocker block(this, wxEVT_TEXT);
|
||||
|
||||
if ( !wxTextCtrlBase::SetFont(font) )
|
||||
@@ -2980,7 +3025,7 @@ bool wxTextCtrl::MSWSetCharFormat(const wxTextAttr& style, long start, long end)
|
||||
wxFont font(style.GetFont());
|
||||
|
||||
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.bPitchAndFamily = lf.lfPitchAndFamily;
|
||||
wxStrlcpy(cf.szFaceName, lf.lfFaceName, WXSIZEOF(cf.szFaceName));
|
||||
@@ -3303,12 +3348,6 @@ bool wxTextCtrl::GetStyle(long position, wxTextAttr& style)
|
||||
|
||||
|
||||
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.lfCharSet = ANSI_CHARSET; // FIXME: how to get correct charset?
|
||||
lf.lfClipPrecision = 0;
|
||||
@@ -3341,7 +3380,10 @@ bool wxTextCtrl::GetStyle(long position, wxTextAttr& style)
|
||||
else
|
||||
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));
|
||||
font.SetFractionalPointSize(cf.yHeight / 20.0f); // 1 pt = 20 twips
|
||||
if (font.IsOk())
|
||||
{
|
||||
style.SetFont(font);
|
||||
|
Reference in New Issue
Block a user