WinForms TopLevel在窗体上的false导致TextBox鼠标选择混乱

时间:2019-06-20 18:17:22

标签: c# winforms

我从MDI应用程序开始,但是窗口管理不方便用户,因此我将所有内容都转换为选项卡式浏览模型。

当我使用TopLevel = false设置一个Form并将其设为另一个Form的子窗体时,一切正常,除非您单击TextBox中的文本,否则光标将移至TextBox的开头而不是您单击的位置。您不能单击特定的插入点,也不能选择文本范围。键盘输入不受影响。下面是一些简单的代码来重现此内容:

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        var form1 = new Form();
        var form2 = new Form();
        var tab = new TabControl();
        tab.TabPages.Add("first");
        tab.Dock = DockStyle.Fill;
        form2.TopLevel = false;
        form1.Controls.Add(tab);
        tab.TabPages[0].Controls.Add(form2);
        form2.Controls.Add(new TextBox { Top = 10, Left = 10, Text = "Blah blah blah" });
        form2.Controls.Add(new TextBox { Top = 35, Left = 10, Text = "more text here blah blah" });
        form2.Visible = true;
        Application.Run(form1);
    }
}

只需运行此示例代码,然后在任一文本框中单击文本中间。

我取代了WndProc,当在另一个框上单击时,表单按以下顺序显示以下消息(>表示嵌套调用的箭头数量):

> form2.WM_PARENTNOTIFY
> form1.WM_PARENTNOTIFY
> form2.WM_MOUSEACTIVATE
>> form1.WM_MOUSEACTIVATE
> form1.WM_WINDOWPOSCHANGING
> form1.WM_WINDOWPOSITIONCHANGED
> form1.WM_ACTIVATEAPP
> form1.WM_NCACTIVATE
> form1.WM_ACTIVATE

我还尝试了什么:我做了很多工作,将子窗体转换为带有标题栏,关闭按钮,拖动大小和移动等的UserControls,但是存在各种问题,事件无法正确连接,因为没有FormClosing / FormClosed事件,自定义控件找不到错误的父表单,等等。

因此,使孩子形成TopLevel = false而不是MdiChild确实符合我的需要,除了这个错误。所有其他控件都可以正确聚焦,并可以按预期与键盘和鼠标进行交互。这是WinForms TextBox控件的一个特定问题。

有人知道如何解决上述示例应用程序显示的TextBox焦点问题吗?

1 个答案:

答案 0 :(得分:0)

我事先做了很多搜索,但是直到发布后的第二天,我才通过相关问题功能找到了Windows Forms: Unable to Click to Focus a MaskedTextBox in a Non TopLevel Form。事实证明,这个问题大部分是该问题的重复。汉斯·帕森特(Hans Passant)对这个问题的回答为我提供了正确的方向。

将所有子表单转换为UserControls无效,因为原本由Form托管的内容正在查找顶层表单而不是子表单。但是Hans的答案指出,如果在表单上设置TopLevel = false且FormBorderStyle = None,则Form基本上会像普通控件一样工作。通过这种方式,所有希望使用Form的东西实际上都会得到Form。

因此,我为UserControls编写的所有窗口管理代码都非常有用(绘制和处理可拖动边框,标题栏,最大化和关闭按钮),而我要做的就是用TopLevel =将UserControls转换回Forms。 false,然后在OnShown中设置FormBorderStyle = None。