【问题标题】:How to change the Enter KeyChar when pressed in a RichTextBox?在 RichTextBox 中按下时如何更改 Enter KeyChar?
【发布时间】:2022-01-20 22:11:20
【问题描述】:

我目前的任务是为一些格式化文本编写一个文本编辑器。出于显而易见的原因,我选择使用 RichTextBox。到目前为止,对于每个键,我都可以修改它的 KeyChar,方法是覆盖 ProcessCmdKey 方法或订阅 KeyPress 事件或覆盖 virtual 方法 OnKeyPress

我在这个例子中使用的 rtf 文本是这样的:

{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Courier New;}{\f1\fnil Courier New;}{\f2\fnil Verdana;}} {\colortbl ;\red0\green0\blue0;} {*\generator Riched20 10.0.19041}\viewkind4\uc1 \pard\sa180\sl72\slmult1\ulc1\ul\b\f0\fs21 Header1:\ulc1\ulnone\b0\f1\line\ulc1\f0 ​​Lorem ipsum。\ulc1\f1\line\ulc1\f0 ​​Lorem ipsum。 \ulc1\f1\line\ulc1\f0 ​​Lorem ipsum.\ulc1\f1\line\ulc1\f0 ​​Lorem ipsum.\ulc1\f1\line\ulc1\f0 ​​Lorem ipsum.\ulc1\f1\line\ulc1\ul\ b\f0 Header2:\ulc1\ulnone\b0\f1\line\ulc1\f0 ​​Lorem ipsum.\ulc1\f1\line\ulc1\f0 ​​Lorem ipsum.\ulc1\f1\line\ulc1\f0 ​​Lorem ipsum.\ulc1 \f1\line\ulc1\f0 ​​Lorem ipsum.\ulc1\f1\line\ulc1\f0 ​​Lorem ipsum.\ulc1\f1\line\ulc1\ul\b\f0 Header3:\ulc1\ulnone\b0\f1\line \ulc1\f0 ​​Lorem ipsum.\ulc1\f1\line\ulc1\f0 ​​Lorem ipsum.\ulc1\f1\line\ulc1\f0 ​​Lorem ipsum.\ulc1\f1\line\ulc1\f0 ​​Lorem ipsum.\ulc1\f1 \line\ulc1\f0 ​​Lorem ipsum.\ulc1\f1\line\line\ulc1\f0 ​​签名...\ulc1\f2\fs20\par }

因此,对于这个 rtf,我基本上是在每次用户按 Enter 时模拟 Shift + Enter,以便在按 Enter 时换行符小于默认换行符。

我为此声明了我自己的RichTextBox,希望我能更深入地挖掘:

public class CustomRichTextBox : RichTextBox { ... }

澄清我到目前为止尝试的方法 - 这些是我的方法,非常适合普通字符:

使用ProcessCmdKey将字符A改为B:

protected override bool ProcessCmdKey(ref Message m, Keys keyData)
{
    if(keyData == Keys.A)
    {
        m.WParam = new IntPtr((int)Keys.B);
        return base.ProcessCmdKey(ref m, Keys.B);
    }
    else if(keyData == (Keys.Shift | Keys.A))
    {
        m.WParam = new IntPtr((int)(Keys.Shift | Keys.B));
        return base.ProcessCmdKey(ref m, (Keys.Shift | Keys.B));
    }

    return base.ProcessCmdKey(ref m, keyData);
}

使用OnKeyPress将字符A改为B:

protected override void OnKeyPress(KeyPressEventArgs e)
{
    if(e.KeyChar == 'A')
    {
        e.KeyChar = 'B';
    }
    else if(e.KeyChar == 'a')
    {
        e.KeyChar = 'b';
    }

    base.OnKeyPress(e);
}

仅对我按 Enter 键,它不能按预期工作(对我没有影响):

protected override bool ProcessCmdKey(ref Message m, Keys keyData)
{
    if (keyData == Keys.Enter)
    {
        m.WParam = new IntPtr((int)(Keys.Shift | Keys.Enter));
        return base.ProcessCmdKey(ref m, (Keys.Shift | Keys.Enter));
    }

    return base.ProcessCmdKey(ref m, keyData);
}

没有简单的方法来实现这一点还是我错过了什么?

编辑:

我忘记在OnKeyPress 中包含该方法。这是我尝试过的:

protected override void OnKeyPress(KeyPressEventArgs e)
{
     if(e.KeyChar == '\r')
     {
         e.KeyChar = '\u2028';
     }

     base.OnKeyPress(e);
}

结果如下:

【问题讨论】:

  • 你试过在OnKeyPress()处理它吗? if (e.KeyChar == (char)Keys.Return) ...
  • @MatthewWatson 是的,我试过了。我在那里检测到 '\r' 字符。 ('\n' 我在那里找不到)。然后,如果我将其替换为“\u2028”,则行为会变得很奇怪:我有两个,而不是一个正常的换行符。

标签: c# winforms richtextbox


【解决方案1】:

事实证明,使用 SendKeys 并通过返回 true 来阻止 Enter KeyPress 非常容易实现...

private bool sendingEnter = false;

public override bool PreProcessMessage(ref Message msg)
{
    if(msg.Msg == WM_KEYDOWN && msg.WParam.ToInt32() == VK_RETURN)
    {
        if (!sendingEnter)
        {
            sendingEnter = true;
            SendKeys.Send("+{ENTER}");
            return true;
        }
        else
        {
            sendingEnter = false;
        }
    }

    return base.PreProcessMessage(ref msg);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-24
    • 1970-01-01
    • 2015-04-28
    • 1970-01-01
    • 2013-08-14
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多