Dotneteers.net
All for .net, .net for all!

LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup

After publishing LearnVSXNow! Part #41 – Toolbar Layout and Persistence I got a letter from Laurie:

I am working on an isolated shell app, and already have a working tool window pane and toolbar (and am using VSXtra). I'm trying to change the visibility of the toolbar so it is visible by default, as soon as the IDE launches, just like the Standard toolbar. Right now, after installing and launching the IDE, the user has to right click on the toolbars and turn on the new toolbar.  I've looked through your posts on this, as well as other sources, but I haven't seen any documentation that says how to turn a toolbar on by default. Can you help?

To be honest, I have never tried to create a toolbar and set it visible initially. First I thought that maybe I can influence the toolbar’s initial visibility through a CommandFlag attribute in the command table (.vsct) file, but I have not found such an attribute.

My second workaround was to create a package that automatically loads at Visual Studio startup time and that package sets the toolbar visible. This second solution worked, so I share the code—and experience—with you.

I have created a simple package with one menu command using the VSPackage wizard and then changed it so that the simple command has been moved to a toolbar. The structure of the .vsct file is the following:

<?xml version="1.0" encoding="utf-8"?>

<CommandTable

  xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable"

  xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <Extern href="stdidcmd.h"/>

  <Extern href="vsshlids.h"/>

  <Extern href="msobtnid.h"/>

  <Commands package="guidShowInitialToolbarPkg">

    <Menus>

      <Menu guid="guidShowInitialToolbarCmdSet" id="MyToolbar" priority="0x100"

        type="Toolbar">

        <Parent guid="guidShowInitialToolbarCmdSet" id="MyToolbar" />

        <CommandFlag>DefaultDocked</CommandFlag>

        <Strings>

          <ButtonText>Sample Startup Toolbar</ButtonText>

        </Strings>

      </Menu>

    </Menus>

 

    <Groups>

      <Group guid="guidShowInitialToolbarCmdSet" id="MyMenuGroup"

        priority="0x0600">

        <Parent guid="guidShowInitialToolbarCmdSet" id="MyToolbar"/>

      </Group>

    </Groups>

   

    <Buttons>

      <Button guid="guidShowInitialToolbarCmdSet" id="cmdidMyCommand"

        priority="0x0100" type="Button">

        <Parent guid="guidShowInitialToolbarCmdSet" id="MyMenuGroup" />

        <Icon guid="guidOfficeIcon" id="msotcidClock" />

        <Strings>

          <CommandName>cmdidMyCommand</CommandName>

          <ButtonText>My Command name</ButtonText>

        </Strings>

      </Button>

    </Buttons>

  

  </Commands>

 

  <Symbols>

    <GuidSymbol name="guidShowInitialToolbarPkg"

      value="{3f005b1f-cdea-4287-8545-6606a2965136}" />

    <GuidSymbol name="guidShowInitialToolbarCmdSet"

      value="{91489787-3361-4715-bb3a-76dbd86353dc}">

      <IDSymbol name="MyMenuGroup" value="0x1020" />

      <IDSymbol name="MyToolbar" value="0x1021" />

      <IDSymbol name="cmdidMyCommand" value="0x0100" />

    </GuidSymbol>

  </Symbols>

 

</CommandTable>

I added the DefaultDocked command flag to the toolbar (it has the name “Sample Startup Toolbar”) so that it would be docked at the top of the VS window. In the next step I updated the package class:

using System;

using System.Diagnostics;

using System.Globalization;

using System.Runtime.InteropServices;

using System.ComponentModel.Design;

using EnvDTE;

using EnvDTE80;

using Microsoft.VisualStudio;

using Microsoft.VisualStudio.CommandBars;

using Microsoft.VisualStudio.Shell.Interop;

using Microsoft.VisualStudio.Shell;

 

namespace DeepDiver.ShowInitialToolbar

{

  [PackageRegistration(UseManagedResourcesOnly = true)]

  [DefaultRegistryRoot("Software\\Microsoft\\VisualStudio\\9.0")]

  [InstalledProductRegistration(false, "#110", "#112", "1.0",

    IconResourceID = 400)]

  [ProvideLoadKey("Standard", "1.0", "ShowInitialToolbar", "DeepDiver", 1)]

  [ProvideMenuResource(1000, 1)]

  [Guid(GuidList.guidShowInitialToolbarPkgString)]

  [ProvideAutoLoad("ADFC4E64-0397-11D1-9F4E-00A0C911004F")]

  public sealed class ShowInitialToolbarPackage : Package, IVsShellPropertyEvents

  {

    private uint _EventSinkCookie;

    protected override void Initialize()

    {

      base.Initialize();

 

      // --- Create command bindings

      var mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;

      if (null != mcs)

      {

        var menuCommandID = new CommandID(GuidList.guidShowInitialToolbarCmdSet,

          (int)PkgCmdIDList.cmdidMyCommand);

        var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);

        mcs.AddCommand(menuItem);

      }

 

      // -- Set an event listener for shell property changes

      var shellService = GetService(typeof(SVsShell)) as IVsShell;

