How do I enumerate another process' windows in Delphi? - windows

I have a process foo.exe that creates a process bar.exe with the CreateProcess function. I want (in foo.exe) to enumerate the controls of a window created in bar.exe and for that I (assume that I) need the window HWND.
I know all the window classes in bar.exe, and that bar.exe only creates one window for each class at a time, so I can use the class names to find the window I want.
But what function should I use to enumerate the windows in another process? I'm looking for something that take a process handle or PID (both returned by the CreateProcess function) and an EnumProc callback procedure. Should I find bar.exe's thread ID (it is a single-threaded application) and use that with the EnumThreadWindows function?

Call EnumWindows to enumerate the top level windows.
Pass each top level window handle to GetWindowThreadProcessId to find out which process ID it is associated with.
When you find a top level window that matches your process ID, check that the window is the main window of the app, presumably by checking its class name.
Finally, call EnumChildWindows on that main window to enumerate all children of that main window.

Related

Access Windows Controls from another class or window

In an MFC program I am trying to access controls that are in one window (class) from another (sibling or daughter) window with code in a different .cpp file. Typically you access a control with a DDX_Control variable defined in the class .cpp file.
DDX_Control(pDX, IDC_STATUS, m_Status);
The code for the other window is in a different file, so I don’t have access to the control variable (m_Status). What I have done is used FindWindow to find the main window, then GetDlgItem to find the control I am interested in:
CWnd * tmpWnd = CWnd::FindWindow(NULL,"MainWindow"); // find the main dialog box
CStatic * tmpStatus = (CStatic*) tmpWnd->GetDlgItem(IDC_Status);
tmpStatus->SetWindowText(“Status Report);
This works fine in the debugger, but fails when executed outside the debugger. FindWindow gets the window ID correctly, but GetDlgItem returns null.
Ideally I’d like to access the control variable (m_Status) from the other window, but I don’ know how to do so. I understand the GetDlgItem is less than ideal under any circumstance.
One solution would be to send a message to the main window class and tell it what to do, but I’d have to have a routine to handle each control and know how to handle whatever kind of data I am sending.
Is there a “right” way to do this?
Thank you
The ultimate answer is to cast to the original class:
((CspDlg *)AfxGetMainWnd())->m_Status.SetWindowText("Report");
Since you created the "main" window you have an object or pointer for it. Or, you can call AfxGetMainWnd() to get a pointer to it. Then you can use that to access a public member such as m_Status. All of your windows are interconnected and it should not be necessary to use FindWindow to find any window in your own program.
The fact that some variables may be defined in another file is not relevant. That can be handled with suitable use of #include "theotherfile.h" and object pointers/references.

Change console color of child process

I'm creating a new process which calls a console application. I want to change the colors of this child process's console window.
The reason is that I can't redirect the console's stdout because the application manipulates the console cursor. Instead I'm stripping the console frame, clipping the info I want and embed the console in my application wholesale. I just want to change the colors so it fits in better.
I know of the SetConsoleTextAttribute function but I don't know how to get to the stdout handle of the child process to use it.
Anyone have any ideas?
The documentation for DuplicateHandle says:
Console handles can be duplicated for use only in the same process
(They are not real handles) so even if you could inject code into the child you could not go down this route.
I'm assuming the parent application does not already have a console (You can only have one per process without doing horrible hacks), if that is the case you should be able to use AllocConsole(), GetStdHandle(), SetConsoleTextAttribute(), CreateProcess() and finally FreeConsole() (You don't need FreeConsole if you only run one child process at the time)
The other option is to use cmd.exe: cmd.exe /T:?? /C childapplication.exe (Replace ?? with the color values you find by running color /? in cmd)

Recreate Window Using GetConsoleScreenBufferInfo Method

I believe that the GetConsoleScreenBufferInfo method gets information about the window passed as a parameter into it into a CONSOLE_SCREEN_BUFFER_INFO structure. Can this information be used to recreate a window? Or is there a method which can create a window taking CONSOLE_SCREEN_BUFFER_INFO as a parameter?
There is no function that I know of that will create a new window given a CONSOLE_SCREEN_BUFFER_INFO structure. There certainly isn't such a thing described in the Console Functions reference.
I'd be interested to know why you want such a thing. Are you trying to create a duplicate console window? If so, you should note that a process can be associated with only one console. And you can't create a console window that's not attached to a process. The console goes away when the last process detaches from it.

Real hwnd from the point

When we use WindowFromPoint winapi function we usually can get the case, when Point specifies to some control within a window. And in such cases WindowFromPoint returns handle to that control, not to the window that handles that control.
For example in my small test application if I point to the "body" of chrome browser I get the control with class = Chrome_RenderWidgetHostHWND and its hwnd.
But what I need is to get the "parent" window for that control (which is obviously should be the chrome window).
Traverse the parents using GetAncestor() passing GA_PARENT. This differs from calling GetParent() which will return the owner if the window is a top-level window.
Can't you just use GetParent? Keep traversing until you find the desktop window.

How do I get a HWND from inside a DLL?

I have a DLL that I want to play sounds using Direct Sound. In order to play sounds, I need the HWND of the executable. I don't have a HWND of the executable that loads the DLL. How do I get that in the DLL without passing it in from the executable?
You could use GetCurrentProcessId to get the current process Id.
You could then call EnumWindows, and check each window with GetWindowThreadProcessId to find a window associated with your process.
However, an easier option might be to just generate your own Window. You can create a 1x1 pixel window that is not visible, and use it with Direct Sound.
This has the advantage of working even if your calling process doesn't have a usable window (or deletes window handles regularly).
Call GetGUIThreadInfo on the main thread. This gets you a bunch of HWNDs. If you need a top-level HWND, pick any valid one (not all values may be filled) and find its top level ancestor with GetAncestor(GA_ROOT).

Resources