猿问
下载APP

在WinForms应用程序中找到集中控件的首选方法是什么?

在WinForms应用程序中找到集中控件的首选方法是什么?

找到当前在WinForms中接收用户(键盘)输入的控件的首选/最简单方法是什么?

到目前为止,我已经提出以下建议:

public static Control FindFocusedControl(Control control){
    var container = control as ContainerControl;
    return (null != container        ? FindFocusedControl(container.ActiveControl)
        : control);}

从表单中,这可以简单地称为(在.NET 3.5+中甚至可以将其定义为表单上的扩展方法) -

var focused = FindFocusedControl(this);

这个合适吗?

是否有我应该使用的内置方法?

请注意,使用层次结构时,单次调用ActiveControl是不够的。想像:

Form
    TableLayoutPanel
        FlowLayoutPanel
            TextBox (focused)

(formInstance).ActiveControl将返回对TableLayoutPanel的引用,而不是TextBox(因为ActiveControl似乎只是在控制树中返回直接活动的子节点,而我正在寻找叶子控件)。


Cats萌萌
浏览 51回答 3
3回答

慕姐4208626

如果您已经对Windows API进行了其他调用,那么使用Peters解决方案没有任何害处。但是我理解你对它的担忧,并且倾向于使用与你类似的解决方案,只使用Framework功能。毕竟,性能差异(如果有的话)不应该很重要。我会采取非递归的方法:public static Control FindFocusedControl(Control control){     var container = control as IContainerControl;     while (container != null)     {         control = container.ActiveControl;         container = control as IContainerControl;     }     return control;}

繁花如伊

在搜索互联网之后,我在George Shepherd的Windows窗体常见问题解答中找到了以下内容.Net框架库不提供用于查询焦点控件的API。您必须调用Windows API才能执行此操作:[C#]public class MyForm : Form{           [DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.Winapi)]           internal static extern IntPtr GetFocus();           private Control GetFocusedControl()           {                Control focusedControl = null;                // To get hold of the focused control:                IntPtr focusedHandle = GetFocus();                if(focusedHandle != IntPtr.Zero)                     // Note that if the focused Control is not a .Net control, then this will return null.                     focusedControl = Control.FromHandle(focusedHandle);                return focusedControl;           }}

慕前端131612

Form或Container上的ActiveControl 将返回该实体的活动控件,无论它嵌套在其他容器中的深度。在您的示例中,如果TextBox具有Focus:则:对于Form,TableLayoutPanel和FlowLayoutPanel:所有这些的ActiveControl属性将是TextBox!一些(但不是全部)“真正的”ContainerControl类型......比如Form和UserControl ......暴露关键事件(在Form的情况下:仅当Form.KeyPreview == true才能使用它们)。其他控件,根据设计,包含其他控件,如TableLayOutPanel,GroupBox,Panel,FlowLayoutPanel等,不是类型ContainerControl,它们不公开KeyEvents。任何将TextBox,FlowLayoutPanel,TableLayoutPanel等对象实例直接转换为ContainerControl的尝试都不会编译:它们不是类型ContainerControl。接受的答案中的代码,以及纠正第一个答案的拼写错误的下一个答案,将编译/接受上述实例作为参数,因为您正在“向下转换”它们以键入'通过使参数类型控制'控制但是在每种情况下,对ControlContainer的强制转换将返回null,并且将返回传入的实例(下载):基本上是无操作。并且,是的,如果你传递一个“真正的”ControlContainer,就像一个Form实例,它在ActiveControl的父继承路径中,修改后的答案代码将起作用,但你仍然只是浪费时间重复'ActiveControl的功能。那么什么是“真正的”ContainerControls:检查它们:ContainerControl的MS文档只有彼得的答案真的回答了明确的问题,但是这个答案带有使用互操作的代价,而'ActiveControl会给你你需要的东西。另请注意,每个Control(容器或非容器)都有一个永远不会为null的Controls Collection,而且很多(我从未尝试过所有这些:我为什么会这样?)基本的WinForms控件让你做到“疯狂” “喜欢将控件添加到像Button这样的'简单'控件的ControlCollection而没有错误。现在,如果您的问题的真正意图是询问您如何找到最外层的ContainerControl ... 那不在Form本身上......一个常规的非容器控件嵌套了一些任意级别的深层...你可以使用一些答案中的想法:但代码可以大大简化。常规控件,ContainerControls,UserControls等(但不是Form!)都有一个'容器属性,你可以访问以获取他们的直接容器,但确保你的inhertance路径中的'最终容器不是一个Form需要一些代码“继续”继承树,这是在这里演示的。您可能还希望查看'Control的'HasChildren属性,它通常用于处理WinForms中的Focus,ActiveControl和Select问题。回顾Select和Focus之间的区别在这里很有价值,并且SO有一些很好的资源。希望这可以帮助。
打开App,查看更多内容
随时随地看视频慕课网APP
我要回答