Fishy
Fishy

Reputation: 35

ContextMenuStrip.Show not working half the time

tl/dr: Every second time I call ContextMenuStrip.Show, it doesn't show.

I am building an application that runs in the background but displays a drop-down menu on the mouse cursor when the user hits a specific hotkey.

If the application has focus, this works 100% of the time. If another application has focus (this is my main use case) it fails exactly 50% of the time. Specifically, the first hotkey press works, but once you select an item from the menu (which triggers a short function), the next hotkey press does not display the menu. If you keep pressing the hotkey without clicking the menu, the menu keeps popping up at the cursor position. If you switch back to the application, the menu appears every time.

I am fairly new to coding, but I have simplified the code such that the hotkey press does nothing other than run a single line of code (ContextMenuStrip.Show), and I have watched in the debugger and that line does get hit, and all the variables look the same to me on the presses that do and don't work.

EDIT: This is the simplest version of the code I could make. Please excuse any weirdness. I'm new to coding and am probably doing unrelated strange things!

To reproduce, run the program, switch to another window, press Ctl-Q to bring up the menu, select an item, press Ctl-Q again and the menu should fail to show.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Input;
using System.Runtime.InteropServices;

namespace Bug
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            // Register hotkey
            int UniqueHotkeyId = 1;
            int HotKeyCode = (int)Keys.Q;
            Boolean F9Registered = RegisterHotKey(
                this.Handle, UniqueHotkeyId, 2, HotKeyCode
            );
            myPopupMenu.menu = myPopupMenu.BuildMenu();
        }
        // Stuff that makes the hotkey work
        [DllImport("user32.dll")]
        public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        protected override void WndProc(ref Message m)
        {
            // Catch when a HotKey is pressed !
            if (m.Msg == 0x0312)
            {
                int id = m.WParam.ToInt32();
                if (id == 1)
                {
                    // Show Menu on hoteky press
                    myPopupMenu.ShowMenu();
                }
            }
            base.WndProc(ref m);
        }
        public PopupMenu myPopupMenu = new PopupMenu();
    }
    

    public class PopupMenu
    {
        public ContextMenuStrip menu { get; set; }

        public ContextMenuStrip BuildMenu()
        {
            ContextMenuStrip menu = new ContextMenuStrip();
            ToolStripMenuItem item;
            ToolStripMenuItem submenu;

            submenu = new ToolStripMenuItem();
            submenu.Text = "submenu";

            item = new ToolStripMenuItem("item", null, MenuClick);
            submenu.DropDownItems.Add(item);
            menu.Items.Add(submenu);

            return menu;
        }

        public void ShowMenu()
        {
            menu.Show(Cursor.Position);
        }

        public void MenuClick(object sender, EventArgs e) { }
    }
}

Upvotes: 2

Views: 191

Answers (1)

Zer0
Zer0

Reputation: 7354

Change

ContextMenuStrip menu = new ContextMenuStrip();

To

ContextMenuStrip menu = new ContextMenuStrip { AutoClose = false };

And your example now works 100% of the time on my end (both focused and not focused).

Why, I'm not quite sure. Just used an automated tool to rapidly change things until desired behavior occurred.

Upvotes: 2

Related Questions