在单击通知区域图标之前返回先前选择的窗口

时间:2013-04-16 22:14:04

标签: c# winforms notifyicon notification-area

我已经构建了一个具有通知区域图标的应用程序,当点击该图标时会显示一个专门为单击而设计的表单,之后用户可以返回到他们在那里做的事情。

目前,我使用this.Hide()删除表单(在表单中发生所需事件时,或表单为Deactivated时),但是当我这样做时,Windows会设置用户焦点到任务栏。在点击通知区域图标之前,如何让用户将焦点返回到他们所在的窗口?

2 个答案:

答案 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_SETFOCUSWM_ACTIVATE消息,这些消息将句柄作为lParam传递给先前活动的窗口。不幸的是,这仅适用于同一线程中的窗口;否则,lParam将为NULL

所以你需要使用WM_ACTIVATEAPP,它将拥有被停用窗口的线程的标识符作为lParam传递。获得线程标识符后,使用GetGUIThreadInfo函数确定该线程中的活动窗口。无论哪个进程拥有该窗口,这都有效,因此它不受上文讨论的WM_SETFOCUSWM_ACTIVATE限制。

跟踪此窗口句柄,并在完成后简单地将焦点恢复到该窗口句柄。