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

C# 尝试在RichTextBox中调整图像大小时,光标闪烁,c#,winforms,richtextbox,C#,Winforms,Richtextbox,我希望这是一个简单的问题。我做了以下工作: 在VS2010中,我创建了一个Windows窗体应用程序 从工具箱中,将RichTextBox控件拖动到窗体 将窗体和RichTextBox控件的大小调整到足以显示小图片的大小。 运行启动调试。 从web浏览器复制一个小图像,并使用ctrl-v将其粘贴到richtextbox。 在richtextbox中选择图像。将显示一个带有小框的调整大小框架。 现在,当我将光标放置在其中一个小的大小调整器框上时,光标会闪烁。我看到了调整大小箭头光标的一瞥,但大多数

我希望这是一个简单的问题。我做了以下工作:

在VS2010中,我创建了一个Windows窗体应用程序 从工具箱中,将RichTextBox控件拖动到窗体 将窗体和RichTextBox控件的大小调整到足以显示小图片的大小。 运行启动调试。 从web浏览器复制一个小图像,并使用ctrl-v将其粘贴到richtextbox。 在richtextbox中选择图像。将显示一个带有小框的调整大小框架。
现在,当我将光标放置在其中一个小的大小调整器框上时,光标会闪烁。我看到了调整大小箭头光标的一瞥,但大多数情况下,它显示的是工字钢光标。它不会像将图片粘贴到写字板中并将光标放置在其中一个小的调整大小框上那样稳定地显示箭头光标。在RichTextBox中调整图片大小是否应该与在写字板中相同?如何停止光标闪烁?

使用以下属性

/// <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子类化,然后添加以下内容以强制光标保持其应有状态

请注意,对于图片之类的对象,光标为十字,对于文本,光标为I型梁

工作原理:

每次RichTextBox请求游标更改SetCursor时,我们都会截取它并检查是否选择了一个对象

如果为true,则将光标更改为Cross。如果为false,则将其更改为I-Beam

有了这个技巧,你将能够在不闪烁的情况下调整图像的大小,并且使用正确的箭头和光标

怎么

首先,您需要对RichTextBox进行子类化,并重写方法WndProc,因此当RichTextBox接收到更改其光标的消息时,我们将检查图像是否为SelectWell,我不知道它是否为图像,但它是一个对象而不是文本

如果选择了图像,我们将消息重定向到DefWndProc,这是默认的窗口过程

守则:


这确实减少了闪烁-但现在我根本看不到鼠标悬停在调整大小框上时的调整箭头光标。谢谢你的建议。这确实消除了光标闪烁。但正如您所提到的,在选择图像时,始终显示一个十字光标。我希望有一个坚实的解决方案,当光标位于调整大小装饰上时,能够稳定地显示适当的调整大小光标,否则,当光标位于图像上时,会显示箭头,而当光标不在图像上时,会显示I形梁。这是写字板和MFC丰富的编辑控件中的行为。太棒了!我想知道是否有一种方法可以判断光标何时在图像上,而当光标不在图像上时则禁用更改。当你点击RichTextBox时,它会检查鼠标下方的内容。如果是图像或文本,也许我们可以找到发送给我们的信息。我希望有一天能发现it@Hal,我改进了代码。我终于摆脱了闪烁+1.边注:我不知道为什么你认为你的代码黑客。对WinForms控件进行子类化并重写不同的方法是很常见的。
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);
    }
}
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);
    }
}