我已经构建了一个具有通知区域图标的应用程序,单击该图标时会显示一个专为单击而设计的表单,之后用户可以返回到他们之前所做的事情。
目前,我正在使用this.Hide()
删除表单(当表单中的所需事件发生时,或者当表单为 时Deactivated
),但是当我这样做时,Windows 将用户焦点设置到任务栏。在单击通知区域图标之前,如何让它将用户焦点返回到他们所在的窗口?
我已经构建了一个具有通知区域图标的应用程序,单击该图标时会显示一个专为单击而设计的表单,之后用户可以返回到他们之前所做的事情。
目前,我正在使用this.Hide()
删除表单(当表单中的所需事件发生时,或者当表单为 时Deactivated
),但是当我这样做时,Windows 将用户焦点设置到任务栏。在单击通知区域图标之前,如何让它将用户焦点返回到他们所在的窗口?
与其在事后试图弄清楚这一点,不如在应用第一次获得焦点时一开始就确定它。换句话说,越早弄清楚越好。
显而易见的解决方案是处理WM_SETFOCUS
或WM_ACTIVATE
消息,将句柄作为lParam
. 不幸的是,这只适用于同一线程中的窗口;否则,lParam
将是NULL
。
所以你需要使用WM_ACTIVATEAPP
,它将拥有被停用窗口的线程的标识符作为lParam
. 获得线程标识符后,使用该GetGUIThreadInfo
函数确定该线程中的活动窗口。无论哪个进程拥有窗口,这都有效,因此它不受上面讨论的WM_SETFOCUS
和的限制WM_ACTIVATE
。
跟踪此窗口句柄,并在完成后简单地将焦点恢复到它。
我设法找出方法。我使用了以下代码:
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int SetForegroundWindow(IntPtr hwnd);
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern IntPtr GetWindow(IntPtr hwnd, int wFlag);
private void switchToLast() {
IntPtr thisWindow = GetForegroundWindow();
IntPtr lastWindow = GetWindow(thisWindow, 3);
SetForegroundWindow(lastWindow);
this.Hide();
}
我发现了很多关于这个问题的参考资料,这就是我到目前为止所拥有的。这个和我发现的其他示例之间的主要区别是行GetWindow(thisWindow, 3)
,在其他示例中第二个是 2,我已将其更改为 3。我相信这是因为将其设置为 2 是获取指向 TaskBar 的指针。