防止从只读RichTextBox中闪烁光标(IBeam)

时间:2009-04-09 12:38:35

标签: winforms richtextbox

无论如何,只要文本框得到焦点,是否会阻止只读RichRextBox的光标(IBeam)闪烁?

我试图阻止来自WM_SETFOCUS的{​​{1}}消息,但它会导致表单挂起。

WndProc

5 个答案:

答案 0 :(得分:9)

您需要使用Win32 API。这是你在VB中可以做的:

'API declares
Private Declare Function HideCaret Lib "user32" _
(ByVal hwnd As IntPtr) As Integer
Private Declare Function ShowCaret Lib "user32" _
(ByVal hwnd As IntPtr) As Integer
'hide the caret in myTextBox
Call HideCaret(myTextBox.Handle)
'show the caret back..
Call ShowCaret(myTextBox.Handle)

和C#

 [DllImport("user32.dll", EntryPoint = "ShowCaret")]
 public static extern long ShowCaret(IntPtr hwnd);
 [DllImport("user32.dll", EntryPoint = "HideCaret")]
 public static extern long HideCaret(IntPtr hwnd);

然后拨打

   HideCaret(richtextbox.Handle)

什么时候你想隐藏它。

答案 1 :(得分:6)

只是说Anirudh Goel的答案不起作用(至少在C#中)。克拉仍然闪烁着:/

我在http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_21896403.html

找到了解决方案

他的班级总是隐藏插入符号,这里是一个改进的符号,所以你可以选择隐藏或不隐藏插入符号。

如果你想隐藏不要忘记将MustHideCaret设置为true

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Lm
{
    public class RichTextBoxEx : RichTextBox
    {
        private readonly object mustHideCaretLocker = new object();

        private bool mustHideCaret;

        [DefaultValue(false)]
        public bool MustHideCaret
        {
            get
            {
                lock (this.mustHideCaretLocker)
                    return this.mustHideCaret;
            }
            set
            {
                TabStop = false;
                if (value)
                    SetHideCaret();
                else
                    SetShowCaret();
            }
        }

        [DllImport("user32.dll")]
        private static extern int HideCaret(IntPtr hwnd);
        [DllImport("user32.dll", EntryPoint = "ShowCaret")]
        public static extern long ShowCaret(IntPtr hwnd);

        public RichTextBoxEx()
        {
        }

        private void SetHideCaret()
        {
            MouseDown += new MouseEventHandler(ReadOnlyRichTextBox_Mouse);
            MouseUp += new MouseEventHandler(ReadOnlyRichTextBox_Mouse);
            Resize += new EventHandler(ReadOnlyRichTextBox_Resize);
            HideCaret(Handle);
            lock (this.mustHideCaretLocker)
                this.mustHideCaret = true;
        }

        private void SetShowCaret()
        {
            try
            {
                MouseDown -= new MouseEventHandler(ReadOnlyRichTextBox_Mouse);
                MouseUp -= new MouseEventHandler(ReadOnlyRichTextBox_Mouse);
                Resize -= new EventHandler(ReadOnlyRichTextBox_Resize);
            }
            catch
            {
            }
            ShowCaret(Handle);
            lock (this.mustHideCaretLocker)
                this.mustHideCaret = false;
        }

        protected override void OnGotFocus(EventArgs e)
        {
            if (MustHideCaret)
                HideCaret(Handle);
        }

        protected override void OnEnter(EventArgs e)
        {
            if (MustHideCaret)
                HideCaret(Handle);
        }

        private void ReadOnlyRichTextBox_Mouse(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            HideCaret(Handle);
        }

        private void ReadOnlyRichTextBox_Resize(object sender, System.EventArgs e)
        {
            HideCaret(Handle);
        }
    }
}

答案 2 :(得分:5)

更简单的方法:将此事件附加到RichTextBox的Enter事件:

  private void Control_Enter(object sender, EventArgs e) {
    ActiveControl = null;
  }

答案 3 :(得分:1)

对我来说,Pedro77的解决方案也不起作用...... 我已将该课程修改为:

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Lm
{
    public class RichTextBoxEx : RichTextBox
    {
        private readonly object mustHideCaretLocker = new object();

        private bool mustHideCaret;

        [DefaultValue(false)]
        public bool MustHideCaret
        {
            get
            {
                lock (this.mustHideCaretLocker)
                    return this.mustHideCaret;
            }
            set
            {
                TabStop = false;
                if (value)
                    SetHideCaret();
                else
                    SetShowCaret();
            }
        }

        [DllImport("user32.dll")]
        private static extern int HideCaret(IntPtr hwnd);
        [DllImport("user32.dll", EntryPoint = "ShowCaret")]
        public static extern long ShowCaret(IntPtr hwnd);

        public RichTextBoxEx()
        {
        }

        private void SetHideCaret()
        {
            MouseDown += new MouseEventHandler(ReadOnlyRichTextBox_Mouse);
            MouseUp += new MouseEventHandler(ReadOnlyRichTextBox_Mouse);
            Resize += new EventHandler(ReadOnlyRichTextBox_Resize);
            HideCaret(Handle);
            lock (this.mustHideCaretLocker)
                this.mustHideCaret = true;
        }

        private void SetShowCaret()
        {
            try
            {
                MouseDown -= new MouseEventHandler(ReadOnlyRichTextBox_Mouse);
                MouseUp -= new MouseEventHandler(ReadOnlyRichTextBox_Mouse);
                Resize -= new EventHandler(ReadOnlyRichTextBox_Resize);
            }
            catch
            {
            }
            ShowCaret(Handle);
            lock (this.mustHideCaretLocker)
                this.mustHideCaret = false;
        }

        protected override void OnGotFocus(EventArgs e)
        {
            if (MustHideCaret)
            {
                HideCaret(Handle);
                this.Parent.Focus();//here we select parent control in my case it is panel
            }
        }

        protected override void OnEnter(EventArgs e)
        {
            if (MustHideCaret)
                HideCaret(Handle);
        }

        private void ReadOnlyRichTextBox_Mouse(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            HideCaret(Handle);
        }

        private void ReadOnlyRichTextBox_Resize(object sender, System.EventArgs e)
        {
            HideCaret(Handle);
        }
    }
}

然后将我的RichTextBoxEx放入(内部)Panel控件中...... 修复了点击鼠标时闪烁的插入符号...

答案 4 :(得分:0)

经过多次反复试验,我找到了简单的解决方案。

在表单的“加载”子例程中,添加以下行:

AddFocusHandlers(Me)

然后将以下内容添加到表单代码的底部。在“HideCaret”例程中规定您希望在其上发生“阻止进入”的控件 (我列出了属于我的表单的三个文本框):

Private Sub AddFocusHandlers(ByVal parentCtr As Control)
    Dim ctr As Control
    For Each ctr In parentCtr.Controls
        AddHandler ctr.LostFocus, AddressOf meLostFocus
        AddFocusHandlers(ctr)
    Next
End Sub

Private Sub meLostFocus(ByVal sender As Object, ByVal e As System.EventArgs)
    LastFocused = DirectCast(sender, Control)
End Sub

'This routine will activate each time any of the listed controls are entered.
Private Sub HideCaret(sender As Object, e As EventArgs) _
               Handles tbDate.Enter, tbAttachments.Enter, tbTemplate.Enter
    LastFocused.Select()
End Sub

最后放在表单代码的顶部(在类名和第一个子或函数之间:

    Private LastFocused As Control  'Control which previously had focus

然后,当用户单击“HideCaret”例程中控件列表中显示的任何控件时,光标只会停留在先前选择的控件中。 VB.Net 是不是很棒?您几乎可以实现任何您认为不可能的事情。