尝试在 RichTextBox 中调整图像大小时光标闪烁

Cursor flickers when trying to resize image in RichTextBox

我希望这是一个简单的问题。我执行以下操作:

  1. 在 VS2010 中,我创建了一个 Windows 表单应用程序
  2. 从工具箱中,将 RichTextBox 控件拖到窗体中
  3. 调整窗体和 RichTextBox 控件的大小,使其足以显示小图片。
  4. 运行(开始调试)。
  5. 从网络浏览器复制小图像并粘贴到 richtextbox(使用 ctrl-v)。
  6. Select 富文本框中的图像。显示带有小框的调整大小框。

现在,当我将光标放在其中一个小尺寸调整器框上时,光标会闪烁。我看到了调整大小箭头光标的一瞥,但大多数时候它显示的是 I 型光标。它不会稳定地显示箭头光标,就像将图片粘贴到写字板并将光标放在其中一个小的调整大小框上时那样。在 RichTextBox 中调整图片大小是否应该与在 WordPad 中一样?如何停止光标闪烁?

使用以下属性

/// <summary>
/// The Lower property CreateParams is being used to reduce flicker
/// </summary>
protected override CreateParams CreateParams
{
    get
    {
        const int WS_EX_COMPOSITED = 0x02000000;
        var cp = base.CreateParams;
        cp.ExStyle |= WS_EX_COMPOSITED;
        return cp;
    }
}

我已经回答了

都2018年了,这个问题还在发生...

这不是最好的,但我创建了一个解决方法。我相信我们可以改进这段代码 --- 也许将来我会自己做。


您需要继承 RichTextBox 然后添加以下内容以强制 Cursor 成为它应该的样子。

请注意 Cursor 对于 对象 如图片或 I-Beam 对于文本是 Cross


工作原理:

  1. 每次 RichTextBox 请求 Cursor 变化(SetCursor),我们拦截它并检查对象是否是 Selected.

  2. 如果为真,则将光标更改为 Cross。如果为假,则将其更改为 I-Beam.


class RichTextBoxEx : RichTextBox
{
    private const int WM_SETCURSOR = 0x20;

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern IntPtr SetCursor(IntPtr hCursor);

    protected override void WndProc(ref Message m) {
        if (m.Msg == WM_SETCURSOR) 
        {
            if (SelectionType == RichTextBoxSelectionTypes.Object) 
            {
                // Necessary to avoid recursive calls
                if (Cursor != Cursors.Cross) 
                {
                    Cursor = Cursors.Cross;
                }
            }
            else 
            {
                // Necessary to avoid recursive calls
                if (Cursor != Cursors.IBeam) 
                {
                    Cursor = Cursors.IBeam;
                }
            }

            SetCursor(Cursor.Handle);
            return;
        }

        base.WndProc(ref m);
    }
}

通过这个 hack,您将能够在不闪烁的情况下调整图像大小,并且使用正确的 Arrows Cursors.

如何

首先你需要子类化 RichTextBox 并重写方法 WndProc,所以当 RichTextBox 接收到改变其 Cursor 的消息时,我们将检查如果图像是 select --- 好吧,我真的不知道它是否是 Image,但它是 Object 而不是 Text.

如果 Image 是 selected,我们将 message 重定向到 DefWndProc --- 这是默认的 Window 过程。

代码:

public class RichTextBoxEx : RichTextBox
{
    private const int WM_SETCURSOR = 0x20;

    protected override void WndProc(ref Message m) 
    {
        if (m.Msg == WM_SETCURSOR) 
        {
            if (SelectionType == RichTextBoxSelectionTypes.Object) 
            {
                DefWndProc(ref m);
                return;
            }
        }

        base.WndProc(ref m);
    }
}