Hi I am trying to host an exe(notepad) in WPF app. Please find the code here:
public partial class MainWindow : Window
{
private Process _process;
private System.Windows.Forms.Panel _panel;
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32")]
private static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent);
[DllImport("user32")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
private const int SWP_NOZORDER = 0x0004;
private const int SWP_NOACTIVATE = 0x0010;
private const int GWL_STYLE = -16;
private const int WS_CAPTION = 0x00C00000;
private const int WS_THICKFRAME = 0x00040000;
const string patran = "patran";
public MainWindow()
{
InitializeComponent();
_process = Process.Start("notepad.exe");
_panel = new System.Windows.Forms.Panel();
wfHost.Child = _panel;
var patranPanelHandle = _panel.Handle;
SetParent(_process.MainWindowHandle, patranPanelHandle);
// remove control box
int style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE);
style = style & ~WS_CAPTION & ~WS_THICKFRAME;
SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style);
// resize embedded application & refresh
ResizeEmbeddedApp();
}
private void ResizeEmbeddedApp()
{
if (_process == null)
return;
SetWindowPos(_process.MainWindowHandle, IntPtr.Zero, 0, 0, (int)_panel.Width, (int)_panel.Height, SWP_NOZORDER | SWP_NOACTIVATE);
}
protected override Size MeasureOverride(Size availableSize)
{
Size size = base.MeasureOverride(availableSize);
ResizeEmbeddedApp();
return size;
}
}
Same code works perfectly fine for Winforms so i used WinformsHost and then added a winforms panel and as described above. But the results are not as expected. The notepad is coming outside of WPF application and the parent child is not working proper
No answer posted for this too
I think, you are invoking SetParent
too soon. You need to do SetParent
once both Parent and Child windows are ready. So, what you could do is wait until the parent window is Loaded
and then launch Child Process. However, call WaitForInputIdle
on the Child Process before you invoke SetParent
.
Below is the sample code I tried and it works:
public partial class MainWindow : Window
{
private Process _process;
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32")]
private static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent);
[DllImport("user32")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
private const int SWP_NOZORDER = 0x0004;
private const int SWP_NOACTIVATE = 0x0010;
private const int GWL_STYLE = -16;
private const int WS_CAPTION = 0x00C00000;
private const int WS_THICKFRAME = 0x00040000;
const string patran = "patran";
public MainWindow()
{
InitializeComponent();
Loaded += (s, e) => LaunchChildProcess();
}
private void LaunchChildProcess()
{
_process = Process.Start("notepad.exe");
_process.WaitForInputIdle();
var helper = new WindowInteropHelper(this);
SetParent(_process.MainWindowHandle, helper.Handle);
// remove control box
int style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE);
style = style & ~WS_CAPTION & ~WS_THICKFRAME;
SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style);
// resize embedded application & refresh
ResizeEmbeddedApp();
}
private void ResizeEmbeddedApp()
{
if (_process == null)
return;
SetWindowPos(_process.MainWindowHandle, IntPtr.Zero, 0, 0, (int)ActualWidth, (int)ActualHeight, SWP_NOZORDER | SWP_NOACTIVATE);
}
protected override Size MeasureOverride(Size availableSize)
{
Size size = base.MeasureOverride(availableSize);
ResizeEmbeddedApp();
return size;
}
For more information on WaitForInputIdle, please refer to this MSDN page.
UPDATE
Attaching the result image:
User contributions licensed under CC BY-SA 3.0