RichTextBox光标不断变为IBeam

5

我有一个只读的 RichTextBox,光标设置为箭头。然而,当我将鼠标悬停在其上时,光标会闪烁,并且在箭头IBeam之间迅速切换。我该如何让它保持在箭头状态而不闪烁?

2个回答

4
Jimi的答案可以有效地停止闪烁,但我对在鼠标移动时捕获鼠标没有好感。例如,在那个解决方案中,我看到一个问题,就是如果你在鼠标移动时设置捕获,那么像Alt+F4或Alt+Space这样的键盘快捷键将无法使用。
我更喜欢处理WndProc并在接收到WM_SETCURSOR时设置光标:
using System.Windows.Forms;
public class ExRichTextBox : RichTextBox
{
    const int WM_SETCURSOR = 0x0020;
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_SETCURSOR)
            Cursor.Current = this.Cursor;
        else
            base.WndProc(ref m);
    }
}

它停止闪烁了。虽然不是完美的解决方案,但至少那些重要的快捷方式将继续工作。


为什么它不完美? - Michael Haddad
1
例如,当您将鼠标悬停在链接上时,它不会显示手形图标。 - Reza Aghaei
1
从我在StackOverflow的经验来看,您是该网站上最好的WinForms专家之一(这可能意味着您是全球最好的之一)。所以我相信您有能力帮助WinForms社区回答这个非常重要的问题。 :D - Michael Haddad
是的,这就是为什么我不改变被接受的答案。Jimi的答案对我来说完全有效。 - Michael Haddad
1
不需要进行任何更改,除非分享一个完美的答案。我也不想影响其他答案,我也投了另一个答案的票。特别是当鼠标在richTextBox上时,如果有人想让Alt+F4起作用,可以使用另一种方法。 - Reza Aghaei
也许可以尝试玩弄DefWndProc被调用时传递的内容(前后)。不过这需要进行一些测试。 - Jimi

3
我假设这是WinForms的RichTextBox,因为WPF没有这个问题。
RichTextBox处理WM_SETCURSOR消息,如果鼠标指针停留在链接上,则将光标更改为Cursors.Hand。开发人员的一条注释:
RichTextBox使用WM_SETCURSOR消息来处理链接,以便我们将光标更改为手形。它通过同步通知消息来实现。因此,我们必须首先将消息传递给DefWndProc,然后,如果在此期间收到通知消息(通过更改“LinkCursor”指示),则将其设置为手形。否则,我们调用Control的WM_SETCURSOR实现来将RichTextBox的光标设置为用户的选择。
当鼠标进入控件范围时,可以设置捕获,然后在鼠标指针离开区域时释放它。必须释放捕获,否则,当您首次单击另一个控件时,光标将设置为RichTextBox。
private void richTextBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (!richTextBox1.ClientRectangle.Contains(e.Location)) {
        richTextBox1.Capture = false;
    }
    else if (!richTextBox1.Capture) {
        richTextBox1.Capture = true;
    }
}

更新,仅使用 MouseMove 事件。 - Jimi
1
我注意到了一些事情。当我将鼠标悬停在“RichTextBox”的边缘时,有时候IBeam又会在短暂的时间内重新出现。也许对有些人来说这是微不足道的,但它让我感到很疯狂。:D 我试图捕捉屏幕以展示它,但它太快了,即使使用60fps我也无法捕捉到它... - Michael Haddad
1
需要释放Capture的原因在答案中有解释。请参考Reza Aghaei所写的内容。当鼠标指针离开控件区域时,需要释放Capture,否则会引发某些错误行为。这也已经解释过了。如果你决定使用自定义控件,请参考如何在标签中对齐文本。除此之外,还有一些自定义RichTextBox支持块对齐(也称为完全对齐)。也许你会用到它。 - Jimi
1
@Jimi 我关于捕获的评论是,虽然当鼠标在控件外部时释放捕获,但当鼠标悬停在RichTextBox上时,Alt+F4将无法工作,因为RichTextBox已经捕获了鼠标。这不是关于鼠标离开时释放捕获的问题。 - Reza Aghaei
1
@Reza Aghaei,是的,我知道你的意思。我的评论是关于强制释放捕获的需求,因为原始问题(OP)显然决定在事件处理程序中只使用richTextBox1.Capture = true; - Jimi
显示剩余4条评论

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