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

本文关键字:选择 窗口 返回 通知 区域 图标 单击 | 更新日期: 2023-09-27 18:09:28

我已经构建了一个应用程序,它有一个通知区域图标,当点击它时,会弹出一个为单次点击设计的表单,之后用户可以返回到他们之前正在做的事情。

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

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

我已经设法找出了原因。我使用了以下代码:

[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是让指针指向任务栏。

你应该在应用程序第一次接收焦点时就确定它,而不是在事实之后才试图弄清楚它。换句话说,你越早明白越好。

明显的解决方案是处理WM_SETFOCUSWM_ACTIVATE消息,它们将句柄作为lParam传递给先前活动的窗口。不幸的是,这只适用于同一线程中的窗口;否则,lParam将为NULL

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

保持跟踪这个窗口句柄,并简单地恢复焦点到它当你完成。