VSIX: Adding a Menu Item to the Visual Studio Editor Context Menu - visual-studio

I have an internal extension I'd like to add to Visual Studio that should hook up to the Editor Context menu - regardless of what type of file is open. I can handle enabling/visibility dynamically but essentially I'd like it to be accessible on any type of editor file.
I've not been able to find the right parent command/group ids to manage to get a custom button to display on the editor context menu. I suspect there's not a single Id but several but any guidance on what I should be looking at. Having a hard time figuring out what the proper parent command Id is to hook up to the editor context menu.
Specifically I need to be able to add View in Browser option to files that Visual Studio doesn't recognize as HTML/Web files (even though they are mapped to the appropriate editors).
Related: Is there anyway to reasonable way to discover the menu command and group names? Poking around in the SharedCommandPlace.vsct is as close as I've come but even that is proving to be very difficult to match to actual menu items.

I was able to figure out the right command groups for the context menu. It turns out the various editors all use separate context ids and so have to be managed as separate menus so this gets messy quick.
Steps
I used the HKEY_CURRENT_USER\SOFTWARE\Microsoft\VisualStudio\14.0\General key and EnableVSIPLogging value of 1 to enable logging.
I then navigated into the editor and with the mouse on an empty area press CTRL-SHIFT and then right click the mouse
This gives the info a menu group like and it looks like this:
---------------------------
VSDebug Message
---------------------------
Menu data:
Guid = {D7E8C5E1-BDB8-11D0-9C88-0000F8040A53}
GuidID = 358
CmdID = 53
Type = 0x00000400
Flags = 0x00000000
NameLoc = ASPX Context
---------------------------
OK
---------------------------
The important values are the GUID and the CommandID.
Add the Guid and Command ID under Symbols like this to register the command set mapping the Guid to the CommandSet and the CommandId to the context menu values:
<GuidSymbol name="aspxContextCommandSet" value="{D7E8C5E1-BDB8-11D0-9C88-0000F8040A53}">
<IDSymbol name="aspxContextMenu" value="0x0035"/>
</GuidSymbol>
Note that the value maps to the CommandID represented as a hex value.
Then reference this group as a parent for your command group (MyMenuGroup) in the Groups section:
<Group guid="guidViewInBrowserPackageCmdSet" id="MyMenuGroup" priority="0x0000">
<Parent guid="aspxContextCommandSet" id="aspxContextMenu"/>
</Group>
You reference the menu group you create for you command buttons and point at the context menu created in the previous step.
If you want to do this for multiple editors (ie. the ASPX, HTML, and Code editors for example as I do) you repeat this process for each of your editors by adding both the GuidSymbol and the Group.You'll end up with multiple Group entries for the same MenuGroup point at a different parent and all will activate appropriately.
Works great, but you'll probably have to make sure you filter your OleMenuCommand objects with a BeforeQueryStatus event handler to ensure the menu shows only when you actually can handle.

I needed the same thing and I used:
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_CODEWIN"/>
So, I just changed the id. See: https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.shell.vsmenus.idm_vs_ctxt_codewin.aspx

The EnableVSIPLogging registry value still works for VS 2015. You just need to add an EnableVSIPLogging DWORD set to 1, under HKEY_CURRENT_USER\SOFTWARE\Microsoft\VisualStudio\14.0\General.
If the CTRL+SHIFT + menu popup or menu select, doesn't result in that dialog, chances are the menu item in question is not implemented as a VSCT resource.
That being said, you may need to experiment a little, as editor and designers are not required to use the same context menu that the code editor uses.
Also, you might want to try out Mads "Extensibility Tools" extension at https://visualstudiogallery.msdn.microsoft.com/ab39a092-1343-46e2-b0f1-6a3f91155aa6 (2017) or https://marketplace.visualstudio.com/items?itemName=MadsKristensen.ExtensibilityEssentials2019 (2019).
He's added a nice autocomplete for VSCT files that's pretty useful.

Related

How to get the hot item name and path from Explorer?

