[英]Font size scaling problems
I'm writing a C++ wxWidgets calculator application, and I want the font of my wxTextCtrl's and my custom buttons to scale when I resize the window.我正在编写一个 C++ wxWidgets 计算器应用程序,并且我希望在调整 window 的大小时缩放我的 wxTextCtrl 和自定义按钮的字体。
The problems are:问题是:
I'm using this code:我正在使用这段代码:
text_controls.cpp text_controls.cpp
MainText = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_READONLY | wxNO_BORDER);
MainText->SetForegroundColour(wxColour(55, 55, 55));
MainText->Bind(wxEVT_TEXT, &Main::OnTextChange, this);
MainText->Bind(wxEVT_SIZE, [this](wxSizeEvent& evt) {
evt.Skip();
MainText->SetFont(
wxFontInfo(wxSize(0, MainText->GetSize().y / 1.3))
.Family(wxFONTFAMILY_SWISS)
.FaceName("Lato")
.Bold()
);
});
And I'm using very similar code to generate the font in my custom button class file:我使用非常相似的代码在我的自定义按钮 class 文件中生成字体:
ikeButton.cpp ikeButton.cpp
void ikeButton::render(wxDC& dc)
{
unsigned int w = this->GetSize().GetWidth();
unsigned int h = this->GetSize().GetHeight();
wxColour* bCol;
if (pressed) {
dc.SetBrush(*pressedBackgroundColor);
dc.SetTextForeground(*pressedTextColor);
bCol = pressedBorderColor;
}
else if (hovered) {
dc.SetBrush(*hoveredBackgroundColor);
dc.SetTextForeground(*hoveredTextColor);
bCol = hoveredBorderColor;
}
else {
dc.SetBrush(*backgroundColor);
dc.SetTextForeground(*textColor);
bCol = borderColor;
}
dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawRectangle(0, 0, w, h);
//bordo
if (borderTh && bCol != NULL)
{
dc.SetBrush(*bCol);
dc.DrawRectangle(0, 0, w, borderTh);
dc.DrawRectangle(w - borderTh, 0, borderTh, h);
dc.DrawRectangle(0, h - borderTh, w, borderTh);
dc.DrawRectangle(0, 0, borderTh, h);
}
//testo
dc.SetFont(
wxFontInfo(wxSize(0, this->GetSize().GetHeight() / 3))
.Family(wxFONTFAMILY_SWISS)
.FaceName("Lato")
.Light()
);
dc.DrawText(text, w / 2 - (GetTextExtent(text).GetWidth()),
h / 2 - (GetTextExtent(text).GetHeight()));
}
I'm really not sure what to do about the second problem.我真的不确定如何处理第二个问题。 I think setting the font size from the size event when the frame is unmaximized causes something to be done in an unexpected order and temporarily breaks wxWidgets' layout system.我认为当框架未最大化时从 size 事件设置字体大小会导致某些事情以意外的顺序完成并暂时破坏 wxWidgets 的布局系统。
The only way I've found to workaround this so far is to use WinAPI calls to inject an extra Layout
call when the window is restored.到目前为止,我发现解决此问题的唯一方法是在 window 恢复时使用 WinAPI 调用来注入额外的Layout
调用。 To do this, add this declaration to your frame class:为此,请将此声明添加到您的框架 class:
#ifdef __WXMSW__
bool MSWHandleMessage(WXLRESULT *result,WXUINT message,
WXWPARAM wParam, WXLPARAM lParam) override;
#endif // __WXMSW__
The body of the MSWHandleMessage
method will need some extra constants that are defined in the wrapwin.h header. MSWHandleMessage
方法的主体将需要一些在 wrapwin.h header 中定义的额外常量。 So in the code file for the frame, have this be the last #include
line:因此,在框架的代码文件中,将其作为最后的#include
行:
#ifdef __WXMSW__
#include <wx/msw/wrapwin.h>
#endif // __WXMSW__
And then add this body for the MSWHandleMessage
然后为MSWHandleMessage
添加这个正文
#ifdef __WXMSW__
bool MyFrame::MSWHandleMessage(WXLRESULT *result, WXUINT message,
WXWPARAM wParam, WXLPARAM lParam)
{
if ( message == WM_SYSCOMMAND && wParam == SC_RESTORE )
{
CallAfter([this](){Layout();});
// We still want to do the default processing, so do not set a result
// and return true.
}
return wxFrame::MSWHandleMessage(result, message, wParam, lParam);
}
#endif // __WXMSW__
Obviously change 'MyFrame' to the name of your frame class.显然将“MyFrame”更改为您的框架 class 的名称。
But I can help with the first one.但我可以帮助第一个。
I think there are 2 small problems with the current calculation of where to draw the text.我认为当前在哪里绘制文本的计算存在两个小问题。 First, I think GetTextExtent
should be called on the dc instead of the window.首先,我认为应该在 dc 上调用GetTextExtent
而不是 window。 Second, I think there is a slight problem with order of the math operations.其次,我认为数学运算的顺序有一点问题。 To center the text, I think the calculation for the x coordinate should be (w - GetTextExtent(text).GetWidth()) / 2
.为了使文本居中,我认为 x 坐标的计算应该是(w - GetTextExtent(text).GetWidth()) / 2
。 A similar change should be made in the calculation for the y coordinate.应在 y 坐标的计算中进行类似的更改。
I would also store the text extent calculation instead of doing it twice:我还将存储文本范围计算而不是两次:
wxSize textExtent = dc.GetTextExtent(text);
dc.DrawText(text, (w - textExtent.GetWidth())/ 2,
(h - textExtent.GetHeight())/2);
Feel free to skip this next part.随意跳过下一部分。
You can sometimes center text vertically better by basing the calculation on a font metric named ascent instead of the text height.您有时可以通过基于名为 ascent 的字体度量而不是文本高度的计算来更好地垂直居中文本。 Here's a diagram of what these font metrics mean from Microsoft这是Microsoft对这些字体指标的含义的图表
The reason ascent might be a better number to use is that the height will include several padding elements that might make the text look slightly uncentered. ascent 可能是一个更好的使用数字的原因是高度将包含几个填充元素,这可能会使文本看起来有点不居中。
wxSize textExtent = dc.GetTextExtent(text);
wxFontMetrics metrics = dc.GetFontMetrics();
dc.DrawText(text, (w - textExtent.GetWidth()) / 2, (h - metrics.ascent) / 2);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.