问题
My situation: A browser displays a webpage served by a locally running webserver. When the user clicks a button on the page, I would like to jump to another, possibly already running, application.
Working on Windows, I thought about processing the button-click in my locally running webserver and just look for the respective HWND
to call SetForegroundWindow on it.
However, as it stands, the locally running webserver is not sufficiently privileged to SetForegroundWindow. Those restrictions make sense, but I think a click is a distinctive enough event to justify a jump to another application.
I read about certain techniques to circumvent this restriction and force a window into the foreground:
- AttachThreadInput: Seems to be a bad idea.
- Sending a hotkey: Seems to be used by the Chromium project, but involves creating an own message loop. Its authors state that it is probably a windows bug (even if the old new thing mentions it without explicit words of caution). Moreover, it does not work reliably if another application already called registered this hotkey.
- Starting a stand-alone wrapper (thereby hopefully giving it sufficient privileges to
SetForegroundWindow
) whose sole task is to switch to the other application: Seems heavyweight, but possibly easier than other solutions.
None of the above looks particularly appealing to me. Do I have any better options?
回答1:
First call SetForegroundWindow
and with GetForegroundWindow
check if you got foreground status.
If not, it could be feasible to check if mouse buttons are down or Alt, Ctrl, Shift or Windows keys are pressed. It this case you shouldn't interrupt user operation (for example drag&drop).
When you decide to continue, aside from hotkey method you have two more workable solutions:
1.
SwitchToThisWindow
, yes "This function is not intended for general use. It may be altered or unavailable in subsequent versions of Windows" etc. but it works.
SwitchToThisWindow( hwnd, TRUE );
Sleep( 100 );
SetForegroundWindow( hwnd );
Doesn't work without Sleep
. Use TRUE, because FALSE buries current foreground window.
2. Minimize/Restore. Animation effect is somewhat annoying. You can switch off animations when DWM is active
BOOL flag = TRUE;
DwmSetWindowAttribute( hwnd, DWMWA_TRANSITIONS_FORCEDISABLED, &flag, sizeof(flag) );
ShowWindow( hwnd, SW_MINIMIZE );
ShowWindow( hwnd, SW_RESTORE );
flag = FALSE;
DwmSetWindowAttribute( hwnd, DWMWA_TRANSITIONS_FORCEDISABLED, &flag, sizeof(flag) );
SetForegroundWindow( hwnd );
来源:https://stackoverflow.com/questions/57004387/bringing-a-window-to-foreground-from-a-background-process