在 RichTextBox 的 TextChange 事件上计算日语文本长度时的性能问题

发布于 2024-11-05 08:07:06 字数 2391 浏览 0 评论 0原文

我有用 C# 2.0 编写的自定义 Richtextbox。用户将在此文本框中输入日语文本。当用户输入时,如果文本大小超过 300,它会以黄色突出显示多余的字符。日语文本可以包含半角和全角字符,我想将半角字符计为尺寸“0.5”,将全角字符计为尺寸“1”。

以下是我的代码...

Dictionary<int, float> charSizes = new Dictionary<int, float>();

void HighlightingTextBox_TextChanged(object sender, EventArgs e)
{
    int index = this.SelectionStart;

    // Reset highlighting and font.
    HighlightText(0, this.BackColor, true);

    // Highlight Text

    float charCount = 0;
    int highlightIndex = 0;

    string currentText = this.Text;

    for (int k = 0; k < currentText.Length; k++)
    {
        int c = currentText[k];

        if (charCount <= CharacterLimit)
        {
            if (charSizes.ContainsKey(c)) // Use already calculated Size
                charCount = charCount + charSizes[c];
            else
            {
                // Check if character is Half width or Full Width
                string charString = currentText[k].ToString();
                string fullChar = Microsoft.VisualBasic.Strings.StrConv(charString, Microsoft.VisualBasic.VbStrConv.Wide, 1041);

                if (c == (int)fullChar[0])
                {
                    // Ascci value matches after converting to full width. So its Full width char.
                    charCount++;
                    charSizes[c] = 1;
                }
                else
                {
                    charCount = charCount + 0.5f;
                    charSizes[c] = 0.5f;
                }
            }

            highlightIndex++;
        }

        // Enforce "Arial" font for English characters in Japanese text
        this.Select(k, 1);
        this.SelectionFont = (c < 128) ? new Font("Arial", 9.5f) : this.Font;
        this.SelectionLength = 0;
    }

    if (charCount > CharacterLimit)        
        HighlightText(highlightIndex, HighlightColor, false);

    this.SelectionStart = index;
}


private void HighlightText(int selectionStart, Color highlightColor, bool enforceFont)
{
    this.Select(selectionStart, this.Text.Length);
    this.SelectionBackColor = highlightColor;

    if (enforceFont)
        this.SelectionFont = this.Font;

    this.SelectionLength = 0;
}

问题是什么?

此代码对于前 8 到 10 个字符可以正常工作。但之后它的工作速度非常慢(需要很多时间,因为它正在遍历文本的“每个”字符)。如果用户打字速度很快,用户界面上需要几秒钟的时间才能出现新字符。

在这种情况下如何提高性能?这个计算还有其他方法吗?

I have custom richtextbox written in C# 2.0. User will enter Japanese text in this textbox. While user typing if text size goes beyond 300, it highlights the extra characters by yellow color. Japanese text can contain half width and full width character and I want to count half width character as Size "0.5" and Full width character as size "1".

Following is my code...

Dictionary<int, float> charSizes = new Dictionary<int, float>();

void HighlightingTextBox_TextChanged(object sender, EventArgs e)
{
    int index = this.SelectionStart;

    // Reset highlighting and font.
    HighlightText(0, this.BackColor, true);

    // Highlight Text

    float charCount = 0;
    int highlightIndex = 0;

    string currentText = this.Text;

    for (int k = 0; k < currentText.Length; k++)
    {
        int c = currentText[k];

        if (charCount <= CharacterLimit)
        {
            if (charSizes.ContainsKey(c)) // Use already calculated Size
                charCount = charCount + charSizes[c];
            else
            {
                // Check if character is Half width or Full Width
                string charString = currentText[k].ToString();
                string fullChar = Microsoft.VisualBasic.Strings.StrConv(charString, Microsoft.VisualBasic.VbStrConv.Wide, 1041);

                if (c == (int)fullChar[0])
                {
                    // Ascci value matches after converting to full width. So its Full width char.
                    charCount++;
                    charSizes[c] = 1;
                }
                else
                {
                    charCount = charCount + 0.5f;
                    charSizes[c] = 0.5f;
                }
            }

            highlightIndex++;
        }

        // Enforce "Arial" font for English characters in Japanese text
        this.Select(k, 1);
        this.SelectionFont = (c < 128) ? new Font("Arial", 9.5f) : this.Font;
        this.SelectionLength = 0;
    }

    if (charCount > CharacterLimit)        
        HighlightText(highlightIndex, HighlightColor, false);

    this.SelectionStart = index;
}


private void HighlightText(int selectionStart, Color highlightColor, bool enforceFont)
{
    this.Select(selectionStart, this.Text.Length);
    this.SelectionBackColor = highlightColor;

    if (enforceFont)
        this.SelectionFont = this.Font;

    this.SelectionLength = 0;
}

What is the problem?

This code works ok for first 8 to 10 characters. But after that it works very slow (takes lot of time as it is going through "EACH" character of text). If user types fast, it takes few seconds to appear new characters on UI..

How to improve the performance in this case? Is there any other way for this calculation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凉薄对峙 2024-11-12 08:07:06

在这种例程中获得性能的最简单方法是:只计算发生了什么变化。

只需比较新旧文本,查看添加或删除了哪些字符,然后根据它们修改总数。

通过这种方式,您一次不会计算多个。

--
此外,缓存您的 Arial 9.5 字体,而不是每次都创建一个新字体。


为了最大程度地减少处理对用户输入的干扰 - 仅当他们暂停设定的时间间隔时才更新它。

    private Timer _timer = new System.Windows.Forms.Timer();
    private bool _processingText;
    public MyRichTextBox()
    {
        _timer = new Timer();
        _timer.Interval = 1000;
        _timer.Tick += new EventHandler(ProcessText);
    }


    protected override void OnTextChanged(EventArgs e)
    {
        if (_processingText == false)
        {
            _timer.Stop();
            _timer.Start();
        }
    }

    private void ProcessText(object sender, EventArgs e)
    {
        _processingText = true;
        _timer.Stop();

        // Insert your processing logic here

        _processingText = false;
    }

The simplest way to gain performance in this kind of routine: Only calculate what changed.

Just compare the old and new text, see what character(s) are added or removed, and modify the total based just on them.

You are never calculating more than one at a time this way.

--
Additionally, cache your Arial 9.5 font rather than creating a new one each time.


To minimize the processing interfering with user typing - only update it when they pause a set interval.

    private Timer _timer = new System.Windows.Forms.Timer();
    private bool _processingText;
    public MyRichTextBox()
    {
        _timer = new Timer();
        _timer.Interval = 1000;
        _timer.Tick += new EventHandler(ProcessText);
    }


    protected override void OnTextChanged(EventArgs e)
    {
        if (_processingText == false)
        {
            _timer.Stop();
            _timer.Start();
        }
    }

    private void ProcessText(object sender, EventArgs e)
    {
        _processingText = true;
        _timer.Stop();

        // Insert your processing logic here

        _processingText = false;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文