0

How can I add a menu item that has an arrow to the right as if there would be a submenu but does not show a submenu?

Background: For a managed C# application I want to add a submenu which is created in an unmanaged DLL (using TrackPopupMenu()).

In my experiments, I can only show the arrow when there are items attached using "DropDownItems.Add".

I tried to use

ToolStripMenuItem menu = new ToolStripMenuItem();
m_menu.Text = "Item that should have arrow w/o submenu";
m_menu.Click += this.OnMenuDoSomething;
m_menu.DropDownItems.Add("");

This still adds a submenu. I then tried these combinations:

m_menu.DropDownItems[0].Enabled = false;
m_menu.DropDownItems[0].Available = false;
m_menu.DropDownItems[0].Visible = false;

but either the submenu including the arrow disappears or nothing at all.

divB
  • 896
  • 1
  • 11
  • 28
  • The arrow is dependent on the fact that there is a submenu - disabling it or hiding it hides the arrow. You can use an icon or one of these: ->, =>, -->. – Mathemats Apr 01 '15 at 02:12
  • Is there really now way to force this? If not, how to I align a text/image on the right side (same place where arrow would be)? – divB Apr 01 '15 at 02:22
  • Alternatively: Are there easy ways to load a menu from a resource within a DLL (like CMenu::FromResource in MFC?) I guess not ... – divB Apr 01 '15 at 02:25
  • I just see that this is not a real solution because: the actual unicode arrows (triangle right, code 9205) does not exist in Windows font. The image is no solution because it seems that only one image can be used – divB Apr 01 '15 at 03:17

1 Answers1

1

When the drop down menu's handle is created, assign it to a NativeWindow to capture the window messages and hide the paint events. In fact, you can hide all events.

When you want to show the drop down menu, simply release the NativeWindow's handle.

E.g.

    private class NW : NativeWindow {
        public NW(IntPtr handle) {
            AssignHandle(handle);
        }

        const int WM_PAINT = 0xF;
        protected override void WndProc(ref Message m) {
            // can ignore all messages too
            if (m.Msg == WM_PAINT) {
                return;
            }
            base.WndProc(ref m);
        }
    }

    [STAThread]
    static void Main() {

        MenuStrip menu = new MenuStrip();

        NW nw = null; // declared outside to prevent garbage collection
        ToolStripMenuItem item1 = new ToolStripMenuItem("Item1");
        ToolStripMenuItem subItem1 = new ToolStripMenuItem("Sub Item1");
        subItem1.DropDown.DropShadowEnabled = false;
        subItem1.DropDown.HandleCreated += delegate {
            nw = new NW(subItem1.DropDown.Handle);
        };

        ToolStripMenuItem miMakeVisible = new ToolStripMenuItem("Make Visible");
        miMakeVisible.Click += delegate {
            if (nw != null) {
                nw.ReleaseHandle();
                nw = null;
            }
        };


        ToolStripMenuItem subItem2 = new ToolStripMenuItem("Sub Item2");
        item1.DropDownItems.Add(subItem1);
        item1.DropDownItems.Add(miMakeVisible);
        subItem1.DropDownItems.Add(subItem2);
        menu.Items.Add(item1);


        Form f = new Form();
        f.Controls.Add(menu);
        f.MainMenuStrip = menu;
        Application.Run(f);
    }
Loathing
  • 5,109
  • 3
  • 24
  • 35