【问题标题】:Hide caret in wxTextCtrl在 wxTextCtrl 中隐藏插入符号
【发布时间】:2021-08-26 13:05:06
【问题描述】:

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

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

有什么建议吗?

【问题讨论】:

  • 我不知道这是否可能。你有兴趣使用 wxStyledTextCtrl 吗?该控件更具可配置性,您可以将插入符号的颜色设置为与窗口背景相同的颜色,这实际上使其不可见。它也可能有助于解决其他问题中的尺寸问题。权衡是 wxStyledTextCtrl 是一个更复杂的控件。
  • 如果不是太复杂也没关系。你能给我举个例子吗?

标签: c++ wxwidgets caret wxtextctrl


【解决方案1】:

下面是一个示例,说明如何创建一个具有您所描述的外观和行为方式的只读样式文本控件。 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);

您可以使用多种方法来更新文本。我认为最有可能有用的是InsertTextAppendTextAddText


如果您想尝试删除显示计算的文本和显示结果的文本之间的额外填充,有一个方法SetExtraAscent 可以传递一个负数来删除每行文本字符上方的额外空格。问题是输入是许多原始像素。但是 size 事件处理程序通过设置缩放来工作,因此每个缩放级别的像素数会有所不同。

虽然有一个解决方法。 MainText-&gt;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',如果这看起来效果更好的话。但这些调整只能通过实验找到。字体真的很难处理。

【讨论】:

  • 非常感谢。您是否知道以不同方式格式化同一 wxStyledTextCtrl 的两个部分的任何方法(同时在调整窗口大小时也正确缩放字体大小)?因为我想在当前计算上方显示一个较小的灰色文本。现在我正在使用两个具有相同背景颜色的 wxTextCtrl,以使它们看起来连续,具有不同的前景色和字体大小。
  • 我认为最好坚持使用 2 个单独的控件。样式化的文本控件绝对有可能使第一行的文本大小较小且颜色为灰色,但是该控件将所有行设置为具有相同的高度。所以第一行将有额外的填充来填充与第二行一样多的空间。所以它看起来与上面发布的图片不同。
  • 我至少可以用 wxStyledTextCtrl 减少两者之间的垂直距离吗?因为现在,如上图所示,有一个令人讨厌的空白。
  • 我已经编辑了答案以展示如何使用样式文本控件方法SetExtraAscent 来尝试删除两个控件之间的一些填充。
猜你喜欢
  • 2010-10-09
  • 1970-01-01
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多