在 RichTextBox 中按下时如何更改 Enter KeyChar?

How to change the Enter KeyChar when pressed in a RichTextBox?

我目前的任务是为一些格式化文本编写文本编辑器。出于显而易见的原因,我选择使用 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 Signature...\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);
}

只有我按回车,没有按预期工作(对我没有影响):

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);
}

这里是结果:

事实证明,使用 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);
}