I'd like to host a window of an external process inside my WPF application. I'm deriving HwndHost
like this:
class HwndHostEx : HwndHost
{
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
private IntPtr ChildHandle = IntPtr.Zero;
public HwndHostEx(IntPtr handle)
{
this.ChildHandle = handle;
}
protected override System.Runtime.InteropServices.HandleRef BuildWindowCore(System.Runtime.InteropServices.HandleRef hwndParent)
{
HandleRef href = new HandleRef();
if (ChildHandle != IntPtr.Zero)
{
SetParent(this.ChildHandle, hwndParent.Handle);
href = new HandleRef(this, this.ChildHandle);
}
return href;
}
protected override void DestroyWindowCore(System.Runtime.InteropServices.HandleRef hwnd)
{
}
}
and using it like this:
HwndHostEx host = new HwndHostEx(handle);
this.PART_Host.Child = host;
where handle
is a handle for an external window I'd like to host and PART_Host
is a border inside my WPF window:
<StackPanel UseLayoutRounding="True"
SnapsToDevicePixels="True"
Background="Transparent">
<Border Name="PART_Host" />
...
This gives me an exception:
Hosted HWND must be a child window.
Sorry for my lack of knowledge but what is the proper way of hosting an external window inside WPF application?
Right before calling 'SetParent' do this:
public const int GWL_STYLE = (-16);
public const int WS_CHILD = 0x40000000;
SetWindowLong(this.ChildHandle, GWL_STYLE, WS_CHILD);
Looking at the docs :
It seems not possibile to "attach" an already running Window from another process inside a WPF app.
How do you get the handle you pass to your HwndHostEx constructor?
To add clarification, here's the final code for hosting a process in a WPF app, taken from Jose's answer:
class HwndHostEx : HwndHost
{
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, UInt32 dwNewLong);
private IntPtr ChildHandle = IntPtr.Zero;
public HwndHostEx(IntPtr handle)
{
this.ChildHandle = handle;
}
protected override System.Runtime.InteropServices.HandleRef BuildWindowCore(System.Runtime.InteropServices.HandleRef hwndParent)
{
HandleRef href = new HandleRef();
if (ChildHandle != IntPtr.Zero)
{
const int GWL_STYLE = (-16);
const int WS_CHILD = 0x40000000;
SetWindowLong(this.ChildHandle, GWL_STYLE, WS_CHILD);
SetParent(this.ChildHandle, hwndParent.Handle);
href = new HandleRef(this, this.ChildHandle);
}
return href;
}
protected override void DestroyWindowCore(System.Runtime.InteropServices.HandleRef hwnd)
{
}
}
// to create an instance:
var processName = "Whatever.exe";
var process = System.Diagnostics.Process.GetProcesses()
.FirstOrDefault(item => item.ProcessName.ToLowerInvariant() == processName && item.MainWindowHandle != IntPtr.Zero);
var handle = process?.MainWindowHandle;
if(handle != null)
{
var host = new HwndHostEx(handle.Value);
YourControl.Grid.Children.Add(host);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.