当窗体没有焦点时,富文本框不会在鼠标按下时开始选择

本文关键字:鼠标 选择 开始 文本 窗体 焦点 | 更新日期: 2024-11-06 08:00:01

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

我试过:

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

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

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

当窗体没有焦点时,富文本框不会在鼠标按下时开始选择

MouseDown

时已晚。

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

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

或者当然:

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

因为它可能会在您移动到文本框上时从窗体上的其他控件窃取焦点。如果这是一个问题,您可以通过使用此处的答案之一检查您的程序是否处于活动状态来防止它。

您可以使用

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);
    }
}

这是从贾斯汀那里获取GetTrueIndexPositionFromPoint方法的代码:

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);
}
这对

我有用;

扩展 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);
}

这个灵魂对我不起作用,因为我的子窗口有一个文本框,当我将鼠标悬停在富文本框上时会失去焦点。经过一些试验和错误,我设法找到了另一种解决方案:

    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消息可以多次发送(包括在初始化主表单时),因此请务必检查您的表单是否不为空,否则您将收到异常。