下面是一个示例,说明如何创建一个具有您所描述的外观和行为方式的只读样式文本控件。 wxStyledTextCtrl 有很多很多方法,因此可以根据需要进一步自定义外观和行为。
MainText = new wxStyledTextCtrl(<parent>, wxID_ANY, wxDefaultPosition,
wxDefaultSize, wxBORDER_NONE);
// Set a small minimimum size.
MainText->SetMinClientSize(wxSize(0,0));
// Set the default style to use the Lato bold font.
MainText->StyleSetFaceName(0, "Lato");
MainText->StyleSetBold(0, true);
// Set the control read only and set the caret invisible.
MainText->SetReadOnly(true);
MainText->SetCaretStyle(wxSTC_CARETSTYLE_INVISIBLE);
// Hode the horizontal scroll bar and the left margin.
MainText->SetUseHorizontalScrollBar(false);
MainText->SetMarginWidth(1,0);
// Use the newer D2D drawing.
MainText->SetTechnology(wxSTC_TECHNOLOGY_DIRECTWRITE);
我在处理这个答案时了解到,有一个选项可以将插入符号设置为不可见,因此没有必要像我上面提到的那样将其设置为背景颜色。
要调整字体大小以填充大部分控件,您可以增加和减少缩放,直到文本大小足够。我认为这也应该解决您其他问题的尺寸问题。
MainText->Bind(wxEVT_SIZE, [this](wxSizeEvent& evt) {
evt.Skip();
int stcHt = evt.GetSize().GetHeight()/1.3;
int zoom = MainText->GetZoom();
if ( stcHt > MainText->TextHeight(0) )
{
// Increase the zoom until a line of text is taller than stcHt.
while ( stcHt > MainText->TextHeight(0) )
{
zoom = MainText->GetZoom();
MainText->SetZoom(zoom+1);
}
}
else
{
// Decrease the zoom until a line of text is shorter than stcHt.
while ( stcHt <= MainText->TextHeight(0) )
{
zoom = MainText->GetZoom();
MainText->SetZoom(zoom-1);
}
zoom = MainText->GetZoom();
}
MainText->SetZoom(zoom);
});
您说您正在更新文本以响应关键事件。要使用样式化文本控件执行此操作,您需要将控件设置为非只读,进行更改,然后将其设置回只读。像这样的:
MainText->SetReadOnly(false);
//update the text in response to the key event.
MainText->SetReadOnly(true);
您可以使用多种方法来更新文本。我认为最有可能有用的是InsertText、AppendText 和AddText。
如果您想尝试删除显示计算的文本和显示结果的文本之间的额外填充,有一个方法SetExtraAscent 可以传递一个负数来删除每行文本字符上方的额外空格。问题是输入是许多原始像素。但是 size 事件处理程序通过设置缩放来工作,因此每个缩放级别的像素数会有所不同。
虽然有一个解决方法。 MainText->TextHeight 返回的值基本上是我提到的指标上升、下降和内部领先的总和 here。为了去除每行顶部的额外填充,我们可以将SetExtraAscent 设置为基本上是内部前导的负数。
执行此操作的计算有点棘手。首先,我们可以估计字体的高度有多少是由内部前导组成的。我能想到的最简单的方法是创建一个临时内存 dc 并获取如下指标:
// Create a temporary memory dc to do some font calculations.
wxMemoryDC mem;
wxFont font(wxFontInfo(wxSize(0, 1000))
.Family(wxFONTFAMILY_SWISS)
.FaceName("Lato")
.Bold());
mem.SetFont(font);
wxFontMetrics metrics = mem.GetFontMetrics();
double internalLeadingPecent = static_cast<double>(metrics.internalLeading) /
static_cast<double>(metrics.height);
然后可以调整大小处理程序以尝试删除内部领先的内容,如下所示:
MainText->Bind(wxEVT_SIZE, [this, internalLeadingPecent](wxSizeEvent& evt) {
evt.Skip();
// First set the extra accent back to zero so that we get
MainText->SetExtraAscent(0);
int stcHt = evt.GetSize().GetHeight();
int zoom = MainText->GetZoom();
int internalLead = internalLeadingPecent*stcHt;
if ( stcHt > MainText->TextHeight(0) - internalLead )
{
// Increase the zoom until a line of text is taller than stcHt.
while ( stcHt > MainText->TextHeight(0) - internalLead)
{
zoom = MainText->GetZoom();
MainText->SetZoom(zoom+1);
}
}
else
{
// Decrease the zoom until a line of text is shorter than stcHt.
while ( stcHt <= MainText->TextHeight(0) - internalLead )
{
zoom = MainText->GetZoom();
MainText->SetZoom(zoom-1);
}
zoom = MainText->GetZoom();
}
MainText->SetExtraAscent(-1*internalLead);
MainText->SetZoom(zoom);
});
我的快速实验表明,这会删除样式文本控件与其上方窗口之间的大部分填充。如果您需要删除更多填充,您可以尝试进一步调整内容,例如删除 '-1.2*internalLead',如果这看起来效果更好的话。但这些调整只能通过实验找到。字体真的很难处理。