Steal focus as SetForegroundWindow can't do it - winapi

I know this sounds evil but my intention is not this at all.
A user has clicked "delay shot" and a countdown starts, during that time they go focus another application, then after countdown user expects my app to take back focus.
SetForegroundWindow fails when it runs from appliction with PID X while application with PID Y is focused.
This worked to bring my window forward, but it doesn't get focus:
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
It sets the window to be always on top. However focus is not put into my window. And then setting it back to HWND_NOTOPMOST leaves it there, even though its not top most, but it still doesnt have focus. Running SetForegroundWindow won't do the trick after these calls to SetWindowPos Is there anyway to steal focus?
I have tried a combination of:
SwitchToThisWindow
SetWindowPos
ShowWindow
SetForegroundWindow
But can't seem to figure it out.
Another reason I think this has to be possible is because Mac OSX allows it with NSApplication activateIgnoringOtherApps: and Linux's allow it too. I'd like to get this cross platform.
As a last resort I was going to use the HWND_TOPMOST method, then GetWindowRect then SetCursorPos and send single click to my window at pos 0,0, I really don't want to though as there might be something at 0,0 and it shouldn't be auto clicked on.

This always works, no matter what app is in foreground (like Task Manager, etc.):
AllocConsole();
auto hWndConsole = GetConsoleWindow();
SetWindowPos(hWndConsole, 0, 0, 0, 0, 0, SWP_NOZORDER);
FreeConsole();
SetForegroundWindow(hWnd);

As the comment says, SetForegroundWindow is sometimes useless intentionally. Basically, two ways are used to bypass restrictions:
Simulate keyboards / mouses
Get privileges
There is some smarter magic to achieve the goal without directly clicking the window you are going to activate. Since I'm not familiar with GUI, I would suggest inject code directly into current foreground window and hand over the foreground right.
Besides there're some examples on simulating.
http://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo.aspx

Related

MFC dialog form on the top of all applications

Is it possible create MFC form that cold stay on the top of all applications on PC not allowing to do anything else without entering required information.
Win32 doesn't support system-modal dialogs any more, as far as I'm aware. This is a relic from 16 bit Windows versions.
You can try yourself with a MB_SYSTEMMODAL type MessageBox.
Closest thing would be to utilize a screen-sized window to display a dimmed desktop background while your dialog is shown. This simulates the behaviour of the user account control -- except that you still can switch tasks.
You can obtain something similar setting your window on "TopMost". You can do it on property sheet in design mode, or programmatically with this line:
SetWindowPos( pWnd->m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE );
Hope this will fit your needs.

Why is SetWindowPos failing to bring windows to the front of the z-order when I have UIAccess rights? (Windows 7)

