.NET Forum / Visual Studio.NET / Extensibility / May 2006
Finding a CommandBar Uniquely
|
|
Thread rating:  |
Rick Strahl (MVP) - 17 May 2006 02:10 GMT Hi all,
I'm still struggling with the problem of trying to retrieve a specific commandbar that is a Context menu. The problem specifically is that there are SEVERAL command bars named "Context" and using:
CommandBars["Context"]
is not likely to return the correct one.
Is there a better way to uniquely identify a Context menu where there's no menu hierarchy to specifically walk down to the correct CommandBar?
There's gotta be SOME way to get a UNIQUE reference to the CommandBar?
Anybody have any ideas?
TIA,
+++ Rick ---
 Signature Rick Strahl West Wind Technologies www.west-wind.com www.west-wind.com/weblog
Carlos J. Quintero [VB MVP] - 17 May 2006 11:14 GMT Hi Rick,
See the answer by Ed Dore [MSFT] in the thread "Enterprise Templates Properties and commandbars problem" in this same newsgroup on April 25. You can retrieve a command bar by GUID/Id instead of by name.
 Signature Best regards,
Carlos J. Quintero
MZ-Tools: Productivity add-ins for Visual Studio You can code, design and document much faster: http://www.mztools.com
> Hi all, > [quoted text clipped - 16 lines] > > +++ Rick --- Rick Strahl (MVP) - 17 May 2006 21:54 GMT Hi Carlos,
Can you be a little more specific? There's a lot of unrelated stuff in that thread.
I'm already using a routine to find the command bar - I know have the right bar in the search routine, but I can't get it to reference that bar in the startup code using either the CommandBar indexer or FindControl. I've tried using the Id of the commandbar but that doesn't work either as the indexer or using FindControl.
You say use the Guid - how do I find the Guid? And then how do I use it to read the CommandBar? Indexer? FindControl?
This doesn't work at all:
ContextBar = bars.FindControl(Missing.Value /*MsoBarType.msoBarTypePopup*/, Missing.Value,"Context",Missing.Value);
and this: ContextBar = bars["Context"]
finds only the first instance which is typically the wrong one.
What is the right way to reference a CommandBar with an ID or Guid and where does the Guid come from (which property - i don't see it on the CommandBar instance. I see an int Id which I've tried with no success using FindControl and also by passing it as the indexer. Both fail.
 Signature Rick Strahl West Wind Technologies www.west-wind.com www.west-wind.com/weblog
> Hi Rick, > [quoted text clipped - 22 lines] >> >> +++ Rick --- Carlos J. Quintero [VB MVP] - 18 May 2006 09:43 GMT Hi Rick,
I was referring to the post where Ed talks about using IVsProfferCommands::FindCommandBar to find a command bar by Guid/Id. The problem is that we don´t know the Guid of that toolbar so you have to either ask some MS tech (maybe Ed can look it for you) or get some document in the SDK that lists the command bar guids (not sure if such thing exists, though). Or maybe the SDK provides a way to get the Guid of a commandbar if you have its name...
 Signature Best regards,
Carlos J. Quintero
MZ-Tools: Productivity add-ins for Visual Studio You can code, design and document much faster: http://www.mztools.com
> Hi Carlos, > [quoted text clipped - 51 lines] >>> >>> +++ Rick --- "Ed Dore [MSFT]" - 19 May 2006 00:19 GMT Hi Rick,
If you can identify the particular context menu you're interested in, I'll see if I can track down the guid:id pair the identifies the commandbar. Note this technique really only works if the commandbar in question was implemented by a package (ala Visual Studio SDK). The guid:id pair that identifies a particular command (or commandbar) it typically defined in the package's embedded command table resource (.CTO file).
This particular problem, of being able to uniquely identify a commandbar from the DTE automation model, is well know to our developers, and they are currently looking into ways to address this in future releases.
Sadly, there is no complete list of guid:id pairs for the hundreds of command and toolbars implemented across the various products integrated into the VS IDE. The .CTC and .H files in the Visual Studio SDK, do contain a good number, but many have not been published, nor likely will be.
So if you have a particular context menu you're interested in, just post here (or the MSDN Extensibility Forum) and we'll try to provide the info for you.
Sincerely, Ed Dore [MSFT]
This post is 'AS IS' with no warranties, and confers no rights.
Rick Strahl (MVP) - 20 May 2006 03:24 GMT Hi Ed,
The menu I'm interested in is the one that pops up in the ASP.NET designer when you are on a table cell. I've got everything else working except this one.
The menu Id (don't know if this helps) is: 33103
On the menu are:
Context 33103 System.__ComObject
Cu&t - 21
Cop&y - 19
&Paste - 22
Past&e Alternate - 746
&Delete - 478
&Style... - 746
&Insert - 32768
De&lete - 32768
&Select - 32768
&Resize - 32768
&Merge Cells - 798
Run As Ser&ver Control - 746
View &Code - 746
View Component Des&igner - 746
View in &Browser - 393219
Edit &Master - 746
Add Co&ntent Page - 10944558
Show Smart Ta&g - 746
WebForms Designer Verbs - 746
Ed&it Template - 32768
E&nd Template Editing - 746
P&roperties - 393246
Assuming you can find this mystical Id <g>, how do I reference then? Through the CommandBars indexer?
I did make this work with a hack for a workaround:
CommandBar contextBar = bars[contextMenuName] as CommandBar;
// *** Get the general Context bar - need to hook that as well
CommandBar designerBar = bars["Context"] as CommandBar;
// *** Get the Cell Context menu
CommandBar cellBar = null;
foreach (CommandBar Bar in bars)
{
if (Bar.Name == "Context" && Bar.Id == 33103)
{
cellBar = Bar;
break;
}
}
That works locally here, but I suspect that the ID isn't actually unique and it probably won't work on other people's machines or locales.
I definitely would like a more reliable and less resource intensive way of doing this.
+++ Rick ---
 Signature Rick Strahl West Wind Technologies www.west-wind.com www.west-wind.com/weblog
> Hi Rick, > [quoted text clipped - 25 lines] > > This post is 'AS IS' with no warranties, and confers no rights. "Ed Dore [MSFT]" - 26 May 2006 19:07 GMT Hi Rick,
I apologize for the late response. Things have been a bit busy around here lately. You're suspicions are correct. There isn't a 100%
guarantee that you're going to get the right context menu in this instance. At least not with the DTE automation interfaces.
As I mentioned in that earlier post Carlos mentioned, the DTE automation model does allow for keying off the CommandBar name, but
those names are not unique. Using the CmdBrowser addin sample from
http://www.microsoft.com/downloads/details.aspx?FamilyId=79C7E038-8768-4E1E- 87AE-5BBBE3886DE8&displaylang=en, and you'll see multiple
commandbars with the same name. This is a known problem that the dev team is working on correcting in some fashion for the next
release. But currently, we're stuck having to find all the CommandBars and then guess which one is the right one based on the
commands it contains. And that isn't necessarily an exact mechanism for retrieving the particular CommandBar you're looking for.
Especially given that people can reconfigure the commandbars.
The context menu you mentioned in your last post is actually implemented by the HTML Editor package and is defined in that package's
embedded .CTO resource with the following guid:id pair:
{D7E8C5E1-BDB8-11D0-9C88-0000F8040A53}:49
The only way to retrieve the menu (aka CommandBar) by way of this unique identifier is with the IVsProfferCommands.FindCommandBar
method. You can retrieve this interface from your addin by way of code similar to the following:
using System; using System.Diagnostics; using System.Runtime.InteropServices;
using Extensibility; using EnvDTE; using EnvDTE80; using Microsoft.VisualStudio.CommandBars;
// note, you need to reference the Microsoft.VisualStudio.OLE.Interop.dll // assembly, which contains the IServiceProvider we need to Query for the // IVsProfferCommands service. using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
namespace GetCmdBar { public class Connect : IDTExtensibility2 { public Connect() { }
public void OnConnection(object app, ext_ConnectMode mode, object inst, ref Array custom) { _applicationObject = (DTE2)app; _addInInstance = (AddIn)inst;
// retrieve IVsProfferComands via DTE's IServiceProvider IOleServiceProvider sp = (IOleServiceProvider)app; Guid guidSvc = new Guid(typeof(IVsProfferCommands).GUID.ToString()); IntPtr service; sp.QueryService(ref guidSvc, ref guidSvc, out service); IVsProfferCommands vsProfferCmds = (IVsProfferCommands)Marshal.GetObjectForIUnknown(service); Marshal.Release(service);
// retrieve the specific command bar we're looking for // (CMDSETID_HtmEdGrp:IDMX_HTM_DESIGN_TABLE) Guid guidCmdGroup = new Guid("{D7E8C5E1-BDB8-11D0-9C88-0000F8040A53}"); uint menuID = 49;
CommandBar cmdBarTableContext = (CommandBar)vsProfferCmds.FindCommandBar(IntPtr.Zero, ref guidCmdGroup, menuID); Debug.WriteLine(cmdBarTableContext.Name); }
public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom) {} public void OnAddInsUpdate(ref Array custom) {} public void OnStartupComplete(ref Array custom) {} public void OnBeginShutdown(ref Array custom) {} private DTE2 _applicationObject; private AddIn _addInInstance; } }
As a side note with respect to identifying the guid:id pair that a package uses to create it's commandbars. Paul Harrington came up
novel way to help identify the guid:id pair by way of the IDE's Export Settings feature. Martin Tracy's recently blogged about this
techinque at http://blogs.msdn.com/martintracy/archive/2006/05/23/604927.aspx. Hopefully, we'll have an even better solution come VS
2005 SP1, and Orcas, by way of a simple logging feature Paul enabled in the core IDE sources a couple weeks back.
Sincerely, Ed Dore [MSFT]
This post is 'AS IS' with no warranties, and confers no rights.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|