It was easy when the Windows' explorer was using a SysListView32 control for displaying its files list as opposed to the DirectUIHWND control in the subsequent versions of Windows after XP.
A simple task such as obtaining the 'hot item' which is that item (a filename) the mouse hovers above for some hundreds of milliseconds, where before I could use the macros
ListView_GetHotItem with ListView_GetItemText and be able to obtain the filename under the mouse cursor.
This simple task becomes almost impossible to do with the DirectUIHWND window unless I revert this control back to a
SysListView32 which I have seen being proposed as the only solution on the many sites I have searched, and even if used the change does not occur immediately but only after I navigate out of the folder first.
It has taken me almost 2 years trying to find a solution to this and until now I feel stumped.
Anyone any idea please ?
Basically I have subclassed the parent of the tooltip and intercepted the tooltip notifications and all I need is the filename and the full path of the item the mouse hoovers above it, the hot item.
https://learn.microsoft.com/en-us/archive/msdn-magazine/2000/march/windows-2000-ui-innovations-enhance-your-user-s-experience-with-new-infotip-and-icon-overlay-shell-extensions
IQueryInfo is required to provide the runtime text to the shell. IPersistFile is used by Explorer to let the extension know about the specific file currently under the mouse pointer.

Certain key equivalents cannot be used for NSMenuItem

I have an NSMenuItem for which I would like to use the key equivalent Command-Option-C. However, when I set the key equivalent in IB, it does not get associated with the menu item when the app is actually run. The entry has no visible key equivalent, and that command does not invoke the item. Other key equivalents, like Shift-Control-C, do indeed work. The one I am trying to use does not conflict with any other key equivalent in the app.
What could be causing this seemingly random problem?
Command-Option-C works just fine here. Could it be that you have a custom keyboard shortcut set up in the keyboard system preferences that uses the same key combination? That would override the application's own shortcuts.
Is it possible the menu item in question is a "special" menu item which may be getting substituted at launch-time by the system? If so, it would be helpful to know whether you are able to set the same keyboard shortcut on a different, perhaps less interesting menu item.
I don't really have an authoritative understanding of which menu items may get this kind of treatment, but have a suspicion for example that maybe the "Help" menu, "Application" menu, or others that are common across many apps get tweaked or even regenerated dynamically, altering what you specified in the nib.
The easiest workaround I would shoot for first is to call setKeyEquvialent: directly on the menu time from code, after the nib has loaded. I couldn't tell from your Twitter summary if you had already tried this, and it also failed.
Check the tag on your menu item. If set to certain values it might Cocoa to override stuff
Check your system Prefs aren't overriding key bindings
Check the key binding doesn't already exist elsewhere in the menu hierarchy, especially in the edit menu

Get Context Menu text of specific TaskBar button

