【问题标题】:Prevent Blinking Cursor (IBeam) from a Read-Only RichTextBox防止从只读 RichTextBox 闪烁光标 (IBeam)
【发布时间】:2021-04-14 13:54:38
【问题描述】:

是否有办法防止只读RichRextBox 的光标(IBeam)在文本框获得焦点时闪烁?

我试图阻止来自WndProcWM_SETFOCUS 消息,但这会导致表单挂起。

if( m.Msg == 0x0007 ) return;

【问题讨论】:

    标签: winforms richtextbox


    【解决方案1】:

    您需要使用 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)
    

    当你想隐藏它时。

    【讨论】:

    • 作为附录,我在事件textbox.GotFocus中调用它时发现成功了@
    【解决方案2】:

    只是说 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);
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 这杀死了我表单中的所有控件。相反,我使用 ActiveControl = .ActiveForm;这可以防止完全锁定。
      • @TheC4Fox 我正在使用它,仅将事件附加到 RichTextbox ENTER 事件。这可以防止控件通过鼠标单击或键盘 TAB 完全聚焦。当用户使用 TAB 键时,您可以通过更多努力使其定位到下一个控件。我稍微修改了答案以使其更清楚。
      【解决方案4】:

      对我来说,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 放入(内部)面板控件... 修复了鼠标单击时插入符号闪烁的问题...

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

          猜你喜欢
          • 2010-10-10
          • 1970-01-01
          • 1970-01-01
          • 2020-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多