locked
How to set the Context menu strip for a Form Header in .NET RRS feed

  • Question

  • Hi ,

     By default if we right click on Form header or if u press Alt + Spacebar one default menu will apper with Resotr Move Size Minimize and maximize. instead of this Menu i want my own menu to appear when we Right click or Press Alt+Spacebar.How to achive this???

    I am trying to Set the Following

    Me.ContextMenuStrip = ContectMenuStrip1

     

    But it is only poping up when we right click on Form.If we clicko n Form Header the normal menu is poping up.

    Do we need to use Any API call?

    Any help appreciated

    Thursday, May 6, 2010 6:14 AM

All replies

  • hello,

    i don't know how to replace system menu on a form with your own. You could probably set ControlBox to false and then handle right mouse button click on the non-client area to display your own context menu ...

    I would personally find it annoying if someone would completely remove system menu from an app I'm using. It's standard, users expect it to be there.
    Here is an example how you can add your own menu items into system menu:

    http://stackoverflow.com/questions/1557904/adding-a-custom-context-menu-item-to-windows-form-title-bar

    EDIT: I've added RemoveMenu to show how you can remove standard menu items ... just think twice before you do that.
    You might need InsertMenuItem  instead of InsertMenu.

     

    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System;
    
    namespace FormSystemMenu
    {
    	public partial class Form1 : Form
    	{
    		public const Int32 WM_SYSCOMMAND = 0x112;
    
    		public const Int32 MF_BYPOSITION = 0x400;
    		public const Int32 MYMENU1 = 1000;
    		public const Int32 MUMENU2 = 1001;
    
    		[DllImport("user32.dll")]
    		private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
    		[DllImport("user32.dll")]
    		private static extern bool InsertMenu(IntPtr hMenu, Int32 wPosition, Int32 wFlags, Int32 wIDNewItem, string lpNewItem);
    		[DllImport("user32.dll")]
    		private static extern bool RemoveMenu(IntPtr hMenu, int uPosition, int uFlags);
    
    		public Form1()
    		{
    			InitializeComponent();
    
    			this.Load += new System.EventHandler(this.Form1_Load);
    		}
    
    		protected override void WndProc(ref Message msg)
    		{
    			if (msg.Msg == WM_SYSCOMMAND)
    			{
    				switch (msg.WParam.ToInt32())
    				{
    					case MYMENU1:
    						MessageBox.Show("Hi from My Menu 1¡¡¡¡");
    						return;
    					case MUMENU2:
    						MessageBox.Show("Hi from My Menu 2¡¡¡¡");
    						return;
    					default:
    						break;
    				}
    			}
    			base.WndProc(ref msg);
    		}
    
    		private void Form1_Load(object sender, EventArgs e)
    		{
    			IntPtr MenuHandle = GetSystemMenu(this.Handle, false);
    
    			// remove Restore
    			RemoveMenu(MenuHandle, 0, MF_BYPOSITION);
    			// remove Move
    			RemoveMenu(MenuHandle, 0, MF_BYPOSITION);
    			// remove Size
    			RemoveMenu(MenuHandle, 0, MF_BYPOSITION);
    			// remove Minimize
    			RemoveMenu(MenuHandle, 1, MF_BYPOSITION);
    			// remove Maximize
    			RemoveMenu(MenuHandle, 1, MF_BYPOSITION);
    			
    			InsertMenu(MenuHandle, 0, MF_BYPOSITION, MYMENU1, "My Menu 1");
    			InsertMenu(MenuHandle, 1, MF_BYPOSITION, MUMENU2, "My Menu 2");
    
    		}
    	}
    }

     

    Hope someone will have a better idea, especially if this doesn't meet your needs.

     

    Best regards,
    Vladimir

    • Edited by Vladimir.Ilic Thursday, May 6, 2010 5:07 PM additional links and removing menu items example
    Thursday, May 6, 2010 4:51 PM
  • I would personally find it annoying if someone would completely remove system menu from an app I'm using. It's standard, users expect it to be there.

    ///

    in VB6 they have done like that..so i should remove the system menu.

    Any way very thanks for ur valuable inputs .i will try this and let u know

    Monday, May 10, 2010 9:08 AM
  • Hi SUNIL,

    In order to get a menu to pop up when right-clicking on a custom design surface, you should do two things. The first thing is to create a class implementing the Interface IMenuCommandService and add the service to the custom design surface. The second thing is to add verbs to the MenuCommandService.

    Suppose you have opened a form in the custom design surface and added several controls on the form. When you right-click on the controls or the form in your custom design surface, a context menu will appear.

    If you want to have a different menu item when you right-click on a custom control in your custom design surface, you should associate a designer to your custom control and override the Verbs property of the designer class.

    The following is a sample.


    // the definition of a class implementing IMenuCommandService
    public class MenuCommandServiceImpl : IMenuCommandService
    {
        // the host
        private IDesignerHost host;

        // commandId-command mapping
        private IDictionary commands;

        // menuItem-verb mapping
        private IDictionary menuItemVerb;

        // the global verbs collection. 
        private DesignerVerbCollection globalVerbs;

        // we use the same context menu over-and-over
        private ContextMenu contextMenu;

        // we keep the lastSelectedComponent around 
        private IComponent lastSelectedComponent;

        public MenuCommandServiceImpl(IDesignerHost host)
        {
            this.host = host;
            commands = new Hashtable();
            globalVerbs = new DesignerVerbCollection();
            menuItemVerb = new Hashtable();
            contextMenu = new ContextMenu();
            lastSelectedComponent = null;
        }
        #region Implementation of IMenuCommandService

        /// called to add a MenuCommand
        public void AddCommand(System.ComponentModel.Design.MenuCommand command)
        {
            if (command == null)
            {
                throw new ArgumentException("command");
            }
            // don't add commands twice
            if (FindCommand(command.CommandID) == null)
            {
                commands.Add(command.CommandID, command);
            }
        }

        /// called to remove a MenuCommand
        public void RemoveCommand(System.ComponentModel.Design.MenuCommand command)
        {
            if (command == null)
            {
                throw new ArgumentException("command");
            }
            commands.Remove(command.CommandID);
        }

        /// called when to add a global verb
        public void AddVerb(System.ComponentModel.Design.DesignerVerb verb)
        {
            if (verb == null)
            {
                throw new ArgumentException("verb");
            }
            globalVerbs.Add(verb);
            // create a menu item for the verb and add it to the context menu
            MenuItem menuItem = new MenuItem(verb.Text);
            menuItem.Click += new EventHandler(MenuItemClickHandler);
            menuItemVerb.Add(menuItem, verb);
            contextMenu.MenuItems.Add(menuItem);
        }

        /// called to remove global verb
        public void RemoveVerb(System.ComponentModel.Design.DesignerVerb verb)
        {
            if (verb == null)
            {
                throw new ArgumentException("verb");
            }

            globalVerbs.Remove(verb);

            // find the menu item associated with the verb
            MenuItem associatedMenuItem = null;
            foreach (DictionaryEntry de in menuItemVerb)
            {
                if (de.Value == verb)
                {
                    associatedMenuItem = de.Key as MenuItem;
                    break;
                }
            }

            // if we found the verb's menu item, remove it
            if (associatedMenuItem != null)
            {
                menuItemVerb.Remove(associatedMenuItem);
            }

            // remove the verb from the context menu too
            contextMenu.MenuItems.Remove(associatedMenuItem);
        }

        /// returns the MenuCommand associated with the commandId.
        public System.ComponentModel.Design.MenuCommand
    FindCommand(System.ComponentModel.Design.CommandID commandID)
        {
               return commands[commandID] as MenuCommand;
        }

        /// called to invoke a command
        public bool GlobalInvoke(System.ComponentModel.Design.CommandID commandID)
        {
            bool result = false;
            MenuCommand command = FindCommand(commandID);
            if (command != null)
            {
                command.Invoke();
                result = true;
            }
            return result;
        }

        /// called to show the context menu for the selected component.
        public void ShowContextMenu(System.ComponentModel.Design.CommandID menuID, int x, int y)
        {
            ISelectionService selectionService = host.GetService(typeof(ISelectionService)) as ISelectionService;
            // get the primary component
            IComponent primarySelection = selectionService.PrimarySelection as IComponent;
            // if the he clicked on the same component again then just show the context
            // menu. otherwise, we have to throw away the previous
            // set of local menu items and create new ones for the newly
            // selected component
            if (lastSelectedComponent != primarySelection)
            {
                // remove all non-global menu items from the context menu ResetContextMenu();
                // get the designer
                IDesigner designer = host.GetDesigner(primarySelection);
                // not all controls need a desinger
                if (designer != null)
                {
                    // get designer's verbs
                    DesignerVerbCollection verbs = designer.Verbs;
                    foreach (DesignerVerb verb in verbs)
                    {
                        // add new menu items to the context menu
                        CreateAndAddLocalVerb(verb);
                    }
                }
            }

            // we only show designer context menus for controls
            if (primarySelection is Control)
            {
                Control comp = primarySelection as Control;
                Point pt = comp.PointToScreen(new Point(0, 0));
                contextMenu.Show(comp, new Point(x - pt.X, y - pt.Y));
            }

            // keep the selected component for next time
            lastSelectedComponent = primarySelection;
        }

        /// returns the the current designer verbs
        public System.ComponentModel.Design.DesignerVerbCollection

     

    Sincerely,
    Helen Zhou


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    • Marked as answer by Helen Zhou Wednesday, May 12, 2010 7:11 AM
    • Unmarked as answer by .NET Learner Suni Wednesday, May 19, 2010 3:06 PM
    Wednesday, May 12, 2010 7:11 AM
  • Hi Helen,

    are you sure that your post has anything to do with the question being asked here ?
    The question was not about invoking custom context menu in design time, it's about replacing form system menu in runtime.
    Which would probably get better responses in the Windows Forms General forum, but still, move it or give it a chance.

    It would be nice of you to give the OP at least couple of days (a week would be my minimum ) to reply before you mark answers on the thread. People answering will most likely skip an answered thread and OP will not get any other ideas until he has the chance to reactivate the thread.

     

    Best regards,
    Vladimir

    Wednesday, May 12, 2010 7:52 PM