Cover your Office document with Windows Forms

How can you hide your Office document behind a Windows Form? This is a question that has come up on the VSTO forums. The scenario is that you are using Windows Forms to gather information from the user and you want your form to appear to replace the Office document. The solution is straight forward, make a Windows Form the same size and location as the Office document you are trying to hide. You can see an example of this in the image below (I manually offset the Windows Form so you can see the Word document underneath).

You can start with a standard VSTO 2005 SE Word project and add the following code.

using System;
using System.Windows.Forms;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Word = Microsoft.Office.Interop.Word;
using Office = Microsoft.Office.Core;

namespace WordWinformCoverAddIn
{
    public partial class ThisAddIn
    {
        Word.Application app;
        Form coverForm = new Form();
        float dpi;

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            app = this.Application;
            app.WindowSize += new Microsoft.Office.Interop.Word.ApplicationEvents4_WindowSizeEventHandler(app_WindowSize);

            //Screen screen = Screen.PrimaryScreen;
            //coverForm.Height = screen.WorkingArea.Height;
            //coverForm.Width = screen.WorkingArea.Width;

            //Convert Words DPI based Height and Width
            System.Drawing.Graphics g = coverForm.CreateGraphics();
            dpi = g.DpiX;

            MatchWordSize();
            coverForm.Show();
        }

        void app_WindowSize(Microsoft.Office.Interop.Word.Document Doc, Microsoft.Office.Interop.Word.Window Wn)
        {
            MatchWordSize();
        }

        private void MatchWordSize()
        {
            coverForm.Height = (int)(app.Height * dpi / 72);
            coverForm.Width = (int)(app.Width * dpi / 72);
            coverForm.Top = (int)(app.Top * dpi / 72);
            coverForm.Left = (int)(app.Left * dpi / 72);
        }

     ...
    }
}

There are a few things you need to understand about the measurement system used by Office and Windows Forms. Windows Forms measurements are in pixels and Office measurements are in points. So we will need to convert from points to pixels. The MatchWordSize function takes care of this.

        private void MatchWordSize()
        {
            coverForm.Height = (int)(app.Height * dpi / 72);
            coverForm.Width = (int)(app.Width * dpi / 72);
            coverForm.Top = (int)(app.Top * dpi / 72);
            coverForm.Left = (int)(app.Left * dpi / 72);
        }

The dpi (dots per inch) is calculated from the graphics object of the windows form, as seen in the code below. This will return your systems dpi setting either normal 96 or large 120. A point is 1/72 of an inch so we divide the points by the dpi and multiple by 72 to give you the pixels.

            //Convert Words DPI based Height and Width
            System.Drawing.Graphics g = coverForm.CreateGraphics();
            dpi = g.DpiX;

Now all that is left is to handle the resize event from Word so that if the application moves or is resized you can adjust the windows form size and location as well.

I have also left some code in the sample above that calculates the size of the screen. You can use this code if you need to make your windows form and Word side by side, for example to simulate the help window or task pane.