在 wxTextCtrl 中隐藏插入符

Hide caret in wxTextCtrl

我正在创建一个 C++ wxWidgets 计算器应用程序。我有一个显示当前计算的 wxTextCtrl。它被设置为只读,因为我正在使用 wxKeyEvent 来写入它。问题是,虽然它被设置为只读,插入符号仍然显示:

我希望文本控件中的文本可选择且不可编辑,并且没有插入符号。

有什么建议吗?

下面是一个示例,说明如何创建外观和行为应与您描述的方式一致的只读样式文本控件。 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, and AddText.


如果你想尝试删除显示计算的文本和显示结果的文本之间的额外填充,有方法 SetExtraAscent 可以传递一个负数来删除额外的 space 每行上面的文字字符。问题是输入是一些原始像素。然而,大小事件处理程序通过设置缩放来工作,因此每个缩放级别的像素数将不同。

虽然有一个解决方法。 MainText->TextHeight 返回的值基本上是我提到的 指标上升、下降和内部领先的总和。要删除每行顶部的额外填充,我们可以将 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);
});

我的快速实验表明,这会删除带样式的文本控件与其上方 window 之间的大部分填充。如果您需要删除更多填充,您可以尝试进一步调整,例如删除“-1.2*internalLead”(如果这样看起来效果更好)。但这些调整只能通过试验找到。字体真的很难对付。