【问题标题】:RichTextBox doesn't start selection on mouse down when the form has not focus当窗体没有焦点时,RichTextBox 不会在鼠标按下时开始选择
【发布时间】:2016-08-15 02:20:18
【问题描述】:

我正在使用 WinForms,在我的表单上我有一个 RichTextBox。当我的表单失焦但可见并且我尝试突出显示/选择文本时,它不允许我这样做,直到表单或文本框本身具有焦点。

我试过了:

txtInput.MouseDown += (s, e) => { txtInput.Focus(); }

但无济于事,我似乎无法在网上找到有关此问题的任何信息。

使用记事本等其他程序进行测试时,它确实具有所需的行为。

【问题讨论】:

  • 这个问题我一开始没看懂。这是测试:打开记事本。输入一些随机文本。将注意力集中在另一个带有记事本的窗口上。在记事本中单击时按住鼠标按钮,就像要突出显示文本一样。在富文本框中尝试相同的操作。文本不会突出显示。
  • 设置HideSelection = false
  • @TaW 我也建议过,但是看了oppassum的评论后,我意识到问题可能是:RichTextBox selection is not working when the form没有焦点,而你可以例如,即使它没有焦点,也只需在 notepad.exe 上执行鼠标选择。它获得了焦点并继续选择,但对于 RichTextBox 仅获得了焦点并进行选择,您应该再次按下鼠标。
  • @reza:啊,确实,我没抓住重点。

标签: c# .net winforms selection richtextbox


【解决方案1】:

您可以使用MouseDownMouseMove 事件手动进行选择。答案基于Taw的第一个想法:

int start = 0;
private void richTextBox1_MouseDown(object sender, MouseEventArgs e)
{
    start = richTextBox1.GetTrueIndexPositionFromPoint(e.Location);
    richTextBox1.SelectionStart = start;
}

private void richTextBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button.HasFlag(MouseButtons.Left))
    {
        var current = richTextBox1.GetTrueIndexPositionFromPoint(e.Location);
        richTextBox1.SelectionStart = Math.Min(current, start);
        richTextBox1.SelectionLength = Math.Abs(current - start);
    }
}

这里是来自JustinGetTrueIndexPositionFromPoint 方法的代码:

public static class RichTextBoxExtensions
{
    private const int EM_CHARFROMPOS = 0x00D7;
    public static int GetTrueIndexPositionFromPoint(this RichTextBox rtb, Point pt)
    {
        POINT wpt = new POINT(pt.X, pt.Y);
        int index = (int)SendMessage(new HandleRef(rtb, rtb.Handle), EM_CHARFROMPOS, 0, wpt);
        return index;
    }

    [DllImport("User32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
    private static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, POINT lParam);
}

【讨论】:

  • 嗯,对不起,但我不能说它对我有任何帮助。也许我累了;-)
【解决方案2】:

MouseDown 为时已晚。

这肯定是一种解决方法,但可能就是您所需要的:

private void txtInput_MouseMove(object sender, MouseEventArgs e)
{
    txtInput.Focus();
}

或者当然:

txtInput.MouseMove += (s, e) => { txtInput.Focus(); }

当您移过文本框时,它可能会从表单上的其他控件中窃取焦点。如果这是一个问题,您可以通过使用answers here.. 之一检查您的程序是否处于活动状态来防止它

【讨论】:

    【解决方案3】:

    这个解决方案对我不起作用,因为我的子窗口有一个 TextBox,当我将鼠标悬停在 RichTextBox 上时它会失去焦点。经过反复试验,我设法找到了另一种解决方案:

        private const int WM_PARENTNOTIFY = 0x0210;
    
        private Form Form = new Form(); // Your Form here!
        private RichTextBox RTB = new RichTextBox(); // Your RichTextBox here!
    
        protected override void WndProc(ref Message m) 
        {
            if ((m.Msg == WM_PARENTNOTIFY) && (Form != null) && (Form.Visible) && (GetChildAtPoint(PointToClient(Cursor.Position)) == RTB))
            {
                RTB.Focus();
            }
    
            base.WndProc(ref m);
        }
    

    WM_PARENTNOTIFY 消息可以多次发送(包括在初始化主表单时),因此检查您的表单是否为空非常重要,否则您将收到异常。

    【讨论】:

      【解决方案4】:

      这对我有用;

      扩展 RichTextBox 并以此覆盖 WindowProc

      protected override void WndProc(ref Message m) {
          const int WM_MOUSEACTIVATE = 0x21;
      
          if (m.Msg == WM_MOUSEACTIVATE) {
              // Take focus to enable click-through behavior for setting selection
              this.Focus();
          }
      
          // Let the base handle the event.
          base.WndProc(ref m);
      }
      

      【讨论】:

        猜你喜欢
        • 2019-05-22
        • 2013-06-22
        • 1970-01-01
        • 2013-12-25
        • 2016-02-07
        • 2013-04-04
        • 1970-01-01
        • 1970-01-01
        • 2010-10-22
        相关资源
        最近更新 更多