在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似乎只返回控件树中的直接活动子级,而我正在寻找叶控件)。
发布于 2009-01-13 16:13:58
如果您已经有了对Windows API的其他调用,那么使用Peters解决方案也没什么坏处。但我理解您对此的担忧,并倾向于采用与您的解决方案类似的解决方案,只使用框架功能。毕竟,性能差异(如果有)应该不是很大。
我会采用一种非递归的方法:
public static Control FindFocusedControl(Control control)
{
var container = control as IContainerControl;
while (container != null)
{
control = container.ActiveControl;
container = control as IContainerControl;
}
return control;
}
发布于 2009-01-13 06:56:05
如果您递归地跟踪ActiveControl,它不会将您带到具有焦点的叶控件?
发布于 2019-05-15 22:20:10
ActiveControl并不总是有效的,就像SplitContainer一样,ActiveControl.Focused是false。
因此,对于一个更愚蠢的证明方法,可以做这样的事情:
private IEnumerable<Control> _get_all_controls(Control c)
{
return c.Controls.Cast<Control>().SelectMany(item =>
_get_all_controls(item)).Concat(c.Controls.Cast<Control>()).Where(control =>
control.Name != string.Empty);
}
var _controls = _get_all_controls(this);
foreach (Control control in _controls)
if (control.Focused)
{
Console.WriteLine(control.Name);
break;
}
https://stackoverflow.com/questions/435433
复制相似问题