在RichTextBox中调整图像大小时,光标闪烁。

4
我希望这是一个简单的问题。我执行以下操作:
  1. 在VS2010中创建一个Windows表单应用程序
  2. 从工具箱中将RichTextBox控件拖到表单上
  3. 调整表单和RichTextBox控件的大小,使其足够大以显示小图片。
  4. 运行(启动调试)。
  5. 从Web浏览器复制一张小图片并粘贴到richtextbox中(使用ctrl-v)。
  6. 在richtextbox中选择图像。 小框中显示了调整大小的框。
现在当我将光标定位在其中一个小调整大小框上时,光标会闪烁。 我看到缩放箭头光标的一瞥,但大多数情况下它显示I-beam光标。 当将图片粘贴到WordPad中并将光标放置在小调整大小框上时,它不会稳定地显示箭头光标。 RichTextBox中的图片调整大小是否应与WordPad中相同? 我该如何停止光标闪烁?
3个回答

2
使用这个技巧,您将能够在不闪烁的情况下调整图像大小,并使用正确的箭头光标。
如何操作:
首先,您需要对RichTextBox进行子类化并覆盖WndProc方法,以便当RichTextBox接收更改其光标的消息时,我们将检查是否选择了图像---好吧,我不知道它是否是一个图像,但它是一个对象而不是文本。
如果选择了图像,则将消息重定向到DefWndProc --- 这是默认窗口过程。
代码如下:
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);
    }
}

太好了!我在想是否有一种方法可以判断光标是否正在图像上方,并在不在时禁用更改。也许这样可以消除其他闪烁问题。 - Hal
当您单击“RichTextBox”时,它将检查鼠标下方的内容。也许我们可以找到发送给“known”的“message”是一个“Image”还是一个“Text”。(希望有一天我能发现它) - D.Kastier
1
@Hal,我改进了代码。我终于摆脱了闪烁问题! - D.Kastier
附注:我不知道为什么你认为你的代码是黑客行为。子类化WinForms控件并覆盖不同方法是很常见的。 - Xam

1

现在已经是2018年了,这个问题仍然存在...

虽然不是最好的解决方法,但我想出了一个变通办法。我相信我们可以改进这段代码 --- 也许将来我会自己做到。


你需要创建RichTextBox的子类,然后添加以下内容来强制Cursor显示为应有的样子。
请注意,Cursor要么是Cross(如图片等对象),要么是I-Beam(如文本)。

工作原理:

  1. 每当 RichTextBox 请求光标更改 (SetCursor) 时,我们拦截它并检查是否选择了对象。

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

谢谢您的建议。这确实消除了光标闪烁。但是,正如您所提到的,当选择图像时,它会一直显示十字光标。我希望有一个稳定的解决方案,当鼠标指针位于调整装饰物上时,能够显示适当的调整大小光标,否则当指针在图像上时显示箭头,并在不在图像上时显示I型光标。这是WordPad和MFC Rich Edit Control中的行为。 - Hal

0
请使用以下属性:
/// <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;
    }
}

我已经在这里回答了。


那确实减少了闪烁 - 但现在当鼠标悬停在调整大小的框上时,我根本看不到调整大小箭头光标。 - Hal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接