I am having trouble with SetWindowPos failing to bring windows of external processes to the top of the z-order reliably. I am able to bring windows to the front like:
NativeMethods.SetWindowPos(hwnd, new IntPtr(-1), Left, Top, Width, Height, 0x10);
NativeMethods.SetWindowPos(hwnd, new IntPtr(-2), Left, Top, Width, Height, 0x10);
It doesn't work 100% of the time though. After some reading, I found a few things.
SetWindowPos documentation states:
To use SetWindowPos to bring a window to the top, the process that owns the window must have SetForegroundWindow permission.
An article on MSDN then states
A process that is started with UIAccess rights has the following abilities:
* Set the foreground window.
AllowSetForeground mentions
The calling process must already be able to set the foreground window
I have signed my .exe and enabled UIAccess so that I can set the foreground window like so in my manifest:
<requestedExecutionLevel level="highestAvailable" uiAccess="true" />
My program starts and I get the UAC prompt asking for permission. I then test for UIAccess, admin rights, and TokenElevationType. The first 2 return true, and the 3rd returns TokenElevationTypeFull. I still run into the same problems though with my new code though.
My code is:
uint processid=0;
NativeMethods.GetWindowThreadProcessId(hwnd, out processid);
NativeMethods.AllowSetForegroundWindow((int)processid);
NativeMethods.SetWindowPos(hwnd, IntPtr.Zero, Left, Top, Width, Height, 0x10);
NativeMethods.RedrawWindow(hwnd, IntPtr.Zero, IntPtr.Zero, NativeMethods.RedrawWindowFlags.Erase | NativeMethods.RedrawWindowFlags.Invalidate | NativeMethods.RedrawWindowFlags.NoChildren);
NativeMethods.RedrawWindow(hwnd, IntPtr.Zero, IntPtr.Zero, NativeMethods.RedrawWindowFlags.Erase | NativeMethods.RedrawWindowFlags.Invalidate | NativeMethods.RedrawWindowFlags.UpdateNow | NativeMethods.RedrawWindowFlags.AllChildren);
What you want to do is contrary to the (complicated) rules Windows has in place to prevent badly-behaved programs from wresting control away from the user. (Control doesn't just mean input focus, but also control of what's visible and what's not.) Although your intentions may be aligned with the user's, what you're asking for is indistinguishable from what disruptive programs often try to do.
There are alternative ways to signal the user that non-foreground windows need attention. Check out FlashWindowEx, for example. You might also consider a tray icon that pops notification balloons. These seem like they'd be appropriate and effective solutions.

Starting a windows-application with focus

I'm writing a small Windows application in Visual C++ without MVC. Its really small, it just contains one textfield, an OK-Button and an Cancel-Button.
The application is started by a background-process when user starts printing. When opening the application doesn't get focus, isn't even visible.
For the user it's importend that the application is directly in focus, so they have as lease clicks as possible to use it.
I tried many many things to get the application in focus:
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SetForegroundWindow(hWnd);
ShowWindow(hWnd, SW_RESTORE);
SetFocus(hWnd);
I even repeated this calls in a timer. All of this doesn't work. Now I found some remarks on MSDN:
The system restricts which processes can set the foreground window. A
process can set the foreground window only if one of the following
conditions is true:
The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The foreground process is being debugged.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
No menus are active.
Anybody knows a workaround for this?
There is no workaround for this. The whole point of this new Windows behavior is to prevent applications from bringing themselves to the foreground on their own and being a nuisance. In your case, I would suggest using a notification icon and showing a balloon message when necessary instead of a window. However, even in this case your notification icon can be hidden by the user and there is no workaround, for the same reason as above.
Now, this is coming from a Java developer and not a Visual C++ developer, but can you maybe set the frame/window/whatever-its-called-in-visual-c to be always on top? In Java, if you have a JFrame, say myJFrame, you can call myJFrame.setAlwaysOnTop(true) and it stays on top of all other windows. This seems to be a simple workaround to your problem, however it may not be desirable for the user if it's blocking something of theirs on screen.
http://www.thescarms.com/vbasic/alttab.aspx seems to do the job
void forceToFront(HWND hWnd) {
HWND foregroundWindow = GetForegroundWindow();
if (foregroundWindow == hWnd) {
// Window is already Foreground-window
return;
}
if (SetForegroundWindow(hWnd)) {
// could set window to foreground without any tricks
return;
}
// attach thread of foreground-window to this window
DWORD foregroundThread = GetWindowThreadProcessId(foregroundWindow, NULL);
DWORD myThread = GetWindowThreadProcessId(hWnd, NULL);
AttachThreadInput(foregroundThread, myThread, true);
SetForegroundWindow(hWnd);
AttachThreadInput(foregroundThread, myThread, false);
}

Pure win32 cross-process child windows

I need to create a transparent overlay window, that goes above another window. The other window is from another vendor. And when the user drags that window mine needs to follow.
WS-CHILD seems like a nice idea but it cannot be combined with WS-EX-LAYERED, which I really need (for transparency). But I still can set a parent without using WS-CHILD.
Parenting does give my winproc notifications (WM-WINDOWPOSCHANGING), but only after dragging is complete, on mouse-up. To give a nice feeling i need to get those notifications (or for example WM-MOVE) continuosly while dragging.
I guess my problem is similar to docking, but the fine docking solution seen fx at CodeProjet uses WS-CHILD. ( http://www.codeproject.com/KB/toolbars/dockwnd.aspx )
I guess I could use polling but that is not what I am looking for. Also I could use ::SetWindowsHook(). But that is my final resort. I am hoping I have missed something trivial and that somebody can point me in a good direction.
Thanx
I know it is not your preferred solution, but I think you need to use a global mouse hook. Pass WH_MOUSE_LL to SetWindowsHookEx() and do nothing in the default case of your low-level mouse proc. But when you get the WM_WINDOWPOSCHANGING notification, start tracking the mouse movements and making appropriate calls to MoveWindow() or whatever.
I use a LayeredWindow for that and set the other window as parent.
This is the code I used for that:
::SetWindowLong(GetHwnd(), GWL_EXSTYLE, GetWindowLong(GetHwnd(), GWL_EXSTYLE) |WS_EX_LAYERED);
::SetLayeredWindowAttributes(GetHwnd(), RGB(255,0,255), 255, LWA_COLORKEY | LWA_ALPHA);
::SetWindowLongPtr(GetHwnd(),GWLP_HWNDPARENT,(long)GetParentHWND());
::SetWindowPos(hndOtherWindow, hndOverlayWinow, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |SWP_NOACTIVATE);
It works for my purposes. There's only one problem left: If my overlaying window loses the focus I want to set the focus, or activate the other window. Do you have an idea?
How about WM_MOVING message? You may try intercepting this message and move your window accordingly.
If you want to know when a window in another process is being moved or sized, you need to install a hook,catch the WM_MOVING and WM_SIZING messages and reflect those messages back to your controller process. Sorry it's not the answer you want! I don't blame you for wanting to avoid cross process hooks, its a bit of a pain...

Can a window be always on top of just one other window?

In Windows, is it possible to set window A such that it is always on top of window B, yet allow other windows to work as normal and appear over the top of both, when active.
In other words, I want a parent-child relationship between two windows. Can this be done without making window A a child of window B, MDI-style? Window B isn't mine (Internet Explorer), and screws my dialog A's graphics up when I try to achieve this with SetParent.
I thought I'd cracked it with this idea from an MSDN forum post, but alas windows A is still always on top of everything, not just window B.
// Place window A on top
SetWindowPos(hWndWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
// Place window B underneath it
SetWindowPos(hWndParent, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
Is it possible?
Wouldn't creating an ownership relationship do the trick?
SetWindowLong(hwndChild, GWL_HWNDPARENT, hwndOwner)
The windows can be in different processes and you can call this from any process. This will ensure that the child window is always above the owner window. This is different than SetParent which actually creates a Parent / Child relationship. Read through this article (its from 1993 but still mostly correct) to see the distinction between ownership and parenting.
When your window's Z-order (or size or position) is changing, it should receive a WM_WINDOWPOSCHANGING message. If you process that message, you have an opportunity to modify the final Z-order (or size or position) to which the window is moved.
To illustrate, in hWndA's window procedure:
case WM_WINDOWPOSCHANGING:
DefWindowProc(hWnd, msg, wParam, lParam);
WINDOWPOS *p = (WINDOWPOS*)lParam;
p->hwndInsertAfter = hWndB;
p->flags &= ~SWP_NOZORDER;
return 0;
should insert hWndA after hWndB in the Z-order any time hWndA's position changes.
Until Vista, one way to do it would have been to use SetWindowsHookEx, and hook the WH_CBT or WH_CALLWNDPROC hook, and then take appropriate action when you detect the Z order changing. However this doesn't work with Vista (as far as I can tell from googling).
The only other solution I can think of is to set up a timer to fire every few seconds, and then when you receive a WM_TIMER, you interrogate the system using GetNextWindow to find out which window is behind yours. If it's not IE, then call SetWindowPos to position your window above IE (I assume you have a HWND for the IE window you care about - remember there can be multiple IE windows).
This will cause problems if people try to bring your window to the front - it will flip back to being just above IE. In this case, in your code you could handle WM_ACTIVATE and try to change the Z-order of IE's window so it's below your window (call SetWindowPos to move IE's window so it's above the window that is currently below your window). This solution may be fraught with problems as Windows may try to prevent you messing with the windows of another process, for security reasons. On the other hand, the MSDN docs for SetWindowPos don't explicitly mention that you can't manipulate the windows of another process. There may be obscure limitations though.
Even with this timer hack, you're going to effectively have a busy-waiting loop in your app (with the frequent WM_TIMER messages) and this is generally a bad thing to do, especially for battery life of laptops etc. (because you prevent the CPU from entering a sleep state, and so on).
I'd say there's no good way of doing this, and anything you're likely to get working will be brittle and cause problems. I strongly recommend not trying to do it. Is it possible to make your program into some kind of plug-in or toolbar for IE instead?
NB Be particularly aware that SetWindowsHookEx imposes a performance penalty at a system-wide level if you go down this route.
Maurice's answer is the best out of what's here but is missing an important step. When you call show on your window that you want as the overlay, you need to call the show method that has the parameter. You'll need to define a class that implements the IWin32Window interface and just make a new instance of that. The only thing that interface cares about is the Handle so just set that to the handle of the IE window and it should work pretty well
If the parent-child relationship is made by yourself with the SetWindowPos() function, your desire can be implemented.
Can you access the Z-order of the windows?
I cannot recall the default z-order of windows, but I think it is 1. You might be able to set IE to a -1 and your app to 0.
Try this:
// Place window A on top of window B
SetWindowPos(hWndA, hWndB, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
The second window handle parameter specifies the next window down in the Z order.
Note this doesn't actually change the window parent-child relationships - but you can simulate it.

Resources