专栏首页程序员的SOD蜜在Office应用中打开WPF窗体并且让子窗体显示在Office应用上

在Office应用中打开WPF窗体并且让子窗体显示在Office应用上

在.NET主程序中,我们可以通过创建 ExcelApplication 对象来打开一个Excel应用程序,如果我们想在Excle里面再打开WPF窗口,问题就不那么简单了。

我们可以简单的实例化一个WPF窗体对象然后在Office应用程序的窗体上打开这个新的WPF窗体,此时Office应用的窗体就是WPF的宿主窗体。然后宿主窗体跟Office应用并不是在一个UI线程上,子窗体很可能会在宿主窗体后面看不到。这个时候需要调用Win32函数,将Office应用的窗体设置为WPF子窗体的父窗体,这个函数的形式定义如下:

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

由于Office应用程序是非托管程序,WPF窗体是托管程序,.NET提供了一个 WindowInteropHelper 包装类,它可以将一个托管程序窗体包装得到一个窗口句柄,之后,就可以调用上面的Win32函数 SetParent 设置窗口的父子关系了。

下面方法是一个完整的方法,可以通过反射实例化一个WPF窗体对象,然后设置此WPF窗体对象为Office应用程序的子窗体,并正常显示在Office应用程序上。

   /// <summary>
        /// 在Excle窗口上显示WPF窗体
        /// </summary>
        /// <param name="assemplyName">窗体对象所在程序集</param>
        /// <param name="paramClassFullName">窗体对象全名称</param>
        public static void ExcelShowWPFWindow(string assemplyName, string paramClassFullName)
        {
            Application.Current.Dispatcher.Invoke(new Action(() => {
                try
                {
                    Assembly assembly = Assembly.Load(assemplyName);
                    Type classType = assembly.GetType(paramClassFullName);
                    object[] constuctParms = new object[] { };
                    dynamic view = Activator.CreateInstance(classType, constuctParms);
                    Window winBox = view as Window;
                    var winBoxIntreop = new WindowInteropHelper(winBox);
                    winBoxIntreop.EnsureHandle();
                    //将Excel句柄指定为当前窗体的父窗体的句柄,参考 https://blog.csdn.net/pengcwl/article/details/7817111
                    //ExcelApp 是一个Excle应用程序对象
                    var excelHwnd = new IntPtr(OfficeApp.ExcelApp.Hwnd);
                    winBoxIntreop.Owner = excelHwnd;
                    SetParent(winBoxIntreop.Handle, excelHwnd);
                    winBox.ShowDialog();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("打开窗口错误:"+ex.Message);
                }
            }));
        }
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 在Linux系统运行WinForm程序

    在Windows系统,最常见的就是Windows Forms程序(以下简称WinForm程序),也就是窗体应用程序,比如MS Office,媒体播放器软件等,W...

    用户1177503
  • Erlang语言学习入门

    近期研究RabbitMQ,发现它是基于Erlang实现的,于是对Erlang这么语言发生了兴趣,官网地址 http://www.erlang.org/ ,去下载...

    用户1177503
  • “一切都是消息”--MSF(消息服务框架)入门简介

    “一切都是消息”--这是MSF(消息服务框架)的设计哲学。 MSF的名字是 Message Service Framework 的简称,中文名称:消息服务框架,...

    用户1177503
  • C#Winform编程的基础知识

    1. 将第一个窗体的值传给第二个窗体,用到第二个窗体的重载构造函数 Form2 form2=new Form(str1);

    Dabelv
  • 附实例!实现iframe父窗体与子窗体的通信

    本文主要会介绍如何基于MessengerJS,实现iframe父窗体与子窗体间的通信,传递数据信息。

    前端林子
  • WPF自学入门(八)WPF窗体之间的交互

    今天我们一起来看一下WPF窗体之间的交互-窗体之间的传值。有两个窗体,一个是父窗体,一个是子窗体。要将父窗体的文本框中的值传递给子窗体中的控...

    黄昏前黎明后
  • VB语言基础重要知识点04

    双击开发界面上的控件,会自动生成这个控件对应的事件。如果这个控件是按钮,会自动生成单机事件对应的代码。注意这个代码不需要自己写,只需要自动生成就可以了,自己去打...

    刘金玉编程
  • 关于Form窗体的StartPosition 属性如何设置的问题

    故只有设置StartPosition 属性放在窗体构造函数中;而不能放在Load事件中。

    跟着阿笨一起玩NET
  • winform 取消datagridview第一行选中状态

    http://www.cnblogs.com/freeliver54/archive/2009/02/16/1391325.html

    跟着阿笨一起玩NET
  • 学生信息管理系统验收总结

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

    DannyHoo

扫码关注云+社区

领取腾讯云代金券