在失去焦点事件中了解谁获得了焦点

9

在失去焦点事件中,是否有可能知道谁获得了焦点?

由于紧凑框架(Compact Framework)没有ActiveControl,因此我不知道如何确定谁获得了焦点。


你在下面的回答评论中提到想要使用LostFocus事件来显示基于当前焦点控件的消息。为什么不直接使用相关控件的GotFocus事件呢? - djdd87
@GenericTypeTea - 说得好。除了显示消息之外,我还需要对正在离开的控件的值进行一些处理。可以在GotFocus中完成,但这可能有点别扭。 - Vaccano
5个回答

6
这是最终有效的解决方案:
public System.Windows.Forms.Control FindFocusedControl()
{
    return FindFocusedControl(this);
}

public static System.Windows.Forms.Control FindFocusedControl(System.Windows.Forms.Control container)
{
    foreach (System.Windows.Forms.Control childControl in container.Controls)
    {
        if (childControl.Focused)
        {
            return childControl;
        }
    }

    foreach (System.Windows.Forms.Control childControl in container.Controls)
    {
        System.Windows.Forms.Control maybeFocusedControl = FindFocusedControl(childControl);
        if (maybeFocusedControl != null)
        {
            return maybeFocusedControl;
        }
    }

    return null; // Couldn't find any, darn!
}

2
一种选择是使用 GetFocus API 进行互操作。
[DllImport("coredll.dll, EntryPoint="GetFocus")]
public extern static IntPtr GetFocus();

这将为您提供当前具有输入焦点的窗口句柄,然后您可以递归迭代控件树以查找具有该句柄的控件。


1
请记住,在LostFocus事件中调用GetFocus将导致控件失去焦点,因此虽然GetFocus将为您提供当前控件,但您必须有一些事件来知道何时调用它。 - ctacke
@ctacke - 哇,这听起来好复杂啊。所以总结一下,如果我在错误的时间调用GetFocus(比如在LostFocus事件中),它实际上会更改当前焦点,而不仅仅是告诉我哪个控件拥有焦点? - Vaccano

1
这是Vaccano的答案的简短代码,使用Linq。
private static Control FindFocusedControl(Control container)
{
    foreach (Control childControl in container.Controls.Cast<Control>().Where(childControl => childControl.Focused)) return childControl;
    return (from Control childControl in container.Controls select FindFocusedControl(childControl)).FirstOrDefault(maybeFocusedControl => maybeFocusedControl != null);
}

完全相同(在高层次的抽象层面上)。

1

不行。首先是一个控件的LostFocus事件,然后是下一个控件的GotFocus事件。只有在你无法确定用户下一步使用哪个控件时,才不可能实现。
而如果紧凑框架控件具有TabIndex属性,则仅当用户使用Tab键时才能预测。

编辑: 好的,你发布了解决方案,我必须承认它很好:简单的“不行”是错误的。 +1


所以我有点困惑... 这份文档说 GotFocus 在 LostFocus 之前执行。http://msdn.microsoft.com/en-us/library/system.windows.forms.control.gotfocus.aspx 但是我看到的是 LostFocus 先执行(就像你说的)。 - Vaccano
1
这份文档当然是正确的,但它缺少了哪个控件实际上被指定的信息。因此请仔细阅读我所写的内容:一个控件的LostFocus事件在_NEXT_控件的GotFocus事件之前发生。MSDN只说了同一控件的GotFocus事件在LostFocus事件之前发生。你谈到了“看到”,所以我假设你制作了一个小例子,在其中将不同控件的Lost-和Gotfocus事件的发生存储在ListBox中。 - OlimilOops
啊...我明白了。嗯,那很有道理,但是我离解决我的问题还是一点头绪都没有。 - Vaccano
1
也许描述一下您真正想要做什么,也许有其他更好的解决方案? - OlimilOops
在我的失去焦点方法中,我想根据获得焦点的控件显示消息(或不显示)。 - Vaccano
我会实现一个IMessageFilter,然后根据你感兴趣的控件句柄查找低级消息。这是最简单、最不拙劣的方法。 - ctacke

1

使用corell.dll似乎是个不错的主意。

另一种可能的方法是为表单上的所有控件创建GotFocus事件处理程序,然后创建一个类级变量,该变量会随着当前焦点所在控件的名称而更新。


我尝试了这个(请参见此处:https://dev59.com/cU3Sa4cB1Zd3GeqPx8aj),但它没有起作用(因为失去焦点在得到焦点之前,正如Oops所指示的那样)。 - Vaccano

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接