Embedding word 2010 editor in a wpf application

Mostafa Rezaei picture Mostafa Rezaei · Jun 1, 2011 · Viewed 14.3k times · Source

How do I use the word editor in a WPF application? Is it possible using windows forms hosting in WPF only? Is there another way to accomplish that?

I found AvalonEdit but it does not have features that I need. So using this way, my problem may not be solved.

Also there is some stuffs out there to host a windows forms control in WPF, but it could not be my answer.

I want to understand that is there a way to use word editor in a native way in a wpf app? Will all APIs be available in that solution?

Thanks in advance.

Answer

pgfearo picture pgfearo · Jun 22, 2011

You can host MS Word (2007/2010 and probably other versions) from within a WebBrowser control, this works in WinForms and should work in WPF too. A .NET API is provided for automating Word, documented here. The required interop assemblies ship with Office 2010, so deployment is a lot simpler than previous Office versions.

See this Microsoft Support article for more details on hosting Word within a WebBrowser control. The Screenshot below shows Word embedded within a host Winforms application.

enter image description here

Note that this only works reliably for a single hosted instance of Word, so you can't show 2 Word documents side by side in the same application. Also, the Ribbon can sometimes go missing - but Word hasn't ever caused the application to crash.

Administrative rights are required to make the required registry updates as there are potential security issues. One easy method to make the registry updates is to write a script, but the following (revised/untested) code shows how this can be done in c# for Word, Excel and PowerPoint:

using System.Security.AccessControl;

    private Dictionary<string,uint> OfficeBrowserRegKeys()
    {
        string[] officeRegKeyArray = new string[]
            {
                @"SOFTWARE\Classes\Word.Document.12",
                @"SOFTWARE\Classes\Word.DocumentMacroEnabled.12",
                @"SOFTWARE\Classes\Excel.Sheet.12",
                @"SOFTWARE\Classes\Excel.SheetMacroEnabled.12",
                @"SOFTWARE\Classes\Excel.SheetBinaryMacroEnabled.12",
                @"SOFTWARE\Classes\PowerPoint.Show.12",
                @"SOFTWARE\Classes\PowerPoint.ShowMacroEnabled.12",
                @"SOFTWARE\Classes\PowerPoint.SlideShow.12",
                @"SOFTWARE\Classes\PowerPoint.SlideShowMacroEnabled.12"
            };
        Dictionary<string,uint> officeRegKeys = new Dictionary<string, uint>();
        uint wrdVal = 0x80000024;
        uint excelVal = 0x80000A00;
        uint powerPtVal = 0x800000A0;
        foreach(string keyName in officeRegKeyArray)
        {
            if (keyName.Contains("Word"))
            {
                officeRegKeys.Add(keyName, wrdVal);
            }
            else if (keyName.Contains("Excel"))
            {
                officeRegKeys.Add(keyName, excelVal);
            }
            else
            {
                officeRegKeys.Add(keyName, powerPtVal);
            }
        }
        return officeRegKeys;
    }

    private void setNewOfficeKeys()
    {
        uint editFlag = 0x00010000;
        Dictionary<string,uint> officeRegKeys = OfficeBrowserRegKeys();

        foreach (KeyValuePair<string, uint> kvp in officeRegKeys)
        {
            try
            {
                RegistryKey rKey = Registry.LocalMachine.OpenSubKey(kvp.Key, 
                   RegistryKeyPermissionCheck.ReadWriteSubTree,
                   System.Security.AccessControl.RegistryRights.SetValue);
                rKey.SetValue("BrowserFlags", unchecked((int)kvp.Value),
                RegistryValueKind.DWord);
                rKey.SetValue("EditFlags", unchecked((int)editFlag),
                RegistryValueKind.DWord);
            }
            catch (Exception e) { string msg = e.Message; }
        }
    }