c# - WinForms TopLevel false 表单与 TextBox 鼠标选择混淆
问题描述
我从一个 MDI 应用程序开始,但窗口管理对用户不友好,所以我将所有内容都转换为选项卡式浏览模型。
当我使用 TopLevel = false 设置一个表单并将其设置为另一个表单的子级时,一切正常,除了当您单击 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
我还尝试了什么:我做了很多工作,将子表单转换为带有标题栏、关闭按钮、拖动调整大小和移动等的用户控件,但是它出现了各种各样的问题,事件没有正确连接,因为没有FormClosing/FormClosed 事件、自定义控件查找错误的父表单等。
因此,使子窗体 TopLevel = false 而不是 MdiChild 正是我需要的,除了这个错误。所有其他控件都正确获得焦点,并按预期与键盘和鼠标交互。这是 WinForms TextBox 控件的一个特定问题。
有谁知道如何解决上述示例应用程序显示的 TextBox 焦点问题?
解决方案
我事先做了一大堆搜索,但直到发布后的第二天,我才发现Windows Forms: Unable to Click to Focus a MaskedTextBox in a Non TopLevel Form via the related questions feature。事实证明,这个问题主要是那个问题的重复。Hans Passant 对这个问题的回答给了我正确的方向。
将所有子窗体转换为 UserControls 不起作用,因为期望由窗体托管的东西正在寻找顶级窗体而不是子窗体。但汉斯的回答指出,如果在表单上设置 TopLevel = false 和 FormBorderStyle = None,则 Form 基本上会像普通控件一样工作。通过这种方式,所有需要 Form 的东西实际上都会得到一个 Form。
因此,我为 UserControls 编写的所有窗口管理代码都证明是有用的(绘制和处理可拖动边框、标题栏、最大化和关闭按钮),我所要做的就是将 UserControls 转换回 TopLevel = false 的窗体,并且然后在 OnShown 中设置 FormBorderStyle = None。
推荐阅读
- autodesk-forge - Autodesk forge 查看器通过 svf 路径获取 AEC 模型数据
- css - 试图以角度创建一个css类但嵌套.getting错误(在我在主类中编写另一个类之前使用'}'))
- visual-studio-code - “键盘映射”和“快捷方式”有什么区别?
- angularjs - Angular JS和SpringBoot,认证后获取用户
- php - 发送 REST 数据后如何使用 PHP 标头重定向?
- java - 列表的休眠长度验证器
- node.js - Microsoft Bot Framework V4 Appinsights 相关信息?如何使用 Nodejs 将其用于自定义指标和自定义事件?
- delphi - 代码编辑器无法识别俄语字符
- jquery - 如何增加弹出框宽度
- f# - F#如何正确插入模块引用