字体大小缩放问题 [英] Font size scaling problems

查看:51
本文介绍了字体大小缩放问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个 C++ wxWidgets 计算器应用程序,当我调整窗口大小时,我希望我的 wxTextCtrl 和我的自定义按钮的字体能够缩放.

问题是:

  1. 我的按钮中的文本并不总是正好位于中心,但有时会略微偏离(尤其是在绿色和红色按钮中)
  2. 当我最大化窗口时,wxTextCtrl 的字体大小会更新,但当我最小化它时不会更新,让它覆盖屏幕的一半,直到我调整窗口大小,此时它会更新到正确的大小.

我正在使用此代码:

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)).家庭(wxFONTFAMILY_SWISS).FaceName(拉托").胆大());});

而且我使用非常相似的代码在我的自定义按钮类文件中生成字体:

ikeButton.cpp

void ikeButton::render(wxDC& dc){unsigned int w = this->GetSize().GetWidth();unsigned int h = this->GetSize().GetHeight();wxColour* bCol;如果(按下){dc.SetBrush(*pressedBackgroundColor);dc.SetTextForeground(*pressedTextColor);bCol = pressBorderColor;}否则如果(悬停){dc.SetBrush(*hoveredBackgroundColor);dc.SetTextForeground(*hoveredTextColor);bCol = hoveredBorderColor;}别的 {dc.SetBrush(*backgroundColor);dc.SetTextForeground(*textColor);bCol = 边框颜色;}dc.SetPen(*wxTRANSPARENT_PEN);dc.DrawRectangle(0, 0, w, h);//波尔多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);}//测试dc.SetFont(wxFontInfo(wxSize(0, this->GetSize().GetHeight()/3)).家庭(wxFONTFAMILY_SWISS).FaceName(拉托").光());dc.DrawText(text, w/2 - (GetTextExtent(text).GetWidth()),h/2 - (GetTextExtent(text).GetHeight()));}

解决方案

对于第二个问题,我真的不知道该怎么办.我认为在框架未最大化时从 size 事件设置字体大小会导致某些事情以意想不到的顺序完成并暂时破坏 wxWidgets 的布局系统.

到目前为止,我发现解决此问题的唯一方法是在恢复窗口时使用 WinAPI 调用注入额外的 Layout 调用.为此,请将此声明添加到您的框架类中:

#ifdef __WXMSW__bool MSWHandleMessage(WXLRESULT *result,WXUINT message,WXWPARAM wParam, WXLPARAM lParam) 覆盖;#endif//__WXMSW__

MSWHandleMessage 方法的主体将需要一些在 wrapwin.h 标头中定义的额外常量.因此,在框架的代码文件中,将此作为最后的 #include 行:

#ifdef __WXMSW__#include #endif//__WXMSW__

然后为 MSWHandleMessage

添加这个正文

#ifdef __WXMSW__bool MyFrame::MSWHandleMessage(WXLRESULT *result, WXUINT 消息,WXWPARAM wParam, WXLPARAM lParam){if ( message == WM_SYSCOMMAND && wParam == SC_RESTORE ){CallAfter([this](){Layout();});//我们还是想做默认处理,所以不设置结果//并返回真.}返回 wxFrame::MSWHandleMessage(result, message, wParam, lParam);}#endif//__WXMSW__

显然将MyFrame"更改为您的框架类的名称.


但我可以帮助解决第一个.

我认为当前在何处绘制文本的计算存在2个小问题.首先,我认为 GetTextExtent 应该在 dc 而不是窗口上调用.其次,我认为数学运算的顺序存在一个小问题.为了使文本居中,我认为 x 坐标的计算应该是 (w - GetTextExtent(text).GetWidth())/2.y 坐标的计算也应进行类似的更改.

我还会存储文本范围计算,而不是执行两次:

wxSize textExtent = dc.GetTextExtent(text);dc.DrawText(text, (w - textExtent.GetWidth())/2,(h - textExtent.GetHeight())/2);


请随意跳过下一部分.

有时您可以通过基于

ascent 可能是一个更好的数字的原因是高度将包含几个可能使文本看起来稍微不居中的填充元素.

wxSize textExtent = dc.GetTextExtent(text);wxFontMetrics 指标 = dc.GetFontMetrics();dc.DrawText(text, (w - textExtent.GetWidth())/2, (h - metrics.ascent)/2);

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.

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.

I'm using this code:

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:

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.

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. To do this, add this declaration to your frame 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. So in the code file for the frame, have this be the last #include line:

#ifdef __WXMSW__
    #include <wx/msw/wrapwin.h>
#endif // __WXMSW__

And then add this body for the 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.


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. 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. A similar change should be made in the calculation for the y coordinate.

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. Here's a diagram of what these font metrics mean from 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.

wxSize textExtent = dc.GetTextExtent(text);
wxFontMetrics metrics = dc.GetFontMetrics();
dc.DrawText(text, (w - textExtent.GetWidth()) / 2, (h - metrics.ascent) / 2);

这篇关于字体大小缩放问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