防止只读RichTextBox中闪烁光标(IBeam)的方法

10
有没有什么方法可以防止只读 RichTextBox 获得焦点时光标(IBeam)闪烁?
我尝试在 WndProc 中屏蔽 WM_SETFOCUS 消息,但这会导致窗体无响应。
if( m.Msg == 0x0007 ) return;
5个回答

10

你需要使用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
作为补充,当我在事件 textbox.GotFocus 中调用它时,我获得了成功。 - maxp

6
仅仅想说Anirudh Goel的答案在C#中不起作用。插入符仍然在那里闪烁。/p> 我在这里找到了解决方案: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);
        }
    }
}

5
更简单的方法:将此事件附加到RichTextBox的Enter事件上:
  private void Control_Enter(object sender, EventArgs e) {
    ActiveControl = null;
  }

这会导致表单中的所有控件失效。相反,我使用了ActiveControl = <MyFormClass>.ActiveForm; 这可以防止完全锁死。 - C4F
@TheC4Fox 我正在使用它,将事件仅附加到RichTextbox ENTER事件。这可以防止控件被鼠标单击或键盘TAB聚焦。通过更多的努力,您可以使其在用户使用TAB键时定位到下一个控件。我稍微修改了答案以使其更清晰明了。 - ChRoNoN

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控件中...这样就可以解决在鼠标单击时出现闪烁光标的问题了。

0

经过多次尝试和错误,我找到了简单的解决方案。

在你的表单的“Load”子程序中,添加以下行:

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不是很棒吗?您可以实现几乎任何您认为不可能的事情。


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