Setting a HWND's lpfnWndProc from another process - c++

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.

Related

Toggle child process window visibility in Visual C++ without relaunching the child

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.

::PostMessage doesn't work when I am tabbed in to another program

In our Program we have a Dialog from a separate dll open to display infomation. I need to close this dialog when our system timer causes the system to lock.
I send information to the dll by registering a system message in both my MainFrm and EditDisplayDll
SYSTEMLOCK = RegisterWindowMessage("SystemLock");
When I sent the message via
::PostMessage(GetActiveWindow()->m_hWnd,SYSTEMLOCK,0,0);
The message correctly sends to my EditDisplayDll and closes the dialog when the system locks; however, if I alt tab while waiting for the timeout and use another program(firefox, outlook, etc.) the message never correctly calls to the EditDisplayDll. The MainFrm and other windows inside of the MainFrm correctly lockout and hide themselves in either case.
I have tried also using HWND_BROADCAST with PostMessage and SendNotifyMessage. I have also tried to use FindWindow() and FindWindowEx() to specifically call the EditDisplayDll.
I cannot use something like GetDlgItem() because my MainFrm.cpp doesn't have access to this dll.
My decision to use GetActiveWindow() was because I believe it looks to windows specific to my program no matter what window I am in as seen in the imagery in Foreground Vs Active window
Finally, my question is, is there a way to call all Windows in my program no matter what program I am currently in or is there another way I could get access to the specific IDD of the EditDisplayDll in order to send the SYSTEMLOCK message to it?
CWnd *cWndED = FindWindow(_T("EditDisplay"),_T("EditDisplay")); HWND
hwnd = (HWND)cWndED;
You should use win32 API ::FindWindow with proper class, window name. And do not cast CWnd pointer to HWND. Your code should look like:
HWND hWnd = ::FindWindow(_T("ProperClass"), _T("ProperNmae"));
if (hWnd != NULL)
{
::PostMessage(hWnd, YOUR_MESSAGE, ....);
}
I will suggest you to find your Dll window class and name using Spy++ and then try to find that using above method. Remember it's always better to use native API for this kind of tasks.
FindWindow is a good solution if you know both, name of the window and the element.
If you want to get the HWND of your window - no element inside the window -, you can pass as first parameter NULL.
::FindWindow(NULL, _T("WindowName"));
Back to your code: If you are lucky your PostMessage does nothing, otherwise the active window may catch your message. Who knows how/if it is handled in the active window ? Use the PostMessage if you have a valid IsWindow(HWND) from FindWindow or FindWindowEx.
In case you want a CWnd from your HWND take a look at this. (The call may be slow)
HWND hWnd = ::FindWindow(_T("ClassName"), _T("WindowName"));
if (hWnd && IsWindow(hWnd))
{
::PostMessage(hWnd, MESSAGE_TO_BE_SEND, lParam_or_Flags);
}

Get notified when a Window closes (or it's owning thread disappears)

I have a hwnd, which my process does not own, and I want to be notified when it disappears so that my code can perform cleanup actions. What's the best way to do this?
To detect when the HWND's owning process disappears, you can get the HWND's process ID from GetWindowThreadProcessId(), then get a HANDLE to the process using OpenProcess(), and then use WaitForSingleObject() or other related wait function. A process handle is signaled when the process exits.
To detect when just the HWND disappears, get the HWND's thread ID from GetWindowThreadProcessId() and then use SetWindowsHookEx() to hook the message queue of that thread so you can intercept WM_DESTROY and WM_NCDESTROY messages for all HWNDs belonging to that thread, looking for the particular HWND that you are interested in. Note that your hook must be implemented in a DLL when hooking another process, so you will have to use an inter-process communication mechanism of your choosing to notify your main app when the HWND is destroyed.

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.

SetWindowsHookEx process-wide instead of system-wide

I'd like to use SetWindowHookEx to catch WM_CREATE (or HCBT_CREATEWND) messages in a process before a creation of a window.
Using the hMod and dwThreadId it is possible to define whether the hook will be system-wide (by setting hMod to be the gInstance of the DLL and dwThreadId to 0), it is also possible to use it to monitor a SINGLE thread in a process (hMod = 0, and dwThreadId = ThreadToMonitorId).
However, I'd like to monitor multiple threads. Is it possible? I guess I can simply call SetWindowHookEx for multiple threads but I'd rather not as it would make things more complex. Are there other alternatives?
Thanks!
You could hook all processes and only process WM_CREATE for the current process. As the hook is called in the context of the process itself, you can simply compare GetProcessId() to the desired process id.
It is very unusual for a process to create more than one thread that owns a UI window. Sometimes it is a interop window which is intentionally hidden, unlikely that you'd want to know about it. Verify your assumptions with Spy++, the owner thread ID is shown in the window properties, Process tab.
If it does have more than one thread creating windows that you want to know about then you'll want to set separate hooks.