加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

使用WIn32 SetParent()在非WPF应用程序内托管WPF应用程序

发布时间:2020-12-14 04:07:44 所属栏目:Windows 来源:网络整理
导读:我有一个 WPF应用程序,我想看起来它托管在另一个 – 非WPF – 应用程序.在现实生活中,这个非WPF应用程序是Internet Explorer中的ActiveX,但为了说明问题,我使用了一个简单的 Windows窗体应用程序. 我使用Windows API函数SetParent,已经有几十个线程.但是,我
我有一个 WPF应用程序,我想看起来它托管在另一个 – 非WPF – 应用程序.在现实生活中,这个非WPF应用程序是Internet Explorer中的ActiveX,但为了说明问题,我使用了一个简单的 Windows窗体应用程序.

我使用Windows API函数SetParent,已经有几十个线程.但是,我找不到任何关于我的确切问题的内容:WPF应用程序右侧和底部的一个小区域没有在非WPF应用程序窗口内绘制.

WPF窗口自行运行:

使用WinForm应用程序窗口作为父级的WPF窗口:

如果将WPF应用程序与WinForms应用程序或普通Win32应用程序(如记事本)交换,我不会遇到此问题.

WinForm代码如下所示:

private void Form1_Load(object sender,EventArgs e)
    {
        // Start process
        var psi = new ProcessStartInfo("c:wpfappwpfappbinDebugwpfapp.exe");
        psi.WindowStyle = ProcessWindowStyle.Normal;
        _process = Process.Start(psi);

        // Sleep until new process is ready
        Thread.Sleep(1000);

        // Set new process's parent to this window
        SetParent(_process.MainWindowHandle,this.Handle);

        // Remove WS_POPUP and add WS_CHILD window style to child window
        const int GWL_STYLE = -16;
        const long WS_POPUP = 0x80000000;
        const long WS_CHILD = 0x40000000;
        long style = GetWindowLong(_process.MainWindowHandle,GWL_STYLE);
        style = (style & ~(WS_POPUP)) | WS_CHILD;
        SetWindowLong(_process.MainWindowHandle,GWL_STYLE,style);

        // Move and resize child window to fit into parent's
        MoveWindow(_process.MainWindowHandle,this.Width,this.Height,true);
    }

注意:我知道这个使用SetParent不一定是推荐的做法,但我想并且需要找到如何这样做,所以请让我:)

我找到了一个相当好的解决方法:在SetParent之前调用MoveWindow:
private void Form1_Load(object sender,EventArgs e)
{
     // Start process            
     var psi = new ProcessStartInfo("C:WpfAppWpfApp.exe");
     psi.WindowStyle = ProcessWindowStyle.Normal;
     _process = Process.Start(psi);

     // Sleep until new process is ready
     Thread.Sleep(3000);

     // Move and resize child window to fit into parent's
     Rectangle rect;
     GetClientRect(this.Handle,out rect);
     MoveWindow(_process.MainWindowHandle,rect.Right - rect.Left,rect.Bottom - rect.Top,true);

     // Set new process's parent to this window
     SetParent(_process.MainWindowHandle,this.Handle);

     // Remove WS_POPUP and add WS_CHILD window style to child window
     long style = GetWindowLong(_process.MainWindowHandle,GWL_STYLE);
     style = (style & ~(WS_POPUP) & ~(WS_CAPTION)) & ~(WS_THICKFRAME) | WS_CHILD;
     SetWindowLong(_process.MainWindowHandle,style);
}

在SizeChanged事件处理程序中,我将子项从父项中取出,调用MoveWindow并将其移回父项.为了减少闪烁,我在执行这些操作时隐藏了窗口:

private void Form1_SizeChanged(object sender,EventArgs e)
{
     ShowWindow(_process.MainWindowHandle,SW_HIDE);

     var ptr = new IntPtr();
     SetParent(_process.MainWindowHandle,ptr);

     Rectangle rect;
     GetClientRect(this.Handle,out rect);

     MoveWindow(_process.MainWindowHandle,true);            
     SetParent(_process.MainWindowHandle,this.Handle);
     ShowWindow(_process.MainWindowHandle,SW_SHOW);
}

它没有解释为什么MoveWindow在SetParent之后不起作用,但它解决了我的问题,所以我将此标记为答案,除非出现更好的东西.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读