使用 HwndHost 在 WPF 中托管外部窗口的正确方法

问题描述 投票:0回答:3

我想在我的 WPF 应用程序中托管一个外部进程的窗口。我像这样导出

HwndHost

    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)
        {

        }
    }

并像这样使用它:

 HwndHostEx host = new HwndHostEx(handle);
 this.PART_Host.Child = host;

其中

handle
是我想要托管的外部窗口的句柄,
PART_Host
是我的 WPF 窗口内的边框:

<StackPanel UseLayoutRounding="True"
        SnapsToDevicePixels="True"
        Background="Transparent">
        <Border Name="PART_Host" />
...

这给了我一个例外:

Hosted HWND must be a child window.

抱歉,我缺乏知识,但是在 WPF 应用程序中托管外部窗口的正确方法是什么?

c# wpf hwndhost
3个回答
6
投票

在调用“SetParent”之前执行以下操作:

public const int GWL_STYLE = (-16);
public const int WS_CHILD = 0x40000000;

SetWindowLong(this.ChildHandle, GWL_STYLE, WS_CHILD);

1
投票

查看文档

  1. 您需要为 CLI 编译的 Win32 控件
  2. 您必须在 WPF 应用程序中创建控件。

似乎不可能从 WPF 应用程序内的另一个进程“附加”已经运行的窗口。

如何获取传递给 HwndHostEx 构造函数的句柄?


0
投票

为了补充说明,以下是在 WPF 应用程序中托管进程的最终代码,取自 Jose 的答案:

    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);
}


© www.soinside.com 2019 - 2024. All rights reserved.