[GIS] ArcGIS 10 add-in: Bring dockable window to front

add-inarcgis-10.0arcmaparcobjectswindows

I have an ArcGIS 10 ArcMap add-in written in C# .NET 3.5 that implements an ESRI.ArcGIS.Desktop.AddIns.DockableWindow (which also inherits from UserControl) and an ESRI.ArcGIS.Desktop.AddIns.Tool that when clicked in the map updates the dockable window.

I'd like to bring the dockable window to the front of the Z-order in the Tool's OnMouseDown() method (when in undocked mode). Currently, if the user opens another dockable window, puts it on top of mine, and clicks with the tool, the window updates but it is not brought to the front. I am already calling IDockableWindow.Show(true) to ensure the window is visible after clicking with the tool. I have also tried UserControl.BringToFront() but it does not have any effect.

The best workaround I currently have is to call IDockableWindow.Show(false) followed by IDockableWindow.Show(true), however this not ideal as it is jarring to have the window disappear and reappear, as well as have to fully repaint which takes a substantial amount of time.

The built-in Identify window does not have this issue and is brought to the top each time the Identify tool is used, so clearly there is a way to do it.

Does anyone know of a better solution to this? Thanks!

Edit: Here is the code I ended up using to resolve this. Thanks Kirk and Petr!

public static void BringDockableWindowToFront(IDockableWindow dockableWindow, IntPtr dockableWindowControlHandle)
/// <summary>
/// Workaround for bringing a dockable window to the top of the Z order.
/// dockableWindowControlHandle is the Handle property of the UserControl implemented by the dockable window
/// </summary>
{
    IWindowPosition windowPos = dockableWindow as IWindowPosition;
    IntPtr parentHwnd = GetParent(dockableWindowControlHandle); // Get parent window handle
    switch (windowPos.State)
    {
        case esriWindowState.esriWSFloating:
            IntPtr grandParentHwnd = GetParent(parentHwnd); // Get grandparent window handle
            SetActiveWindow(grandParentHwnd);  // Activate grandparent window when in floating (undocked) mode
            break;
        //case esriWindowState.esriWSMaximize: // Mode not yet implemented in ArcGIS 10, check at 10.1
        //case esriWindowState.esriWSMinimize: // Mode not yet implemented in ArcGIS 10, check at 10.1
        case esriWindowState.esriWSNormal:
            SetActiveWindow(parentHwnd); // Activate parent window when in normal (docked) mode
            break;
    }
    SetFocus(dockableWindowControlHandle); // Set keyboard focus to the dockable window
}

// Retrieves a handle to the specified window's parent or owner.
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetParent(IntPtr hWnd);

// Sets the keyboard focus to the specified window.
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr SetFocus(IntPtr hWnd);

// Activates a window.
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr SetActiveWindow(IntPtr hWnd);

Best Answer

Try using the SetWindowPos winapi call with the hWnd of the dockable window control (or maybe it's parent or grandparent container control) with the HWND_TOP flag.

Related Question