有谁知道在停用表单时确定哪个窗口将获得焦点的方法?
问问题
1902 次
3 回答
7
我找到了答案。不要订阅激活和停用事件,而是在 WndProc 中处理WM_ACTIVATE消息(用于激活和停用)。由于它报告正在激活的窗口句柄,我可以将该句柄与我的表单句柄进行比较,并确定焦点是否正在更改为其中任何一个。
const int WM_ACTIVATE = 0x0006;
const int WA_INACTIVE = 0;
const int WA_ACTIVE = 1;
const int WA_CLICKACTIVE = 2;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_ACTIVATE)
{
// When m.WParam is WA_INACTIVE, the window is being deactivated and
// m.LParam is the handle of the window that will be activated.
// When m.WParam is WA_ACTIVE or WA_CLICKACTIVE, the window is being
// activated and m.LParam is the handle of the window that has been
// deactivated.
}
base.WndProc(ref m);
}
编辑:此方法可以在它适用的窗口之外使用(例如在弹出窗口之外)。
您可以使用 NativeWindow 根据其句柄附加到任何窗口并查看其消息循环。请参见下面的代码示例:
public class Popup : Form
{
const int WM_ACTIVATE = 0x0006;
const int WA_INACTIVE = 0;
private ParentWindowIntercept parentWindowIntercept;
public Popup(IntPtr hWndParent)
{
this.parentWindowIntercept = new ParentWindowIntercept(hWndParent);
}
private class ParentWindowIntercept : NativeWindow
{
public ParentWindowIntercept(IntPtr hWnd)
{
this.AssignHandle(hWnd);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_ACTIVATE)
{
if ((int)m.WParam == WA_INACTIVE)
{
IntPtr windowFocusGoingTo = m.LParam;
// Compare handles here
}
}
base.WndProc(ref m);
}
}
}
于 2009-05-01T23:36:27.850 回答
0
您应该能够使用Form.ActiveForm
静态属性确定活动表单。
于 2009-05-01T21:25:56.853 回答
0
在实现自动完成弹出窗口(类似于 VS 中的 Intellisense 窗口)时,我遇到了同样的问题。
该WndProc
方法的问题在于,必须将代码添加到发生弹出窗口的任何表单中。
另一种方法是使用计时器并在短暂的间隔后检查 Form.ActiveControl。这样,代码可以更好地封装在编辑器控件或弹出表单中。
Form _txPopup;
// Subscribe whenever convenient
public void IntializeControlWithPopup(Form _hostForm)
{
_hostForm.Deactivate + OnHostFormDeactivate;
}
Timer _deactivateTimer;
Form _hostForm;
void OnHostFormDeactivate(object sender, EventArgs e)
{
if (_deactivateTimer == null)
{
_mainForm = sender as Form;
_deactivateTimer = new Timer();
_deactivateTimer.Interval = 10;
_deactivateTimer.Tick += DeactivateTimerTick;
}
_deactivateTimer.Start();
}
void DeactivateTimerTick(object sender, EventArgs e)
{
_deactivateTimer.Stop();
Form activeForm = Form.ActiveForm;
if (_txPopup != null &&
activeForm != _txPopup &&
activeForm != _mainForm)
{
_txPopup.Hide();
}
}
于 2009-11-01T14:13:13.607 回答