代码之家  ›  专栏  ›  技术社区  ›  Phil Wright

在WinForms中,如何跟踪任何子控件何时获得或失去焦点?

  •  1
  • Phil Wright  · 技术社区  · 15 年前

    我有一个Windows窗体自定义控件,它像一个面板,可以包含任意数量的子控件。子控件的数量和类型在运行时确定,因此我需要以通用的方式工作,而不知道可能存在或可能不存在的确切子控件。

    我想根据面板是否包含焦点来更改面板的背景色。因此,如果面板的子级(或面板子级的子级等)获得了我想知道的焦点,那么我可以更新自定义面板的背景色。当焦点转移到不在子层次结构中的某个东西上时,我还需要知道,这样我就可以还原到原始的背景色。

    control.containsFocus非常适合告诉我面板是否在子层次结构中包含焦点,但我需要知道何时发生了更改。目前,我只能想出以下糟糕的机制。

    我钩住每个孩子和每个孩子的每个孩子的gotfocus/lostfocus等。我还必须钩住controladded/controlremoved,以确保我与可能改变的孩子层次结构保持同步。正如您所看到的,这可能最终会导致大量的事件挂钩,我怀疑一定有一种更简单的方法。有什么想法吗?

    2 回复  |  直到 12 年前
        1
  •  1
  •   Frans Bouma    15 年前

    恐怕这是唯一的选择。WinForms有时在其API中有一些恼人的漏洞。我没有检查,但如果containsFocus只是容器控件的控件树的递归遍历,以查看是否有任何控件具有焦点,我不会感到惊讶。

    拥有大量的事件处理程序并不是什么大问题,而是引发了许多改变UI元素的事件。您可以通过对可添加的控件进行子类化来解决这个问题(但我不确定是否必须允许所有控件或只允许一个子集),并将面板传递给添加的控件,以便控件在获得/失去焦点时调用面板。但这也需要做大量的工作,而且将代码放在面板中类似观察者的模式更容易实现。

        2
  •  7
  •   uglycoyote    12 年前

    好像在用 进入 离开 事件就是答案。gotfocus将只发送到获得焦点的特定控件,而enter事件也将发送到获取gotfocus事件的控件的父控件(和祖先控件)。

    http://msdn.microsoft.com/en-us/library/system.windows.forms.control.leave.aspx

    “进入和离开事件是分层的,将层叠起来, 沿着父链向下,直到达到适当的控制。为了 例如,假设您有一个带有两个GroupBox控件的窗体,并且每个控件 GroupBox控件有一个文本框控件。当插入符号从 一个文本框到另一个,为文本框引发Leave事件 和GroupBox,并且为其他GroupBox和 “文本框”。