Search code examples
c#.netoutlook-addin

How to keep a dialog on top of application


I'm currently working on a little outlook-addin. My plugin opens a dialog (System.Windows.Forms.Form).

I'd like to keep the dialog on top of outlook, so I tried the TopMost, but that keeps the dialog on top of all applications.

I'd like the dialog to be on top when outlook is the active application, how can I achieve this?

UPDATE

Thanks to Dmitry and kallocain I could solve this issue. I want to outline my resulting solution:

In the TabCalendarRibbon class of my Outlook plugin I have an event method for activating my dialog, there I used the code from kallocain to get the window handle:

Explorer explorer = Context as Explorer;
IntPtr explorerHandle = (IntPtr)0;

if (explorer != null)
{
    IOleWindow window = explorer as IOleWindow;
    if (window != null)
    {
        window.GetWindow(out explorerHandle);
    }
}

As described in kollacains answer, I had to add the OLE interop assembly. I used the explorer handle to Show my dialog:

var dlg = new NewEntryDialog();
dlg.Show(new WindowWrapper(explorerHandle));

As you might notice, I could not use the window handle directly but had to implement a tiny wrapper that implements IWin32Window. For this I followed a description I found via the previous answer Dmitry linked to. I simply copied the following code:

public class WindowWrapper : System.Windows.Forms.IWin32Window
{
    public WindowWrapper(IntPtr handle)
    {
        _hwnd = handle;
    }

    public IntPtr Handle
    {
        get { return _hwnd; }
    }

    private IntPtr _hwnd;
}

And voila, it works pretty much as I expected. It would be even better if the dialog was only active as long as I am on the calendar ribbon, but that is something for another day. BTW, pretty much code for the result, I think...


Solution

  • As Akrem noted, see How to make form topmost to the application only?. To get the HWND of an Outlook explorer object (e.g. Application.ActiveExplorer), cast it to IOleWindow and call IOleWindow.GetWindow().