C++ winAPI basics - switching through windows - c++

Not very sure how to explain it in a clear way. Basicaly, the thing is that I'm looking for a method to change a current active window ( Self-produced def., hope it'll be understandable enough ) - window, where the text is directly typed right now. Whooh.
What have I allready discovered is msdn help and SetFocus() or SetActiveWindow(), but it doesn't solve my problem ( or, what is also possible, I'm just using it in a wrong way ).
Simply:
HWND Dest = GetFocus();
... //Some moving around on the 'alt-tab level' :-|
SetFocus(Dest);
Doesn't set the Dest window active again.
Please, excuse for the newbie questions, hope it won't take much time from you. Thanx!

SetFocus() does not bring a window to the top. It just sets the keyboard focus.
SetActiveWindow() on the other hand brings the specific window on top, but only if the application that calls it is also the application that owns it. ( according to the documentation).
When you say you did try SetActiveWindow() what do you mean? How did it fail? What results did it produce?
Another function you can try is SetForegroundWindow() in case you want to activate a window belonging to another application but this has its problems as you see from below (directly from the documentation):
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.

Try using the SetForegroundWindow function.
Do however note that there are limitations on this, which are explained on the MSDN page remarks sections and I've copied here.
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.
An application cannot force a window to the foreground while the user
is working with another window. Instead, Windows flashes the taskbar
button of the window to notify the user.
What that means is that if you don't own the current foreground process (which is probably the case when the user tabs around) then you can't set a new foreground window.
There are several hacks around (google SetForegroundWindow and you will find them) but they are hacks and not a good idea - let the user decide what is in the foreground! (also as Raymond Chen explains on his blog here the hacks can often cause a program to hang)

Related

What's the correct way to bring a window to the front

I've been trying multiple ways of bringing a window into focus and on top of other windows.
I've tried SetForegroundWindow(), BringWindowToTop(), SetActiveWindow(). None of these work consistently.
How can I simply make it so that a window that I want to be in focus, becomes on top of all other windows and is focused? Why is this so difficult?
SetForegroundWindow() is the correct way to change the foreground window, but the thread that calls SetForegroundWindow() has to meet certain criteria for it to "work". If it does not meet the criteria, the window's taskbar button is flashed instead. This is by design. This is to protect the user from applications stealing focus and you should respect that.
See also:
Foreground activation permission is like love: You can’t steal it, it has to be given to you
What if two programs did this?
Your process needs to satisfy a few conditions for it to be able to set the foreground window.
This is to prevent applications from stealing focus - which is a very bad user experience.
Imagine you're writing an email, and halfway through it your application decides now would be a good time to push a window into foreground. As you're typing suddenly the focused window would instantly change and your keypresses would now be sent to your program instead of the mail program. Not only could this cause all sorts of havoc (the keys you pressed are now sent to your program, so hotkeys might get triggered, dialogs dismissed, etc...) - but it would also be a really frustrating experience for the user (especially for less technically-inclined people).
That is the reason why SetForegroundWindow() & similar functions sometimes won't push your window to the foreground, but still report success. Your window will still flash in the task bar though, so users know that something happened in your application.
SetForegroundWindow
The exact list of conditions that need to be met for SetForegroundWindow() to work are detailed in the documentation:
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.
An application cannot force a window to the foreground while the user is working with another window ¹. Instead, Windows flashes the taskbar button of the window to notify the user.
1 this is what prevents the mail program example detailed above from happening.
A process that fulfills these criteria can also "share" its permission to set the foreground window with another process by calling AllowSetForegroundWindow()
SetActiveWindow
SetActiveWindow() only works if the targeted window is attached to your message queue and one of your application windows is currently the foreground window.
Activates a window. The window must be attached to the calling thread's message queue.
The window will be brought into the foreground (top of Z-Order) if its application is in the foreground when the system activates the window.
BringWindowToTop
BringWindowToTop() is a convenience function for SetWindowPos(), which again has the same restrictions:
If an application is not in the foreground, and should be in the foreground, it must call the SetForegroundWindow function.
To use SetWindowPos to bring a window to the top, the process that owns the window must have SetForegroundWindow permission.
Using UI Automation
Since you mentioned that you need this functionality for an accessibility tool, here's how you could accomplish this using UI Automation:
This example uses bare-bones COM for simplicity, but if you want you can of course use e.g. wil for a more C++-like API.
#include <uiautomation.h>
bool MoveWindowToForeground(IUIAutomation* pAutomation, HWND hWnd) {
// retrieve an ui automation handle for a given window
IUIAutomationElement* element = nullptr;
HRESULT result = pAutomation->ElementFromHandle(hWnd, &element);
if (FAILED(result))
return false;
// move the window into the foreground
result = element->SetFocus();
// cleanup
element->Release();
return SUCCEEDED(result);
}
int main()
{
// initialize COM, only needs to be done once per thread
CoInitialize(nullptr);
// create the UI automation object
IUIAutomation* pAutomation = nullptr;
HRESULT result = CoCreateInstance(CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, IID_IUIAutomation, reinterpret_cast<LPVOID*>(&pAutomation));
if (FAILED(result))
return 1;
// move the given window into the foreground
HWND hWnd = FindWindowW(nullptr, L"Calculator");
MoveWindowToForeground(pAutomation, hWnd);
// cleanup
pAutomation->Release();
CoUninitialize();
return 0;
}