I've got some code that grabs the TaskBar buttons and their text from the windows TaskBar using User32.SendMessage with the TB_GETBUTTON message to retrieve a TBBUTTON structure (Win32 API via C# P/Invokes). But I'm trying to figure out how to then, once I have the handle to the button, grab the associated context menu text. There is some status information on there for a specific application that I would like to retrieve. The button text gets me some of it, but I need to the context menu text to complete it.
Any ideas?
This is not completely clear... Context menus don't have text, as such - they have menu items, each one of which will have text. By "context menu text", do you mean the text of the menu items in the taskbar button's popup/context menu? For example, "Restore", "Minimize" etc in the screenshot below?
If so, I suspect you're going about this the wrong way:
This menu doesn't belong to the button, but is the system menu of the window represented by the taskbar button. If the button has a context menu, this is probably for a grouped collection of windows, not one specific window (or even windows for one process.)
Making judgements based on the context menu of a window sounds like a dodgy approach to me, especially based on text since that will change depending on where in the world your user is located. Applications can also change the contents of this menu so there's no guarantee it will contain something you expect to be there. It would be better to check the window style, if it's minimized, etc, to find out the information that also affects the contents of the menu.
I'm going to answer this based on what your needs seem to be from the question, not what you've directly asked, since (a) it's not possible as asked and (b) I think you're trying to do something else. (As a general guideline, in a question it's good to state why you're trying to do something - and even maybe ask about that, ie 'how do I achieve X' - in case there's a better method than the one you're using. Here, X is probably 'find out information about this window' not 'get the text of the context menu', because that's probably only one possible method to get to X.) Also I think extracting data from the internals of a third-party application like Explorer (the taskbar is an Explorer window) is fragile and prone to break in future versions of Windows.
The system menu or window information (whichever one) belongs to application windows. Unless taskbar buttons are grouped (and then it's the subitems) one taskbar button corresponds to one specific window in the system. So what you want to do is find these windows. You do this by:
Using the EnumWindows function
Then for each window that is passed to the callback, checking the extended window style using GetWindowLong with GWL_EXSTYLE to see if the WS_EX_APPWINDOW bit is set
In addition, sometimes other windows are shown: these heuristics should help.
Each one of these windows is a window that should appear on the taskbar, Alt-Tab dialog, etc.
You say you're getting the text of the taskbar button - this is probably the window caption of the window, and GetWindowText is the canonical (read: probably a lot more reliable) way to get the caption of a window belonging to another process.
If you really want the popup menu, then:
Use GetSystemMenu to retrieve the handle for the system menu for the window. Applications can customise this, so if your app is doing this (and that's why you want the popup menu) ensure you pass false to the bRevert parameter
You can then get the number of menu items using GetMenuItemCount and for each one call GetMenuItemInfo to get info about each menu item. Pass true to the fByPosition parameter to indicate you're accessing the menus by position (since you know the count, you're getting item 0, 1, 2... count-1).
This fills a MENUITEMINFO structure, which (I think, I haven't ever had to code this so I haven't tested) will tell you the text associated with an item via the dwTypeData field "if the MIIM_STRING flag is set in the fMask member".
If you really want information about the window status, you can get this information using methods like IsIconic to see if it's minimized, GetWindowLong again to get other information, etc. I'd suggest you ask another SO question about how to get whatever specific information about a window for details.
Hope that helps!

How to maintain focus on menu after clicking a menu command

Simple version
Is there any way to maintain focus on menu after clicking a menu command?
Detailed version
Specifically, I've made a menu with some menu item with checked property. The problem is that each time I click checked menu item the menu lose its focus. It can be pretty annoying when there is a number of menu item with checked property and I want to manipulate them at once.
The most elegant solution for the problem would be maintaining focus on menu, but I can't find a way to apply it. Is it possible? And if so, what's the way to do that?
Even if there would a solution for it, sooner or later you will enter a situation in which a numerical or string property is changed via the menu, and then it becomes even impossible to keep the focus on the menu (while the dialog requesting the number or string is on the screen).
The first, simple alternative would be to put the checkable menu items on a toolbar or ribbon (just like Word does with Bold, Italic, Underline, ...). Numerical/string properties can then also be added on the toolbar or ribbon.
A second alternative could be to have a more complete configuration dialog in which the user can change all the configuration items. The configuration dialog can co-exist with the current checkable items, so users simply changing one check and users changing many properties all get a quick way of doing what they want.
You might also pose this question on https://ux.stackexchange.com/ (this sibling site is more oriented towards good user interface practices).

Visual Studio Immediate window: how to see more than the first 100 items

I am trying to see the properties of an object with over 300 properties in the Immediate Window of Visual Studio 2005. Only the first 100 items are displayed, followed by this caption:
< More... (The first 100 of 306 items were displayed.) >
I am trying to see the rest of the items, but can't figure it out.
I realize that I could see these in a Watch window, but that's not the same.
Sometimes its useful to see the list in the immediate window rather than looking in the watch window. You can easily see more results than the first 100 by using:
yourList.Skip(100).ToArray()
Which really doesn't take long to write and works well - was useful for me.
Update: As pointed out in the comments below, this answer is actually wrong and applicable ONLY to collections and NOT to objects with lots of properties. I'm leaving it here as lots of people seem to have found it useful.
If you add your object to the watch window, then expand the properties so that all are displayed. Then Ctrl+A and Copy. You can then paste in excel to get an organized list of properties and their values.
The immediate window was designed to be a quick view tool. If you want to see more detail, you will have to view it in either the Watch Window or the Quick Watch Window.
Another option is to write a Visual Studio AddIn that operates similarly to the Immediate Window, but has more options.
I always create an extension method to export objects to xml when debugging like this. It's very useful for troubleshooting object data. Here is what I use:
public static void SerializeToXML(this object entity)
{
System.Xml.Serialization.XmlSerializer writer = new System.Xml.Serialization.XmlSerializer(entity.GetType());
System.IO.StreamWriter file = new System.IO.StreamWriter(string.Format(#"{0}\{1}.xml", Directory.GetCurrentDirectory(), entity.GetType().Name));
writer.Serialize(file, entity);
file.Close();
}
It's not 100% full proof, but most of the time it is perfect. It will create an xml file in the application directory with the objects name as the file name. In the immediate window you can just type the object name then .SerializeToXML().
so: myList.SerializeToXML()
Its an old question but to get the properties and values of an object during runtime a more reasonable solution with Quickwatch window is here:
Open Quickwatch during Debug mode
Type in your Variablename and press Enter
Press CTRL + A and CTRL + C in order to select and copy all Properties. You need to expand those which contains values and are non primitive types.
Paste to your favorite editor.

Resources