Using Visual Studio 2017.
I use
siStartInfo.dwFlags &= STARTF_USESHOWWINDOW;
siStartInfo.wShowWindow = SW_HIDE;
to create a child process (through CreateProcess()) with a hidden window. It works perfectly.
What I would like, if at all possible, is to be able to toggle the visibility status of the child process' window, post-creation, from the main program on demand (with a press of a button, for example). I want to control the child process' window visibility without relaunching it through CreateProcess().
Modifying the child process code is not an option - it can be many different programs with not necessarily available source code.
Thanks in advance.
If you know a unique window class or title of the child process, you can use FindWindow() to find that window.
For a more generic approach, use EnumWindows() to enumerate all top-level windows. For each window call GetWindowThreadProcessId() to check if it belongs to the child process.
Call ShowWindow() to toggle visibility.
Related
I have written a simple win32 program say abc.exe.
I have added a button in it, clicking on which an external exe say xyz.exe should start.
But the original program i.e. abc.exe should be inaccessible while xyz.exe is running. (Same as in the case of message box where the parent window remains inactive unless message box is closed)
How can Ido it ?
It would be great if you could post an example code.
You can use WaitForSingleObject (IIRC) to wait for the new process to terminate. You can make your window not visible (e.g. via ShowWindow) before waiting. Check successful launch first.
When the button is pressed, create the 'xyz.exe' process using CreateProcess function and save the new process' handle (hProcess in the PROCESS_INFORMATION struct you passed in CreateProcess).
Then you can disable the 'abc.exe' window by calling EnableWindow with bEnable set to FALSE.
In the window procedure of 'abc.exe', where the WM_PAINT message is handled add a check to see if the 'xyz.exe' process is still running. You can do this by using GetExitCodeProcess function with the handle you saved earlier and checking if the return value is STILL_ACTIVE. If the 'xyz.exe' process is no longer active, you can then enable the 'abc.exe' window using EnableWindow again.
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.
I have a program that launches a child process.
When the child process crashes I would like there not to be a debug message box. I would like to do this without writing anything in the child process.
I am running this on windows 7.
In the createProcess function, in the flags parameter I only put CREATE_NEW_CONSOLE.
During my attempts, I put SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX) in the child process and made it crash, there was no dialog box. Now I put the same function call in the parent program before I called create process, and made the child program crash, now the message box appeared.
What should I do differently?
have you set CREATE_DEFAULT_ERROR_MODE in process creation flags?
I have a win32 main application that spawns a child process.
At the moment I use CreateWindowEx to create a HWND in the main application followed by spawning a child process. The child process then looks up the HWND using FindWindow. I would like to handle the Window messages (e.g. WM_SIZE, WM_SETFOCUS etc) for this HWND in the child process, therefore I tried setting the GWLP_WNDPROC attribute in the child process but I'm getting an access denied error, which is reasonable.
I thought about creating a HWND directly in the child process instead but when the window is clicked on, the main application loses focus which is not acceptable for my use case.
Does anyone have a suggestion on what to do to keep the focus on the main application, while having the child process handling the messages?
Use SetWindowsHookEx with one of the windows message hooks (e.g. WH_CALLWNDPROC) to intercept the messages going to other windows, then filter by the HWND of the window in question.
In your child process you can call ShowWindow with WS_NOACTIVATE. When calling CreateProcess function you can specify STARTUPINFO as follows:
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNOACTIVATE;
You can even explicitly give back focus in your child application to main window.
I suppose you want to have similar design to what chromium does. If you look closely at their design docs:
http://www.chromium.org/developers/design-documents/inter-process-communication
you will see that they do implement IPC between processes but they do not have single message processing function in main process.
As last hint - not related to question, read on jobs under windows - this mechanism allows to take a closer control on child processes.
I need to enumerate all running applications. In particular, all top windows. And for every window I need to add my custom item to the system menu of that window.
How can I accomplish that in C++?
Update.
I would be more than happy to have a solution for Windows, MacOS, and Ubuntu (though, I'm not sure if MacOS and Ubuntu have such thing as 'system menu').
For Windows, another way to get the top-level windows (besides EnumWindows, which uses a callback) is to get the first child of the desktop and then retrieve all its siblings:
HWND wnd = GetWindow(GetDesktopWindow(), GW_CHILD);
while (wnd) {
// handle 'wnd' here
// ...
wnd = GetNextWindow(wnd, GW_HWNDNEXT);
}
As for getting the system menu, use the GetSystemMenu function, with FALSE as the second argument. The GetMenu mentioned in the other answers returns the normal window menu.
Note, however, that while adding a custom menu item to a foreign process's window is easy, responding to the selection of that item is a bit tricky. You'll either have to inject some code to the process in order to be able to subclass the window, or install a global hook (probably a WH_GETMESSAGE or WH_CBT type) to monitor WM_SYSCOMMAND messages.
Once you have another window's top level handle, you may be able to call GetMenu() to retrieve the Window's system menu and then modify it, eg:
HMENU hMenu = GetMenu(hwndNext);
You can use EnumWindows() to enumerate top level Windows.
I don't have a specific answer for the second part of your question, but if you subclass the window, I imagine you can modify the system menu.
EDIT: or do what Chris said: call GetMenu()
Re: the update - please note that not even Microsoft Windows requires windows to have a sytem menu. GetMenu( ) may return 0. You'll need to intercept window creation as well, because each new top window presumably needs it too.
Also, what you propose is rather intrusive to other applications. How are you going to ensure they don't break when you modify their menus? And how are you going to ensure you suppress the messages? In particular, how will you ensure you intercept them before anyone else sees them? To quote Raymond Chen, imagine what happens if two programs would try that.