      if (shellService != null)

      {

        ErrorHandler.ThrowOnFailure(shellService.

          AdviseShellPropertyChanges(this, out _EventSinkCookie));

      }

    }

 

    private void MenuItemCallback(object sender, EventArgs e)

    {

      // --- Show a Message Box to prove we were here

      IVsUIShell uiShell = (IVsUIShell)GetService(typeof(SVsUIShell));

      Guid clsid = Guid.Empty;

      int result;

      ErrorHandler.ThrowOnFailure(uiShell.ShowMessageBox(

                 0,

                 ref clsid,

                 "ShowInitialToolbar",

                 string.Format(CultureInfo.CurrentCulture,

                   "Inside {0}.MenuItemCallback()", this.ToString()),

                 string.Empty,

                 0,

                 OLEMSGBUTTON.OLEMSGBUTTON_OK,

                 OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,

                 OLEMSGICON.OLEMSGICON_INFO,

                 0,        // false

                 out result));

    }

 

    public int OnShellPropertyChange(int propid, object propValue)

    {

      // --- We handle the event if zombie state changes from true to false

      if ((int)__VSSPROPID.VSSPROPID_Zombie == propid)

      {

        if ((bool)propValue == false)

        {

          // --- Show the commandbar

          var dte = GetService(typeof(DTE)) as DTE2;

          var cbs = ((CommandBars)dte.CommandBars);

          CommandBar cb = cbs["Sample Startup Toolbar"];

          cb.Visible = true;

 

          // --- Unsubscribe from events

          var shellService = GetService(typeof(SVsShell)) as IVsShell;

          if (shellService != null)

          {

            ErrorHandler.ThrowOnFailure(shellService.

              UnadviseShellPropertyChanges(_EventSinkCookie));

          }

          _EventSinkCookie = 0;

        }

      }

      return VSConstants.S_OK;

    }

  }

}

The package is decorated with the ProvideAutoLoad attribute using the NoSolution UI context GUID in order to load automatically. The command bar is set visible through the automation objects (DTE) and could be set visible in the Initialize method. However, there is a design “feature” in package initialization: while the Initialize method runs for an automatically loaded package, the Shell initialization may have not been completed. Asking for a DTE object with the GetService method could result (and not just could, but does) in a null service instance. To solve this situation, we subscribe for the property changes of the Shell and watch the event when the VSSPROPID_Zombie property value changes from true to false, indicating that the Shell gets fully functional.

This is done in the OnShellPropertyChange method. The highlighted lines are the ones which display the toolbar.

I am not sure this is the best (or much easier) solution for this issue. If you have other working ideas, please, share it with me.

 


Posted Feb 03 2009, 03:18 PM by inovak
Filed under: ,

Comments

Sergey Vlasov wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Sat, Jun 19 2010 10:06

Another solution is to use VisibilityConstraints:

 <VisibilityConstraints>

   <VisibilityItem guid="guidShowInitialToolbarCmdSet" id="MyToolbar" context="UICONTEXT_NoSolution" />

...

Found it at social.msdn.microsoft.com/.../3e305bd3-7e66-4a55-8f44-a3a371d18fcf

Youbi Katsu wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Thu, Apr 26 2012 13:05

The VisibilityConstraints really works! Thanks for the suggestion.

buy imitrex online wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Fri, Feb 15 2013 20:29

UBjLoF Fantastic blog post.Thanks Again. Really Great.

logo designer wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Sat, Feb 16 2013 23:56

Hey, thanks for the blog article.Thanks Again. Want more.

buy Imitrex online wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Sun, Feb 17 2013 23:19

Hey, thanks for the blog post.Much thanks again. Keep writing.

buy Cialis online wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Sun, Feb 17 2013 23:27

This is one awesome post.

buy stendra cheap online wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Mon, Feb 18 2013 1:33

Thank you for your blog.Really looking forward to read more. Much obliged.

buy clomid wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Tue, Feb 19 2013 2:01

Thanks for the post.Much thanks again.

weight loss pills wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Wed, Feb 20 2013 22:20

Great, thanks for sharing this blog.Thanks Again. Will read on...

High Blood Pressure Diet wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Tue, Feb 26 2013 23:54

I really enjoy the article.Really looking forward to read more. Great.

clomiphene 25 mg wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Wed, Feb 27 2013 15:29

qt8Ad1 Wow, great blog post.Really thank you! Really Cool.

manchester escorts wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Thu, Feb 28 2013 11:39

Really informative article.Really looking forward to read more. Great.

improve conversion rate wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Thu, Feb 28 2013 13:14

I think this is a real great post.Thanks Again.

reading games wrote re: LVN! Sidebar #7 - Showing a toolbar at Visual Studio startup
on Thu, Feb 28 2013 13:44

Really informative post.Really thank you!

Load a ToolWindow at VSShell Startup | SixPairs wrote Load a ToolWindow at VSShell Startup | SixPairs
on Fri, Aug 23 2013 13:51

Pingback from  Load a ToolWindow at VSShell Startup | SixPairs