问题
I have built an application that has a Notification Area Icon, which when clicked brings up a form that is designed for a single click, after which the user can then return to what they where doing before hand.
Currently, I am using this.Hide()
to remove the form (either when the desired event in the form occurs, or when the form is Deactivated
), but when I do, Windows sets the users focus to the Task Bar. How can I get it to return the Users focus to the Window they where on before clicking on the Notification Area Icon?
回答1:
I have managed to find out how. I used the following code:
[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();
}
I found numerous references to the problem, and this is what I have so far. The main difference between this and other examples I have found is the line GetWindow(thisWindow, 3)
, where the second was 2 in other examples, I have changed this to 3. I believe this is because having it set to 2 was getting the Pointer to the TaskBar.
回答2:
Rather than trying to figure this out after the fact, you should determine it at the outset when your app is first receiving the focus. In other words, the sooner you figure it out the better.
The obvious solution would be to handle either the WM_SETFOCUS
or WM_ACTIVATE
messages, which pass the handle to the previously-active window as the lParam
. Unfortunately, this works only for windows in the same thread; otherwise, the lParam
will be NULL
.
So you need to use WM_ACTIVATEAPP, which passes the identifier of the thread that owns the window being deactivated as the lParam
. Once you have the thread identifier, use the GetGUIThreadInfo function to determine the active window in that thread. This works regardless of which process owns the window, so it is not subject to the limitations discussed above for WM_SETFOCUS
and WM_ACTIVATE
.
Keep track of this window handle, and simply restore focus to it when you are finished.
来源:https://stackoverflow.com/questions/16048088/returning-to-window-previously-selected-before-clicking-notification-area-icon