How to find main HWND handle of MFC-using parent process - winapi

I have a DLL file that is running under a parent piece of software. The parent software uses MFC and displays a main GUI window. What I want to do is create my own little modeless dialog box to pop up on the screen and sit right next to the main window. To do this I think I need the HWND of the parent's main window so I can find it's RECTangle and then move my DLL's window to where I want it.
If at all possible, I'd like not to change the source of the parent. How could I do this?
A second, possibly related, question is whether I should use MFC, or plain windows API, to create my DLL's dialog box. I want the method that will be easier to get it going, and I have read on MSDN that I may need the parent MFC application to send me messages for my MFC to work, which I'd rather not do.

I don't know if you can create an MFC dll that can find MFC objects created in another module. I'm pretty sure that MFC can be used to create dialogs from DLLs, regardless of whether or not MFC is used in the application.
That said, if you are not already an MFC expert, and have no real wish to become one, creating a dialog box from a dll is quite easy. MFC's CDialog is really a thin wrapper over CreateDialog so you don't gain much.
I can think of at least two approaches to find the application window if the app/dll interface doesn't hand it over:
Use FindWindow to locate the window based on its title, or classname. As frameworks like MFC sometimes generate window classnames dynamically this might be problematic.
Use EnumWindows to enumerate all top level windows. GetWindowThreadProcessId can test if it belongs to the current process.

Call GetGUIThreadInfo on the main thread. This gets you a bunch of HWNDs. Pick any valid one (not all values may be filled) and find its top level ancestor with GetAncestor(GA_ROOT). Unlike EnumWindows, this doesn't require enumeration, and unlike FindWindow this doesn't require specialized knowledge

For obtaining the PID of the parent — not the HWND — look at this that I found on http://www.codeexperts.com/showthread.php?1380-get-parent-process-id-from-child-process-id&p=2845&viewfull=1#post2845
DWORD GetParentProcessID(DWORD dwProcessID)
{
DWORD dwParentProcessID = -1 ;
HANDLE hProcessSnapshot ;
PROCESSENTRY32 processEntry32 ;
hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) ;
if(hProcessSnapshot != INVALID_HANDLE_VALUE)
{
processEntry32.dwSize = sizeof(PROCESSENTRY32) ;
if(Process32First(hProcessSnapshot, &processEntry32))
{
do
{
if (dwProcessID == processEntry32.th32ProcessID)
{
dwParentProcessID = processEntry32.th32ParentProcessID ;
break ;
}
}
while(Process32Next(hProcessSnapshot, &processEntry32)) ;
CloseHandle(hProcessSnapshot) ;
}
}
return dwParentProcessID ;
}

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.

Is it possible to embed one application in another application in Windows?

