简体   繁体   English

字体大小缩放问题

[英]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:问题是:

  1. The text in my buttons isn't always precisely in the center, but sometimes slightly off (especially in the green and red buttons)我的按钮中的文本并不总是精确地在中心,但有时会稍微偏离(尤其是在绿色和红色按钮中)
  2. When I maximize the window, the wxTextCtrl's font size updates, but not when I minimize it, leaving it to cover half the screen until I resize the window, at which point it updates to the correct size.当我最大化 window 时,wxTextCtrl 的字体大小会更新,但当我最小化它时不会更新,让它覆盖一半屏幕,直到我调整 window 的大小,此时它会更新到正确的大小。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM