Reputation: 4516
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
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