I'm writing a Windows application in Visual C++ 2008 and I want to embed the calculator (calc.exe) that comes with Windows in it. Does anyone know if that is possible, and if it is, can you give me hints on how I could achieve that?
Yes, it's possible to embed the calc in your own application but it will still run in it's own process space. There may also be some restrictions imposed by UAC but that will depend on how calc is launched. All you need to do is change the parent of the main calc window and change it's style to WS_CHILD.
void EmbedCalc(HWND hWnd)
{
HWND calcHwnd = FindWindow(L"CalcFrame", NULL);
if(calcHwnd != NULL)
{
// Change the parent so the calc window belongs to our apps main window
SetParent(calcHwnd, hWnd);
// Update the style so the calc window is embedded in our main window
SetWindowLong(calcHwnd, GWL_STYLE, GetWindowLong(calcHwnd, GWL_STYLE) | WS_CHILD);
// We need to update the position as well since changing the parent does not
// adjust it automatically.
SetWindowPos(calcHwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
}
Microsoft has various technologies to support embedding, most famously OLE which is a COM-based technology. This is, for example, how you can embed an Excel spreadsheet in your application. However, I'm fairly certain that calc does not implement any of the required interfaces for that to happen.
So that only leaves you with hacky solutions, like trying to launch it yourself and play games with the window hierarchy, or try to present it to users and then copy the results out through the clipboard, etc. This is all technically possible, but not a good idea. In fact, it's probably more difficult than just writing your own calculator app... depending on what you want to to enable users to do. If you explain why you want to do this someone may have some better solutions to propose.

How does DispatchMessage decide which WndProc to use?

I'm going through some code for an open source project and this is my first time dealing with a Win32 app (mostly did console stuff). I see that several functions within the code are windows procedures because they return LRESULT CALLBACK.
Is there something the programmer has to do to make sure DispatchMessage invokes the right WndProc or is DispatchMessage coded in a way that it can determine the right WndProc all on its own?
EDIT:
I'm guessing that the way DispatchMessage(const MSG*) chooses between different WndProc's in an application is based on the window handle member (HWND) of the MSG object passed to it.[Hope previous sentence wasn't too confusing.] If the message was for the edit window for an application, for example, (and not for its main window,) then DispatchMessage will choose the WndProc member function for the particular class for which the edit window is an object of. If the message was for the main window, then it would choose the WndProc member function for the class that the main window is an object of (for me, this class would be the Notepad_plus_Window class). This is only a thought, though. I haven't found much to back it up so I'd be glad if anyone could confirm this.
Yes you are right, it uses MSG.hwnd to send the message to the correct window. One thing to be noted, it will use the WndProc associated with the window, not the window class. A window is an instance of a window class.
This article of Microsoft's "Under The Hood" illustrates this with rather detailed pseudo-code of DispatchMessage() that might be worth taking a look as well )

Hiding a control in Windows

I can't figure out how to hide a child window (a control), more specifically a GroupBox and a PushButton. I thought ShowWindow() with SW_HIDE as the second parameter would do the job, but it simply doesn't work. Yet SW_SHOW works just fine. I have the correct window handle for both controls, so that's not the issue.
I googled and all I could find was people asking how to hide dialogs, not controls. Either that or MFC-based applications, which doesn't apply here.
I'm using pure Windows API, no MFC.
What am I getting wrong?
EDIT: More info: I'm writing some simple class wrappers for WinApi controls. The WindowsControl class has, along other methods, the following methods for showing and hiding the Control:
void Show() {
ShowWindow(this->_hWnd,SW_SHOWNOACTIVATE);
}
void Hide() {
ShowWindow(this->_hWnd,SW_HIDE);
}
Every control inherits from WindowsControl.
This image has the window layout so you understand exactly what I'm doing: http://i.stack.imgur.com/PHQnH.png
When the user clicks inside the "Chipset" Static control, it'll load information for a given Tile (which is stored in an array, but that's irrelevant). Depending on the setting, it'll hide the "Edit bitwall" button on the left and show the empty GroupBox behind it or viceversa.
Just to be clear this isn't something wrong with my windows api wrappers, I am getting the correct HWND. Though ShowWindow might not be able to be called from a Window Procedure that isn't the parent's (that'd be weird).
EDIT2: Using C++ with Visual Studio 2008, no MFC, no WTL, no CLR, no .NET
EDIT3: I'll post even more code so it's easier
Inside the static's window procedure, I handle WN_LBUTTONDOWN like this:
case WM_LBUTTONDOWN: {
...
update_tiledata(c, l)
void update_tiledata(GroupBox * c, ListView* l ) {
...
if (chp_copy.Tiles[selectedTile].Pass() == PT_BITWALL) {
c->Controls(CTL_BTNEDITBIT)->Show();
c->Controls(CTL_FRPHOLD)->Hide();
} else {
c->Controls(CTL_FRPHOLD)->Show();
c->Controls(CTL_BTNEDITBIT)->Hide();
}
update_edits();
}
The ommited code does nothing to affect the classes, as I said before, ShowWindow with SW_HIDE IS getting called, with the correct HWND, but nothing is happening.
A control in a Window or dialog can be hidden using
ShowWindow(hControlWin, SW_HIDE);
In a dialog you can retrive the controls window handle by calling
GetDlgItem(hDlg, < CtrlID >);
Typically you write something like:
ShowWindow(GetDlgItem(hDlg, 2), SW_HIDE);
It would be helpful if you give more information and some code: How did you create the controls? What language, compile and framework did you use?
I think the function call you want is EnableWindow I have used this before to disable a button on a form. You will need to get an handle to the Window (object) first though so you might want to use EnumChildWindows to iterate through all the controls to find the one you want.

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