I need my app to create right-click context menu items (and sub-menu items). I'm not concerned with the code - but I don't know how to make sub-menu items in the registry. It's not as logical as one would expect.
I've searched countless times already and have officially given up searching for now.
I know that we can create a context menu item using regedit.exe by going to the shell key and adding a new one but how do I create sub menu items like 7zip for example?
Take a look at this Code-Project article: Add a context menu to the Windows Explorer. It seems to be very easy by using the Registry class provided by the .net framework.
Some more advanced/better solution seems to be using some library such as: SharpShell
EDIT
Please take a look at: .NET Shell Extensions - Adding submenus to Shell .
Ths part should solve your problem:
// <summary>
// Creates the context menu when the selected item is a folder.
// </summary>
protected void MenuDirectory()
{
ToolStripMenuItem MainMenu;
MainMenu = new ToolStripMenuItem
{
Text = "MenuDirectory",
Image = Properties.Resources.Folder_icon
};
ToolStripMenuItem SubMenu1;
SubMenu1 = new ToolStripMenuItem
{
Text = "DirSubMenu1",
Image = Properties.Resources.Folder_icon
};
var SubMenu2 = new ToolStripMenuItem
{
Text = "DirSubMenu2",
Image = Properties.Resources.Folder_icon
};
SubMenu2.DropDownItems.Clear();
SubMenu2.Click += (sender, args) => ShowItemName();
var SubSubMenu1 = new ToolStripMenuItem
{
Text = "DirSubSubMenu1",
Image = Properties.Resources.Folder_icon
};
SubSubMenu1.Click += (sender, args) => ShowItemName();
// Let's attach the submenus to the main menu
SubMenu1.DropDownItems.Add(SubSubMenu1);
MainMenu.DropDownItems.Add(SubMenu1);
MainMenu.DropDownItems.Add(SubMenu2);
menu.Items.Clear();
menu.Items.Add(MainMenu);
}
You have to create a command folder for example Archive, with two commands: A and B.
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\*\shell\Archive]
"MUIVerb"="Archive"
"SubCommands"="Windows.A;Windows.B"
The * in key means this menu shows up at right click on any file. If you want it only at the *.7z files, use HKEY_CLASSES_ROOT\.7z\shell\Archive. The value of MUIVerb will be the name of menu item. If you named the MUIVerb to 7-Zip, the right click menu will contains two 7-Zip items.
Then create the commands there:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.A]
"MUIVerb"="Command name of A"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.A\command]
#="notepad.exe \"%1\""
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.B]
"MUIVerb"="Command name of B"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.B\command]
#="notepad.exe \"%1\""
In this example, you get an Archive menuitem, with cascaded two command, whats open the current file with notepad. It works with Windows 7 and newer.
Related
I learned how to add an item to the right-click context menu, but I would like to add an icon too. I tested adding a value Icon to the key (imagine that the key is HKCL\lnkfile\shell\MY COMMAND\command, I added the icon value to HKCL\lnkfile\shell\MY COMMAND) but it doesn't work, I put the path to the icon inside it but it's 32x32, maybe is that the problem maybe no... do someone know how to add an icon to my menu item?
Thanks for any answer
For Windows 7 & 8 & 10
Add custom item to Context Menu:
Sublime Text 3
Path to the application: C:\Program Files\Sublime Text 3\sublime_text.exe.
Run regedit.exe (or press Windows Start Button & type: regedit)
Goto:
HKEY_CLASSES_ROOT\\*\shell
(* is right at the top)
Right_mouse_click shell in left panel for options to create a new Key:
New > Key
call it: Sublime Text 3 (or whatever you like to call it)
Then we create another Key under the one we just created: Right_mouse_click Sublime Text 3 (in fact: your own app's name) in left panel for options to create a new Key:
New > Key
call it: command
In the RIGHT panel change (Default) key value (double click or Right_mouse_click & Modify) to:
C:\Program Files\Sublime Text 3\sublime_text.exe %1
In actual fact: your own app's path.
BUT DO ADD THE FOLLOWING AT THE END OF YOUR PATH after a space: %1.
OPTIONAL: Set Icon + Position in menu:
Icon:
Click on key you created: Sublime Text 3 (Not it's child we just created: command)
Create a new String Value for it (Right_mouse_click on RIGHT panel background or menu: edit, then New > Key, choose String Value)
Call it: Icon
Set it's value as we did for command above to:
"C:\Program Files\Sublime Text 3\sublime_text.exe"
In actual fact: your own app's path
+
Position in context menu:
Create another String Value where we created Icon just as we did above
Call it: Position
Set it's Value to:
Top
or if you'd like:
Bottom
NOTE: ICON & POSITION STRING KEYS ARE NOT CREATED IN command, BUT ITS PARENT: whatever you called your app key in \shell.
This might be a long shot, but try creating a String value named "Icon" under the HKCL\lnkfile\shell\MY COMMAND key, and then set the value to the path to your icon (e.g. C:\Program Files\Your Program\YourProgram.exe,0), assuming your icons are embedded in whatever application you specified to run in your command.
Ok I've worked a bit on this and understood an important thing: If you are on Windows XP or older, you need to do a dll, create GUIDs, reference... a very long task to set only an icon to context menu
Otherwise if you have vista or seven (and it's the technique I'm using) Cory's answer works well.
simply add an entry in Registry :
HKCR\Directory\shell\%MY_APPLICATION%\command\
Key name : Icon
Key value : Full path of exe (it will use application embedded icon)
I am currently invoking the windows task manager using a click event in WPF. The event simply executes 'Process.Start("taskmgr").
My question is, is there a way to choose which tab inside task manager is selected when the process starts / is displayed? I am looking to have the 'performance' tab selected automatically whenever the click event is raised.
Thanks for the help.
To expand on Philipp Schmid's post, I've whipped up a little demo:
Run it as a console application. You need to add references to UIAutomationClient and UIAutomationTypes.
One possible improvement you (or I, if you desire) can make is to hide the window initially, only showing it after the correct tab has been selected. I'm not sure if that would work, however, as I'm not sure that AutomationElement.FromHandle would be able to find a hidden window.
Edit: At least on my computer (Windows 7, 32 bit, .Net framework 4.0), the following code initially creates a hidden Task Manager and shows it after the correct tab has been selected. I don't explicitly show the window after selecting the performance tab, so probably one of the automation lines does as a side-effect.
using System;
using System.Diagnostics;
using System.Windows.Automation;
namespace ConsoleApplication2 {
class Program {
static void Main(string[] args) {
// Kill existing instances
foreach (Process pOld in Process.GetProcessesByName("taskmgr")) {
pOld.Kill();
}
// Create a new instance
Process p = new Process();
p.StartInfo.FileName = "taskmgr";
p.StartInfo.CreateNoWindow = true;
p.Start();
Console.WriteLine("Waiting for handle...");
while (p.MainWindowHandle == IntPtr.Zero) ;
AutomationElement aeDesktop = AutomationElement.RootElement;
AutomationElement aeForm = AutomationElement.FromHandle(p.MainWindowHandle);
Console.WriteLine("Got handle");
// Get the tabs control
AutomationElement aeTabs = aeForm.FindFirst(TreeScope.Children,
new PropertyCondition(AutomationElement.ControlTypeProperty,
ControlType.Tab));
// Get a collection of tab pages
AutomationElementCollection aeTabItems = aeTabs.FindAll(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty,
ControlType.TabItem));
// Set focus to the performance tab
AutomationElement aePerformanceTab = aeTabItems[3];
aePerformanceTab.SetFocus();
}
}
}
Why do I destroy previous instances of Task Manager? When an instance is already open, secondary instances will open but immediately close. My code doesn't check for this, so the code that finds the window handle will freeze.
While taskmgr.exe doesn't have any command line arguments to specify the selected tab, you can use Windows UI Automation to 'navigate' to the performance tab.
Unfortunately, taskmgr.exe does not support any command line argument.
When run, it will always activate the tab that was active on last close.
Starting with Windows 10 build 18305, you can now set a preferred tab to have Task Manager open to by default.
To update:
Click on the start menu and in the search box type 'Windows Update'
Chose 'Windows Update Settings'
In the left panel click 'Preview Builds'
Click on the 'Check' now.
Download the new build.
After update, change dword value of StartUpTab in Win registry key:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\TaskManager
0 – Processes tab
1 – Performance tab
2 – App history tab
3 – Startup tab
4 – Users tab
5 – Details tab
6 – Services tab
Win CMD:
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\TaskManager /v "startup" /t REG_DWORD /d "1"
This (experimental) feature is only available to some Windows Insiders.
No other tabs except "Start-up" are supported for older builds of Win 10:
taskmgr /4 /startup
To reset:
reg delete HKCU\Software\Microsoft\Windows\CurrentVersion\TaskManager /v "Preferences" /f
To confirm modified key:
REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit" /v "LastKey" /d "HKCU\Software\Microsoft\Windows\CurrentVersion\TaskManager" /f & regedit
Tested in Win 10 CMD
I have seen this one before. We want a dedicated tab item with a '+' symbol on it. Like chrome browser in Silver light Application.
There is always a tab item appears at the end half visible and once you click on it, it turns into a complete tab item.
That was a little though to answer :P
Here it goes:
Create a class called LinqToVisualTree. You can find it at the end of this post, along with an explanation of what it does. Basically, it lets you query your Visual Tree through LINQ.
To add anything to the tabs row in a TabControl, you need to manipulate the TabPanel, which holds the "buttons" of tabs. TabPanel is in the System.Windows.Controls.Primitives namespace, so refer to it.
The easiest way to get the TabPanel I've found is to name at least one of your TabItems and do this:
using System.Windows.Controls.Primitives; // Contains TabPanel
using LinqToVisualTree;
void AddPlusButton() {
// Creates a button beside the tabs
var button = new Button()
{
Content = "+",
IsTabStop = false // To prevent keyboard press
};
// Links the Click with the "new tab" function
button.Click += new RoutedEventHandler(btPlus_Click);
// *** HERE IS THE TRICK ***
// Gets the parent TabPanel in the Visual Tree and cast it
var tabpn = tabItem1.Ancestors<TabPanel>().FirstOrDefault() as TabPanel;
// Links the button created
tabpn.Children.Add(button);
}
Here's the method for the plus button:
void btPlus_Click(object sender, RoutedEventArgs e)
{
// Creates a new TabItem
var ti = new TabItem();
ti.Header = "TabAdded";
ti.Content = new TextBlock() { Text = "Tab content!" };
// Links it
tabControl.Items.Add(ti);
}
That's it! Tip: I've just find out about the TabPanel class using Silverlight Spy. Searching on Google, I could just find methods of doing this by changing the Template Style from the TabControl.
Best regards!
I want to add a feature to my MenuStrip where I want there to be an option where you can hover over or press the menu option to open recently opened projects .
File---> Recently Opened Projects---> {List of projects.....}
The same kind of option/menu that exists in Microsoft office products (e.g. word 2007).
I know how to get an array of the file names. I just need to know how to put the array of the names at the Sub MenuStrip.
You can add them dynamically in code:
private void menuItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem item = new ToolStripMenuItem();
item.Text = "your file name";
item.Click += new EventHandler(yourEventHandler);
menuItem.DropDownItems.Add(item);
}
You need to create ToolStripMenuItems in a loop and call DropDownItems.Add to add them to your parent menu item.
In the loop, you should add a handler to their Click event.
According to http://msdn.microsoft.com/en-us/library/aa984351%28VS.71%29.aspx
Disabling the first or toplevel menu item in a menu (for example, the "File" menu item in a traditional File menu) disables all the menu items contained within the menu. Likewise, disabling a menu item that has submenu items disables the submenu items.
According to http://msdn.microsoft.com/en-us/library/ms171655.aspx
Disabling the first or top-level menu item in a menu disables all the menu items contained within the menu. Likewise, disabling a menu item that has submenu items disables the submenu items.
However, if I create a new Windows Forms project and add the following code, I can still use the shortcut key to access the Child menu item that, according to MSDN, should be disabled.
public Form1()
{
InitializeComponent();
// Main menu
MenuStrip mainMenu = new MenuStrip();
this.Controls.Add(mainMenu);
// Top Level menu
ToolStripMenuItem topLevelMenuItem = new ToolStripMenuItem("&Top Level");
mainMenu.Items.Add(topLevelMenuItem);
// Child menu item
ToolStripMenuItem childMenuItem = new ToolStripMenuItem("&Child...", null, (o, e) => MessageBox.Show("Doing something."));
childMenuItem.ShortcutKeys = Keys.Control | Keys.C;
childMenuItem.ShortcutKeyDisplayString = "Ctrl + C";
topLevelMenuItem.DropDownItems.Add(childMenuItem);
// Menu item to toggle the Top Level menu's Enabled property
mainMenu.Items.Add(new ToolStripMenuItem("Toggle Enable for Top Level menu", null, (o, e) =>
{
topLevelMenuItem.Enabled = !topLevelMenuItem.Enabled;
MessageBox.Show("topLevelMenuItem.Enabled = " + topLevelMenuItem.Enabled + Environment.NewLine + "childMenuItem.Enabled = " + childMenuItem.Enabled);
}));
}
I can see that childMenuItem.Enabled is not changing at all, while topLevelMenuItem.Enabled does.
Sure, I could use a for loop to disable all menu items under the Top Level menu, or even disable just the Child menu item, but according to MSDN I shouldn't have to. What's the deal? Am I missing something, misinterpreting something, or is MSDN just wrong?
It is a bug. There are lots of bugs in the ToolStripItem classes, they were not fixed when the time was right (some time after the .NET 2.0 release), now it is too late. Posting these bugs to the Connect feedback site isn't useful, they'll just tell you to visit the MSDN forums to find a workaround. I think you already got one. Fwiw, here's one that matches your case.