Open a WPF form in an Office application and have subforms appear on the Office application

In the .NET main program, we can open an Excel application by creating an ExcelApplication object. If we want to open the WPF window in Excel, the problem is not so simple.

We can simply instantiate a WPF form object and then open the new WPF form on the form of the Office application. At this time, the form of the Office application is the host form of WPF. Then the host form and the Office application are not on the same UI thread, and the child form is likely to be invisible behind the host form. At this time, you need to call the Win32 function to set the form of the Office application as the parent form of the WPF child form. The form of this function is defined as follows:

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

Since Office applications are unmanaged programs and WPF forms are managed programs, .NET provides a WindowInteropHelper wrapper class, which can wrap a managed program form to get a window handle, and then call the above Win32 function SetParent to set the window father-son relationship.

The following method is a complete method, which can instantiate a WPF form object through reflection, and then set the WPF form object as a subform of the Office application and display it normally on the Office application.

 

   ///  <summary> 
        /// Display the WPF form on the Excle window
         ///  </summary> 
        ///  <param name="assemplyName">The assembly where the form object is located </param> 
        ///  <param name="paramClassFullName"> Form object full name </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();
                    // Specify the Excel handle as the handle of the parent form of the current form, refer to https://blog.csdn.net/pengcwl/article/details/7817111 
                    // ExcelApp is an Excle application object 
                    var excelHwnd = new IntPtr( OfficeApp.ExcelApp.Hwnd);
                    winBoxIntreop.Owner = excelHwnd;
                    SetParent(winBoxIntreop.Handle, excelHwnd);
                    winBox.ShowDialog();
                }
                catch (Exception ex)
                {
                    MessageBox.Show( " Error opening window: " + ex.Message);
                }
            }));
        }
    }

     

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324938058&siteId=291194637