Disable window from calling SetForegroundWindow

I have a serious problem on my work machine with a third party software window stealing keyboard focus, using a winapi monitor tool i detect that whenever the windows steal focus it first call SetForegroundWindow.
While searching about, i have found the winapi LockSetForegroundWindow, wow i thought i had solved the problem, however, LockSetForegroundWindow blocks me from activating any other window.
I also found that would be possible to 'block' the window from calling SetForegroundWindow using a hook, but i have no knowledge about hooking, would like to ask if there's something else i could try.
Usually calling SetForegroundWindow() isn't bad. Since Windows XP, there is a lock that no program do this without being allowed to do this. Read the docs: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setforegroundwindow
This are the exceptions:
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 process is being debugged.
The foreground process is not a Modern Application or the Start Screen.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
No menus are active.
But when the third party tools uses AttachThreadInput(), it bypasses all these checks.
Just delete this "bad" software. Contact the developers.

Invalid content when nCurses app comes from background

I have observed odd behavior with my nCurses app when putting it to background/foreground. After a couple of times my window shows invalid content. I suspect that when sending SIGSTOP/SIGCONT signals to my app I need to be handle those and refresh window, but I can't find any note about it. Does nCurses has some way of refreshing window when coming back from background? Or the reason can be different?
ncurses does have a handler for SIGTSTP, which it sets up in initscr — if it is in the default state:
SIGTSTP
This handles the stop signal, used in job control. When resuming
the process, this implementation discards pending input with
flushinput (see curs_util(3x)), and repaints the screen assuming
that it has been completely altered. It also updates the saved
terminal modes with def_shell_mode (see curs_kernel(3x))

How to move the cursor to the last opened window (possibly popup) in c++

I need to move the mouse to the last opened window. This last window will be a popup created by whatever website.
I guess all I need is to get the position of the last opened window and use SetMousePos, right?
I'm not really familiar with the windows API and any help is welcome - Thanks!
Edit:
To answer the questions, we are writing a program that gets malware data. Unfortunately some malware only start working after the mouse moves to a popup they opened. Its a research-based application
I haven't tested this but I believe you could try the following:
Enumerate running processes and order by PID.
The highest number PID should be the "newest" process.
For the newest process enumerate its windows (use GetWindowThreadProcessId)
At this point I guess you'd have to pick which window you think is the "main" window, for example if the malware opens two windows I don't know how you're going to choose which one to give focus to?
Of your picked HWND get its position on the desktop.
Use SetMousePos to move the mouse to the position of the window.
I haven't included all the API's you'll need for these tasks as its generally quite easy to find on here :)
One way to track recently opened windows is to use SetWinEventHook to listen to the EVENT_OBJECT_CREATE and EVENT_OBJECT_SHOW events. In the callback, filter:
just events with a non-null HWND where idObject==OBJID_WINDOW to get just window creation events (vs other creation events such as for items within a listbox)
for top-level only windows, also filter by checking GetAncestor(hwnd, GA_PARENT) is GetDesktopWindow()
And check that the window is indeed currently visible (WS_VISIBLE style is set in GetWindowLong(GWL_STYLE)).
Also filter by GetWindowThreadProcessId() and via the thread/process you pass into SetWinEventHook if you only care about HWNDs from a specific app.
The reason for checking both of these events is that some windows are created hidden and then shown, others are created fully visible, while others are created once, then shown/hidden many times over their lifetime.
You can then cache this 'last known created hwnd' in a global and check it as needed, using GetWindowRect() to get its location, and SetCursorPos() to move the mouse to that location.
--
If the most recent popup is an active window which takes focus - as is the case with dialogs, but not usually the case with 'pop-under' windows - you can use GetGUIThreadInfo(NULL, ...) to determine the currently active HWND, which might be the one you are looking for, returned in the GUITHREADINFO.hwndActive member of the struct you pass it.

Qt Need to bring Qt application to foreground called from win32 application

I have a simple win32 application that uses the createProcess method to call Qt application.
The problem is that I like to bring the Qt application to the foreground.
Who is responsible for this? The parent win32 app or the Qt application?
The application that currently has the foreground focus is the only one that is allowed to change the foreground focus. You need to use the SetForegroundWindow function to exercise this right.
The "Remarks" section in the documentation contains an applicable list of restrictions:
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.
An application cannot force a window to the foreground while the user is working with another window. Instead, Windows flashes the taskbar button of the window to notify the user.
The real question is why you need to do this at all. Changing the foreground application is very likely to get you into trouble, either with all of the restrictions that Windows places on it, or with your users. It's a very user-hostile action, which is one of the reasons why Windows has tightened up the restrictions on it in recent years.
Get the window handle of the Qt application and call SetForegroundWindow
http://msdn.microsoft.com/en-us/library/ms633539.aspx
You probably want to do it from the parent process. The cleanest/most dependable way to use SetForegroundWindow is to call it from the process that's currently in the foreground.