tigrou
tigrou

Reputation: 4516

How to detect everytime a key has been pressed on a context menu (winforms)?

In a Winforms application, I use a ContextMenuStrip (shown when right clicking on notification icon).

I would like to detect if a key has been pressed when context menu item is open (eg : by registering to an event).

There is no KeyDown event on ContextMenuStrip, unlike most controls. However, there is a PreviewKeyDown event. I have registered to that event, however it does not work as expected.

Here is my context menu :

Item1
Item2
SubMenu > SubItem1
          SubItem2

If I press a key while Item1 is higlighted (mouse is on it), event is triggered. However, if I press a key when SubItem1 is highlighted, nothing happen.

Same behavior happen if no item is highlighted : If only context menu is opened (no item highlighted), event is triggered. If sub context menu is opened (no item highlighted), event is not triggered.


Here is some code sample as requested :

//MainForm.cs
void ContextMenuStrip1PreviewKeyDown(object sender, EventArgs e)
{
    MessageBox.Show("OK"); //not always called, as explained above
}

//MainForm.Designer.cs (generated automatically by form designer)
this.contextMenuStrip1.PreviewKeyDown +=
  new System.Windows.Forms.PreviewKeyDownEventHandler(this.ContextMenuStrip1PreviewKeyDown);

Upvotes: 1

Views: 528

Answers (1)

Reza Aghaei
Reza Aghaei

Reputation: 125197

To detect the Shift key state when a context menu strip is open, As an option you can handle Application.Idle event and will check the key state using GetKeyState function:

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern short GetKeyState(int keyCode);
public const int KEY_PRESSED = 0x8000;
public static bool IsKeyDown(Keys key)
{
    return Convert.ToBoolean(GetKeyState((int)key) & KEY_PRESSED);
}

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    Application.Idle += Application_Idle;
}

void Application_Idle(object sender, EventArgs e)
{
    if (!contextMenuStrip1.Visible)
        return;
    if (IsKeyDown(Keys.ShiftKey))
        someMenuItem.Text = "Shift is Down";
    else
        someMenuItem.Text = "Shift is Up";
}

protected override void OnFormClosed(FormClosedEventArgs e)
{
    Application.Idle -= Application_Idle;
    base.OnFormClosed(e);
}

Upvotes: 1

Related Questions