Various issues using SetParent to embed window into external process [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Embedding HWND into external process using SetParent
I'm trying to embed a window from my process into the window of an external process using the SetParent function and have encountered a few problems that I'm hoping someone can help me out with. First off, here is an outline of what I am currently doing to embed my window into the application:
WND myWindow; //Handle to my application window
HWND externalWindow; //Handle to external application window
SetParent(myWindow,externalWindow);
//Remove WS_POPUP style and add WS_CHILD style
DWORD style = GetWindowLong(myWindow,GWL_STYLE);
style = style & ~(WS_POPUP);
style = style | WS_CHILD;
SetWindowLong(myWindow,GWL_STYLE,style);
This code works and my window appears in the other application, but introduces the following issues:
When my window gains input focus, the main application window of the external process loses focus (i.e. title bar changes color).
Keyboard shortcut commands of the main application do not work while my window has focus.
Does anybody know workarounds for these issues? I would like my window to be treated as just another child window of the main application.
Thanks.

When my window gains input focus, the main application window of the external process loses focus (i.e. title bar changes color).
You need to use AttachThreadInput to attach your process's thread to the input queue of the host process. In addition to synchronizing message processing across all attached threads, this causes them to share focus, asynchronous key state, activation, and other input-related properties.
Keyboard shortcut commands of the main application do not work while my window has focus.
When your window has keyboard focus, the thread that owns your window receives all keyboard messages from the system. If you need the main window's UI thread to handle accelerators, you must somehow route keyboard input to that thread for preprocessing. How you do this depends largely on the UI technologies you are using for your applications and how you need accelerators to be processed.
Building a user interface that spans multiple threads in different processes is difficult and there are many pitfalls.

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;
}

Can't focus from main window after closing dialog from other thread

I create a new CWindThread in CWinApp::InitInstance(). In that thread, I create a dialog (for displaying a progress bar in that dialog).
After finishing InitInstance(), I close the dialog by calling DestroyWindow() from the dialog, but the application is loosing focus from main window.
I used AfxGetMainWnd()->SetActiveWindow(); to set focus for main window but it is not working.
How can I return the focus to the main window after closing the dialog?
There is no real good way to do that. The focus is set per thread. So there is no "focus" over all windows.
The only chance you have is to set the new foreground window, that belongs to the other thread with SetForegorundWindow. From within the same application this should work without restrictions.
If it doesn't work you need to "synch" both message queues. This is done by AttachThreadInput. If both messages queue are already attached, than there is no problem with settings the focus directly. But the behaviour of the application will change... Please read the docs, of the functions I linked too.
When a modal popup window is displayed, the reason a user cannot interact with the owner window is that it is disabled. When the modal window is destroyed, care must be taken to re-enable the owner window BEFORE destroying the popup as windows cannot activate a disabled window. This is the usual cause of popup windows re-activating the wrong window.

Create a child window inside another application

I'm trying to write a bot in C++ for a PC game using the windows API. I've managed to find the process HANDLE, its ID and finally its HWNDwith EnumWindows. I've managed also to send messages to its window (using SendMessage) in order to simulate keystrokes. Since the game runs full screen I'd like to create a child window inside it with custom controls to switch on/off the bot easily but i'm having problems with it. I've tried to register a window class and create a window with the game's HWND as a parent but I can't see anything. This is the code I've used to create the child window (not working):
// ... Window class registering etc...
HWND hChild = CreateWindowEx(0,
"MyWindowClass",
"Title",
WS_CHILD | WS_VISIBLE,
0, 0, 100, 100,
hParent,
NULL,
AHInstance,
NULL); // Parent is a valid window handle from another process
Honestly I'm not a skilled windows API programmer, this whole thing is new to me. I'm not even sure if this is the right way to do such thing.
[Edit.] When i minimize/maximize the game my window shows correctly for a second or two. It seems that the game's rendering is happening after the rendering of my window. Any idea? And what about messages? Should i manage them or not? Is the game going to forward messages to my window?
You are not going to have much success by running the code from a different process. Cross process parent/child relationships seldom work. Especially if the other process is not expecting it. This is not something you take on lightly. The capability only exists as a compatibility sop to 16 bit Windows. No place for that technique today.
It seems plausible to me that you don't need to parent the window in this way. If you don't need it to be a child of a window in the other process, don't do that.
If you do need it to be a child of the other process then you might be in trouble. Perhaps you could inject a DLL into the other process and create the window there. Also not without difficulties.
Windows have thread affinity. This means that the thread that creates the window will be processing the messages for that window. Furthermore, all windows in a parent-child chain should be processed by the same thread. Otherwise, bad things happen.
So - how is your code being run? If it's a separate executable, you're going to be much better off leaving your window as a top-level window, and simply monitoring the target window for move events (using UI Automation, for example) and having your window move appropriately.
Otherwise, you're going to need to inject your code into the game executable, and have it create the windows on the appropriate thread. I wouldn't recommend that.

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.

win32 DialogBox app: how to show text from callback on the DialogBox?

I'm working on a win32 DialogBox based app. This uses DialogBox() to create the dialog box, and has a dialog box procedure which does all the usual things.
The dialog box has some static text controls on it, and generally I'm showing text in these via SendDlgItemMessage() from within the dialog box procedure.
However at one point the DialogBox initiates a lengthy operation. This operation has a callback with a series of status messages. I'm having some trouble showing these messages on the dialog box, for two reasons:
The callback function doesn't know what the dialog box HWND is, because it gets called from the code which carries out the lengthy operation. I suppose I can define a file scope HWND variable and copy the dialog box HWND into it from the dialog box procedure just before the lengthy operation is started. That way, the callback function could have access to the dialog box HWND. But that seems awfully kludgy: is there a more elegant way?
The dialog box procedure is blocked while the lengthy operation happens. This doesn't matter because it's an embedded system. But will Windows even show the text in the dialog box if I issue a SendDlgItemMessage() while the dialog box procedure is blocked?
edit I've done some investigations using SendDlgItemMessage() to send a WM_SETTEXT to a static text control on a dialog. The text is displayed immediately even if the dialog box procedure is blocked.
Well, your dialog HWND is a singleton so it isn't the end of the world. But yes, the standard way this is done is by passing an opaque pointer to the code that gets the job done. Compare with the lParam argument of EnumWindows() for example, the callback gets that pointer back.
Whether a control repaints itself immediately is an implementation detail. I only know of progress bar doing this. You could call UpdateWindow on the dialog window handle to get any pending paint updates flushed to the screen.
The all-around better mouse trap is to perform long running tasks on a worker thread. Avoids Windows displaying the "Not Responding" ghost window, avoids timeouts on broadcast messages and numerous potential deadlock problems. But tends to be tricky to get right, you cannot update the window directly from the worker thread.