【发布时间】:2008-12-05 21:18:11
【问题描述】:
我需要能够确定ContainsFocus 何时在Control(特别是Windows 窗体)上发生变化。覆盖OnGotFocus 不是答案。当我将表单带到前台时,ContainsFocus 为真,Focused 为假。那么OnGotFocus 是否与ContainsFocus 等效?还是其他方式?
【问题讨论】:
我需要能够确定ContainsFocus 何时在Control(特别是Windows 窗体)上发生变化。覆盖OnGotFocus 不是答案。当我将表单带到前台时,ContainsFocus 为真,Focused 为假。那么OnGotFocus 是否与ContainsFocus 等效?还是其他方式?
【问题讨论】:
注意:如果您有子控件,则会触发子控件的 GotFocus 事件。否则调用表单的 OnGotFocus。
如果我正确理解了这个问题,那么这应该有效:
bool lastNotificationWasGotFocus = false;
protected override void OnControlAdded(ControlEventArgs e)
{
SubscribeEvents(e.Control);
base.OnControlAdded(e);
}
protected override void OnControlRemoved(ControlEventArgs e)
{
UnsubscribeEvents(e.Control);
base.OnControlRemoved(e);
}
private void SubscribeEvents(Control control)
{
control.GotFocus += new EventHandler(control_GotFocus);
control.LostFocus += new EventHandler(control_LostFocus);
control.ControlAdded += new ControlEventHandler(control_ControlAdded);
control.ControlRemoved += new ControlEventHandler(control_ControlRemoved);
foreach (Control innerControl in control.Controls)
{
SubscribeEvents(innerControl);
}
}
private void UnsubscribeEvents(Control control)
{
control.GotFocus -= new EventHandler(control_GotFocus);
control.LostFocus -= new EventHandler(control_LostFocus);
control.ControlAdded -= new ControlEventHandler(control_ControlAdded);
control.ControlRemoved -= new ControlEventHandler(control_ControlRemoved);
foreach (Control innerControl in control.Controls)
{
UnsubscribeEvents(innerControl);
}
}
private void control_ControlAdded(object sender, ControlEventArgs e)
{
SubscribeEvents(e.Control);
}
private void control_ControlRemoved(object sender, ControlEventArgs e)
{
UnsubscribeEvents(e.Control);
}
protected override void OnGotFocus(EventArgs e)
{
CheckContainsFocus();
base.OnGotFocus(e);
}
protected override void OnLostFocus(EventArgs e)
{
CheckLostFocus();
base.OnLostFocus(e);
}
private void control_GotFocus(object sender, EventArgs e)
{
CheckContainsFocus();
}
private void control_LostFocus(object sender, EventArgs e)
{
CheckLostFocus();
}
private void CheckContainsFocus()
{
if (lastNotificationWasGotFocus == false)
{
lastNotificationWasGotFocus = true;
OnContainsFocus();
}
}
private void CheckLostFocus()
{
if (ContainsFocus == false)
{
lastNotificationWasGotFocus = false;
OnLostFocus();
}
}
private void OnContainsFocus()
{
Console.WriteLine("I have the power of focus!");
}
private void OnLostFocus()
{
Console.WriteLine("I lost my power...");
}
【讨论】:
解决此问题的一种方法是使用计时器。这绝对是蛮力,但它可以完成工作:
private Timer m_checkContainsFocusTimer = new Timer();
private bool m_containsFocus = true;
m_checkContainsFocusTimer.Interval = 1000; // every second is good enough
m_checkContainsFocusTimer.Tick += new EventHandler(CheckContainsFocusTimer_Tick);
m_checkContainsFocusTimer.Start();
private void CheckContainsFocusTimer_Tick(object sender, EventArgs e)
{
if (!m_containsFocus && ContainsFocus)
OnAppGotFocus();
m_containsFocus = ContainsFocus;
}
但是有没有更简单的方法?
【讨论】:
应该处理 GotFocus 和 LostFocus 事件。
还有一点需要注意...... SDK 对 ContainsFocus 属性的描述如下:
您可以使用此属性来确定 无论是控制或任何 其中包含的控件具有 输入焦点。要确定是否 控制有焦点,不管 它的任何子控件是否有 焦点,使用 Focused 属性。
编辑:
在处理 GotFocus 事件时,您可能仍需要检查 Focused/ContainsFocus 属性,具体取决于控件层次结构的设置方式。
如果控件或其任何子控件具有焦点,ContainsFocus 将为真。 仅当特定控件本身具有焦点时,焦点才会为真,无论其子控件如何。
【讨论】: