我已经构建了一个具有通知区域图标的应用程序,当点击该图标时会显示一个专门为单击而设计的表单,之后用户可以返回到他们在那里做的事情。
目前,我使用this.Hide()
删除表单(在表单中发生所需事件时,或表单为Deactivated
时),但是当我这样做时,Windows会设置用户焦点到任务栏。在点击通知区域图标之前,如何让用户将焦点返回到他们所在的窗口?
答案 0 :(得分:0)
我已经设法找出方法。我使用了以下代码:
[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才能获得指针到任务栏。
答案 1 :(得分:0)
在您的应用首次获得焦点后,您应该在开始时确定它,而不是在事后确定这一点。换句话说,越早弄清楚就越好。
显而易见的解决方案是处理WM_SETFOCUS
或WM_ACTIVATE
消息,这些消息将句柄作为lParam
传递给先前活动的窗口。不幸的是,这仅适用于同一线程中的窗口;否则,lParam
将为NULL
。
所以你需要使用WM_ACTIVATEAPP
,它将拥有被停用窗口的线程的标识符作为lParam
传递。获得线程标识符后,使用GetGUIThreadInfo
函数确定该线程中的活动窗口。无论哪个进程拥有该窗口,这都有效,因此它不受上文讨论的WM_SETFOCUS
和WM_ACTIVATE
限制。
跟踪此窗口句柄,并在完成后简单地将焦点恢复到该窗口句柄。