Reputation: 5744
I'm trying to get a legacy MFC application and a new WPF usercontrol to shut down a dialog window based on a button press in the WPF usercontrol. In essence, I would like some tips on how I can get the DoModal()
function of MFC return.
For various reasons the dialog is a MFC CDialog
started via DoModal
, which hosts a single WPF component and nothing else. This component then has a button which will need to close the CDialog
after doing some various tasks. This application is an.. exiting.. case of legacy and it's really hard to track control flow and where the actual message pumps driving this thing resides. It's also full of #defines
that makes everything twice as difficult as it should be. I think I have identified the message pump, so I think I can insert something into that to make it close - if I can get to that from the WPF control.
I do not know how to send a windows message out from the usercontrol to the host, or how to get the HWND
of the host from the usercontrol. I'm sure there is a way to get that, or another better way of communicating?
Is the correct approach to send a WM_CLOSE
message to the parent HWND
? Or perhaps I can send a WM_USER
to the dialog pump and handle the actual closing there?
Upvotes: 0
Views: 2115
Reputation: 15271
Declare a close event in the control. Raise the event when the close button is closed.
In your CDialog-derived class, subscribe to the event, then call EngDialog in the event handler.
Upvotes: 2
Reputation: 2368
Try this. It should work for any WPF element (if it's a Visual), by finding it's containing HWND, tracing up the HWND tree until it finds the root parent, then sending that a WM_CLOSE message.
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
private static extern IntPtr GetParent(IntPtr hWnd);
//I'd double check this constant, just in case
static uint WM_CLOSE = 0x10;
private void CloseContainingWindow(Visual visual)
{
// Find the containing HWND for the Visual in question
HwndSource wpfHandle = PresentationSource.FromVisual(this) as HwndSource;
if (wpfHandle == null)
{
throw new Exception("Could not find Window handle");
}
// Trace up the window chain, to find the ultimate parent
IntPtr hWindow = wpfHandle.Handle;
while (true)
{
IntPtr parentHWindow = GetParent(hWindow);
if (parentHWindow == (IntPtr)0) break;
hWindow = parentHWindow;
}
// Now send the containing window a close message
SendMessage(hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
Upvotes: 4
Reputation: 1959
WM_CLOSE should work, but you have to try it. Another approach is to post a WM_COMMAND message to the parent dialog. Sending a WM_USER looks too complicated.
Upvotes: 0