6

I'm working on an Excel add in that opens a winform after the user clicks a button on a ribbon bar. This button needs to be non-modal so that the user can still interact with the parent window, but it also must remain on top of the parent window at all times. To accomplish this I'm trying to pass the parent window as a parameter into the Show() method. Here's my code:

Ribbon1.cs

    private void button2_Click(object sender, RibbonControlEventArgs e)
    {
        RangeSelectForm newForm = new RangeSelectForm();

        newForm.Show(this);
    }

The problem with this code is that the word 'this' references the ribbon class, not the parent window. I also tried passing in Globals.ThisAddIn.Application.Windows.Parent. This results in a runtime error "The best overloaded method match for 'System.Windows.Forms.Form.Show(System.Windows.Forms.IWin32Window)' has some invalid arguments". What is the correct way to pass the parent window to Show()?

In case it's relevant, this is an Office 2010 app written on .NET 4.0 using C#.

EDIT --- based on Slaks Answer

 using Excel = Microsoft.Office.Interop.Excel;

...

        class ArbitraryWindow : IWin32Window
        {
            public ArbitraryWindow(IntPtr handle) { Handle = handle; }
            public IntPtr Handle { get; private set; }
        }

        private void button2_Click(object sender, RibbonControlEventArgs e)
        {
            RangeSelectForm newForm = new RangeSelectForm();
            Excel.Application instance = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
            newForm.Show(new ArbitraryWindow(instance.Hwnd));
        }
hughesdan
  • 3,019
  • 12
  • 57
  • 80

1 Answers1

15

You need to create a class that implements IWin32Window and returns Excel's Application.Hwnd property.

For example:

class ArbitraryWindow : IWin32Window {
    public ArbitraryWindow(IntPtr handle) { Handle = handle; }
    public IntPtr Handle { get; private set; }
}

newForm.Show(new ArbitraryWindow(new IntPtr(Something.Application.Hwnd)));
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • I'm getting "Unknown member Application of ExcelAddIn2.Globals" – hughesdan Dec 25 '11 at 21:02
  • I don't know offhand where to find the Excel `Application` instance, but you should have one from the addin. – SLaks Dec 25 '11 at 21:03
  • I found it in Microsoft.Office.Interop.Excel. But after fixing that I'm now getting "Unknown constructor Ribbon1.ArbitraryWindow(int) of ExcelAddIn2.Ribbon1.ArbitraryWindow. See the edit to my question for details. – hughesdan Dec 25 '11 at 21:30
  • You need `new IntPtr(...)`. Edited. – SLaks Dec 25 '11 at 21:32
  • @SLaks: Sorry to disturb you. But do you have any hint for my related question (http://stackoverflow.com/q/20688734/1413641)? No one helped me until yet... – jreichert Jan 03 '14 at 14:30
  • No need to create your own class, use [`NativeWindow`](http://msdn.microsoft.com/en-us/library/system.windows.forms.nativewindow(v=vs.110).aspx). – Mark Ransom Feb 19 '14 at 16:47
  • @MarkRansom: That is far more complicate than what you need here. – SLaks Feb 19 '14 at 17:11
  • @SLaks, how is this complicated? `NativeWindow wnd; wnd.AssignHandle(new IntPtr(app.Hwnd)); newForm.Show(wnd);` – Mark Ransom Feb 19 '14 at 17:17
  • @MarkRansom: Read the source code for that class; it does all sorts of things that you don't need or want. – SLaks Feb 19 '14 at 17:30