How to retrieve a tool window's position in Visual Studio

Viewed 154

In the Visual Studio extension I'm developing, I provide a custom tool window.

I'm trying to find out if the user has the tool window docked to a side (left/right/top/bottom) or if it is floating. Is there a way to calculate the current position of my tool window and is there an event to know after a user has completed moving it?

Some background: I'm developing the CodeStream extension for Visual Studio. There is functionality that when a user selects code we show three circle buttons in the CodeStream tool window (it's actually a webview) to provide some actions. When the CodeStream panel is docked to the right, the 3 buttons are on the left side of the panel and this is correct.

But, if a user moves the CodeStream panel to the left side of screen or elsewhere, I'd like to be able to know that so I can direct our webview to move the 3 buttons to the right side of the screen. I've provided two screenshots below.

We also have a VSCode extension and I've implemented similar logic there.

enter image description here

enter image description here

1 Answers

Take a look at the IVsWindowFrame.GetFramePos method:

using Microsoft.VisualStudio.Shell;
...
ThreadHelper.ThrowIfNotOnUIThread();

if (Package.GetGlobalService(typeof(Interop.IVsUIShell)) is Interop.IVsUIShell shellService)
{
    shellService.GetToolWindowEnum(out var toolWindows);

    foreach (Interop.IVsWindowFrame frame in ComUtilities.EnumerableFrom(toolWindows))
    {
        frame.GetProperty((int)VsFramePropID.DocView, out var docView);
        if (docView?.GetType().FullName == "MyNamespace.MyToolWindow")
        {
            frame.GetFramePos(out var pos, out var guid, out int px, out int py, out int pcx, out int pcy);

            // Do something

            break;
        }
    }
}

I have not explored the usage of the values provided by GetFramePos. The docs say "Returns the position of the window," so presumably they are useful for that purpose.

(There may be a more expedient way to obtain the target Interop.IVsWindowFrame than enumerating all the tool windows as in the above example... that's just what I was doing when I discovered this method.)

Related