I have an WPF User control, let's say UCInner, which contains a WPF Popup. UCInner is used in another WPF user control, let's say UCOuter.
UCOuter is embedded in an ElementHost (ElementHost.Child = UCOuter).
Finally UCOuter is embedded within an Outlook VSTO custom task pane ahd this latter used in a winforms application (Outlook VSTO Add-in).
So from the most inner WPF Control, UCInner, I would like to obtain the parent Window. I have tried some alternatives with no success, I am always getting null or exceptions:
Window w = Window.GetWindow(myPopup);
Window w = Window.GetWindow(UCInner);
I also have tried what explained here and also this one.
- UPDATED - ANOTHER ATTEMPT:
I have tried below piece of code and i can get successfully the window handle, but now from the handle I need to get the Window Object.
dynamic activeWindow = Globals.ThisAddIn.Application.ActiveWindow();
Microsoft.VisualStudio.OLE.Interop.IOleWindow win = activeWindow as Microsoft.VisualStudio.OLE.Interop.IOleWindow;
IntPtr handle;
win.GetWindow(out handle);
So in order to get the Window object I have tried this based on the Window handle:
System.Windows.Interop.HwndSource hwndSource = System.Windows.Interop.HwndSource.FromHwnd(handle);
Window w = hwndSource.RootVisual as Window;
but this does not work, hwndSource is null.
CodePudding user response:
First, you need to retrieve the parent window handle, in case of Explorer window in Outlook you can use:
Outlook.Explorer explorer = OutlookApplication.ActiveExplorer();
IOleWindow oleWindow = explorer as IOleWindow;
IntPtr handle = IntPtr.Zero;
oleWindow.GetWindow(out handle);
if (handle != IntPtr.Zero)
{
WindowInteropHelper helper = new WindowInteropHelper(DialogWindow);
helper.Owner = handle;
DialogWindow.ShowInTaskbar = false;
DialogWindow.ShowDialog();
}
where IOleWindow
can be defined in the following way:
/// <summary>
/// Implemented and used by containers and objects to obtain window handles
/// and manage context-sensitive help.
/// </summary>
/// <remarks>
/// The IOleWindow interface provides methods that allow an application to obtain
/// the handle to the various windows that participate in in-place activation,
/// and also to enter and exit context-sensitive help mode.
/// </remarks>
[ComImport]
[Guid("00000114-0000-0000-C000-000000000046")]
[InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleWindow
{
/// <summary>
/// Returns the window handle to one of the windows participating in in-place activation
/// (frame, document, parent, or in-place object window).
/// </summary>
/// <param name="phwnd">Pointer to where to return the window handle.</param>
void GetWindow (out IntPtr phwnd) ;
/// <summary>
/// Determines whether context-sensitive help mode should be entered during an
/// in-place activation session.
/// </summary>
/// <param name="fEnterMode"><c>true</c> if help mode should be entered;
/// <c>false</c> if it should be exited.</param>
void ContextSensitiveHelp ([In, MarshalAs(UnmanagedType.Bool)] bool fEnterMode) ;
}
CodePudding user response:
If you need to figure out the right parent window to display your own WPF window, cast Application.ActiveWindow
to IOleWindow
(Application.ActiveWindow
can return either Explorer
or Inspector
, they both support IOleWindow
) and call IOleWindow.GetWindow
. Once you have the HWND
, create an instance of the WindowInteropHelper class and specify the Outlook window handle as the parent:
if (outlookHwnd != IntPtr.Zero)
{
WindowInteropHelper helper = new WindowInteropHelper(YourDialogWindow);
helper.Owner = outlookHwnd;
YourDialogWindow.ShowInTaskbar = false;
}