Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to center a WPF Window in a Excel VSTO addin

Tags:

.net

wpf

vsto

The problem is that a WPF window only takes a system.form.window so I cannot set Excel to be the owner object in my VSTO application, because the VSTO addin only exposes Excel's hwnd, or its active window as a Native Window since it is COM. That means when WindowStartUpLoadation is set to be center owner it doesn't work. So I am forced to work around this.

What I have come up with so far after reading this site is to try and manually center the window, but even with his simple example my window never appears centered.

 private static void CenterWpfWindowInExcel(WpfParameterDialog wpfDialog)
    {
        WindowInteropHelper helper = new WindowInteropHelper(wpfDialog);
        helper.Owner = new IntPtr(Globals.ExcelAddin.Application.Hwnd);


        // Manually calculate Top/Left to appear centered
        double nonWpfOwnerLeft = Globals.ExcelAddin.Application.ActiveWindow.Left; // Get non-WPF owner’s Left
        double nonWpfOwnerWidth = Globals.ExcelAddin.Application.ActiveWindow.Width; // Get non-WPF owner’s Width
        double nonWpfOwnerTop = Globals.ExcelAddin.Application.ActiveWindow.Top; // Get non-WPF owner’s Top
        double nonWpfOwnerHeight = Globals.ExcelAddin.Application.ActiveWindow.Height; // Get non-WPF owner’s Height
        wpfDialog.WindowStartupLocation = WindowStartupLocation.Manual;
        wpfDialog.Left = nonWpfOwnerLeft + (nonWpfOwnerWidth - wpfDialog.Width)/2;
        wpfDialog.Top = nonWpfOwnerTop + (nonWpfOwnerHeight - wpfDialog.Height)/2;
    }

Any ideas?

like image 577
Sam Plus Plus Avatar asked Aug 08 '13 20:08

Sam Plus Plus


1 Answers

I was able to solve this by get getting the Rect of the Main Excel Window using user32.dll

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

It appears that Globals.ExcelAddin.Application.ActiveWindow was not giving me back the dimension I expected. I think it was giving me the Ribbon Addin's dimensions and not Excel's Main Window.

like image 75
Sam Plus Plus Avatar answered Oct 05 '22 05:10

Sam Plus Plus