Tuesday, March 18, 2003 11:46 PM Shawn A. Van Ness

Programmatically Adding a UserControl to the VS.NET ToolBox

I've been tasked with writing a custom install-action, to add a few user controls to the VS.NET toolbox.  "No problem", I said.

Word? Schmurd. This VS.NET ToolBox can o' worms has turned out to be a new low in application-integration migraine severity...


There exists an innocent little API function, ToolBoxItems.Add(), in the EnvDTE assembly.  Of course, its documentation is a masterpiece of misinformation...

I Google'd long and hard, and all I could scrape up was anecdotal evidence from various folks that it was possible -- somehow -- I just had to work around a few quirks.  What those quirks were, exactly, and how to workaround them...?  Not much consistent info to go on.

All I knew for sure was that calling ToolBoxItems.Add, with every reasonable combination of typename and assemblyname for parameters, didn't work.

Some folks said I have to index the tabs by number (what?), some folks said I have to load a Solution file first (yikes!), and some folks said I have to display the Properties window first...  Unlikely as it sounds, that latter suggestion (plus or minus a few other non-intuitive stumbling blocks) turned out to be the case!

Think: EnvDTE.DTE.ExecuteCommand("View.PropertiesWindow");

There is clearly a very deep-running bug in VS.NET, regarding this Properties window.  I've noticed it flashing briefly into existance, quite often, even when I have it hidden -- I somehow suspect that this "workaround" is well-known within the halls of Building 40. Grrr...  Hopefully this is fixed in Everett, but of course I can't afford to care about that.

So, without further ado, here is the magic sequence to add InkPicture and InkEdit, from the Microsoft Tablet PC SDK, onto the VS.NET Toolbox.  This code can be run from any standalone app -- it does not need to be run from within an addin.  (In fact, all instances of VS should be closed.)  Hope this helps somebody...

        private static void AddToolBoxTab(EnvDTE.DTE env)
        {
            // First, ensure Tablet SDK is installed -- get location of Microsoft.Ink.dll
            string fullpathToMicrosoftInk = LookupMicrosoftInkAssemblyFilename();

            // Prepare to munge the toolbox -- get toolbox window, object, and tabs collection
            EnvDTE.Window toolboxWindow = env.Windows.Item(EnvDTE.Constants.vsWindowKindToolbox);
            EnvDTE.ToolBox toolbox = (EnvDTE.ToolBox)toolboxWindow.Object;
            EnvDTE.ToolBoxTabs toolboxTabs = toolbox.ToolBoxTabs;

            // Careful to check if our tab already exists
            foreach (EnvDTE.ToolBoxTab tab in toolboxTabs)
            {
                if (tab.Name == TabName)
                    return;
            }

            // No, so add it
            EnvDTE.ToolBoxTab newtab = toolboxTabs.Add(TabName);

            // WinBug: gotta show the Properties window, first (this cost me ~1 day of my life)
            env.ExecuteCommand("View.PropertiesWindow""");

            // WinBug2: gotta activate the tab and select the first item (grr...)
            newtab.Activate();
            newtab.ToolBoxItems.Item(1).Select();

            // Finally: add the Microsoft Ink controls
            newtab.ToolBoxItems.Add( 
                @"Unused?"
                fullpathToMicrosoftInk, 
                EnvDTE.vsToolBoxItemFormat.vsToolBoxItemFormatDotNETComponent
                );
        }

        private static string LookupMicrosoftInkAssemblyFilename()
        {
            Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.LocalMachine;
            rk = rk.OpenSubKey(KeyName, false);

            if (rk == null)
                throw new ArgumentException(String.Format("Could not find registry key:\n[HKLM\\{0}]",KeyName));

            string fullpathToAssembly = (string)rk.GetValue(null);
            fullpathToAssembly += @"\Microsoft.Ink.dll";

            if (!System.IO.File.Exists(fullpathToAssembly))
                throw new System.IO.FileNotFoundException("File not found", fullpathToAssembly);

            return fullpathToAssembly;
        }

 

Comments

# Revenge of the Toolbox: VS 2003 : Shawn A. Van Ness's Blog

Wednesday, March 19, 2003 2:46 AM by TrackBack

Revenge of the Toolbox: VS 2003 : Shawn A. Van Ness's Blog

# Programmatically Adding a UserControl to the VS.NET ToolBox : Sam Gentile's Blog

Wednesday, March 19, 2003 2:46 AM by TrackBack

Programmatically Adding a UserControl to the VS.NET ToolBox : Sam Gentile's Blog

# re: Programmatically Adding a UserControl to the VS.NET ToolBox

Sunday, April 27, 2003 3:28 PM by Kant

What's the "KeyName" points to in the LookupMicrosoftInkAssemblyFilename()?

# re: Programmatically Adding a UserControl to the VS.NET ToolBox

Sunday, April 27, 2003 3:46 PM by Shawn A. Van Ness

Oops, sorry -- clipboard fumble.

private const string TabName = @"Tablet PC";
private const string KeyName = @"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\Tablet PC Assemblies";

# re: Programmatically Adding a UserControl to the VS.NET ToolBox

Tuesday, September 09, 2003 9:15 AM by Vassil Atanasov

How do you get the EnvDTE.DTE object in custom install action?

# re: Programmatically Adding a UserControl to the VS.NET ToolBox

Tuesday, September 09, 2003 10:19 AM by Shawn A. Van Ness

You can just instantiate it, via its default constructor... but that's probably not what you want -- it'll try to wrap the v7.0 CLSID!

Here's the rest of the saga...
http://weblogs.asp.net/savanness/posts/5352.aspx
http://weblogs.asp.net/savanness/posts/5701.aspx
http://weblogs.asp.net/savanness/posts/6012.aspx

# re: Programmatically Adding a UserControl to the VS.NET ToolBox

Sunday, March 07, 2004 6:02 AM by Roger Johansson

Hi,
i have this working with vs.net 2002 , but i want to add the same components to vs.net 2003 also.

(my code is almost identical to the one you have here above)

# re: Programmatically Adding a UserControl to the VS.NET ToolBox

Wednesday, May 19, 2004 5:40 AM by Gian

Can you tell me some MSDN sources where I can find informations on the so called "WinBugs"?
Thanks

# re: How do I manipulate ToolBox Items?

Wednesday, June 23, 2004 3:09 PM by TrackBack

# re: Toolbox Stupidity - Visual Studio 2003

Monday, July 12, 2004 5:19 AM by TrackBack