Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ContextMenuStrip and PreviewKeyDown

4 views
Skip to first unread message

Dave

unread,
Jan 31, 2007, 10:18:22 AM1/31/07
to
How do I get my ContextMenuStrip to receive key down preview events? I have
the event hooked but I don't see the key strokes in the event?

Dave


Dave

unread,
Feb 1, 2007, 3:05:56 PM2/1/07
to
Put a combo box in the menu and key digits into it, you will notice your key
preview is not getting the keystrokes


""Jeffrey Tan[MSFT]"" <je...@online.microsoft.com> wrote in message
news:hnSQ%23uaRH...@TK2MSFTNGHUB02.phx.gbl...
> Hi Dave,
>
> Based on my understanding, you are registering
> ContextMenuStrip.PreviewKeyDown event in Winform application, however,
your
> event is never fired.
>
> Can you tell me how do you try to fire this event? Based on my research,
> ContextMenuStrip.PreviewKeyDown actually inherits from Control class. In
> Control.PreviewKeyDown MSDN document, we will read: "Occurs when a key is
> pressed while the control has focus". So, this event will be fired when
the
> control has focus. Note: in this scenario, the control means the
> ContextMenuStrip instead of the control the ContextMenuStrip associated
> with. In my test project, I right click on the associated control to show
> out the ContextMenuStrip, and then I pressed the keyboard, the
> ContextMenuStrip.PreviewKeyDown event will fire without any problem. You
> may give these steps a try.
>
> I have attached the sample project in this reply(you may use Outlook
> Express to download it), for your information.
>
> Hope this helps.
>
> Best regards,
> Jeffrey Tan
> Microsoft Online Community Support
> ==================================================
> Get notification to my posts through email? Please refer to
>
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
> ications.
>
> Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
> where an initial response from the community or a Microsoft Support
> Engineer within 1 business day is acceptable. Please note that each follow
> up response may take approximately 2 business days as the support
> professional working with you may need further investigation to reach the
> most efficient resolution. The offering is not appropriate for situations
> that require urgent, real-time or phone-based interactions or complex
> project analysis and dump analysis issues. Issues of this nature are best
> handled working with a dedicated Microsoft Support Engineer by contacting
> Microsoft Customer Support Services (CSS) at
> http://msdn.microsoft.com/subscriptions/support/default.aspx.
> ==================================================
> This posting is provided "AS IS" with no warranties, and confers no
rights.


Jeffrey Tan[MSFT]

unread,
Feb 1, 2007, 10:49:35 PM2/1/07
to
Hi Dave,

Thanks for your feedback.

Yes, I can reproduce this behavior. Actually, this is expected. After
adding a ToolStripCombobox into the ContextMenuStrip, when you are typing
in the combobox edit textbox, there is actually another child control in
ContextMenuStrip control, that is the Combobox. So the keydown notification
will not be sent to its parent control, but to the direct child
control--ComboBox.(This makes sense, for example, when you are typing in
the ContextMenuStrip, you do not want its parent control(Form)'s
PreviewKeyDown event to be called. )

To resolve this problem, you may get the reference to the Combobox and
register its PreviewKeyDown like below:

private void Form1_Load(object sender, EventArgs e)
{
this.toolStripComboBox1.ComboBox.PreviewKeyDown += new
PreviewKeyDownEventHandler(ComboBox_PreviewKeyDown);
}

void ComboBox_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
MessageBox.Show("ComboBox_PreviewKeyDown");

Dave

unread,
Feb 2, 2007, 8:55:56 AM2/2/07
to
I was hoping to not have to do that. Is there no functionality similar to
the KeyPreview property of a form on a ContextMenuStrip?

In all the history of windows any parent window is capable of hooking the
keyboard events of it's child window.

In my case this Context menu is an abstract class and has dozens of custom
controls with dozens of controls on the custom control. I would eventually
have to create hundreds of key event handlers. Which is not my preferred
way of doing this.

I guess I need to create some sort of popup window similar to
ContextMenuStrip that is based on a form class so I can turn on KeyPreview.
Any suggestions?

Dave


""Jeffrey Tan[MSFT]"" <je...@online.microsoft.com> wrote in message

news:2ZNqt0nR...@TK2MSFTNGHUB02.phx.gbl...

Dave

unread,
Feb 5, 2007, 11:10:41 AM2/5/07
to
Did you manually edit the designer get contextMenuStrip1 constructed like
this?

this.contextMenuStrip1 = new
ContextMenuStripTest.Form1.MyContextMenuStrip(this.components);


""Jeffrey Tan[MSFT]"" <je...@online.microsoft.com> wrote in message

news:c$RUYQNSH...@TK2MSFTNGHUB02.phx.gbl...
> Hi Dave,
>
> Thanks for your feedback!
>
> Yes, I understand your concern. However, this is somewhat the limitation
of
> Windows control keyboard input model.
>
> Net Winform encapsulates the Win32 Windows controls, such as Edit
> control(TextBox), Combobox, ListView, Button etc..., so it also obeys the
> Win32 control message model and input model. In Windows control keyboard
> input model, the WM_KEYDOWN messages(which maps to .Net Control.KeyDown
> event) will only be sent to the control currently has focus. It will not
be
> sent to this focused control's parent window or sibling window("window" is
> the same concept as "control"). So if we type in the TextBox, the Windows
> GUI system will not notify the parent Form class.
>
> Yes, I see the Form.KeyPreview property. Let's research how this property
> is implemented. Below is the stack trace I captured when Form.KeyPreview
> property is set to true while I pressed a key on the focused button:
>
> > ContextMenuStripTest.Form1.Form1_KeyDown(object,
> System.Windows.Forms.KeyEventArgs) C#
>
System.Windows.Forms.Control.OnKeyDown(System.Windows.Forms.KeyEventArgs)
> C#
> System.Windows.Forms.Control.ProcessKeyEventArgs(ref
> System.Windows.Forms.Message) C#
> System.Windows.Forms.Form.ProcessKeyPreview(ref
> System.Windows.Forms.Message) C#
> System.Windows.Forms.Control.ProcessKeyMessage(ref
> System.Windows.Forms.Message) C#
> System.Windows.Forms.Control.WmKeyChar(ref System.Windows.Forms.Message)
> C#
> System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message)
C#
> System.Windows.Forms.ButtonBase.WndProc(ref
System.Windows.Forms.Message)
> C#
> System.Windows.Forms.Button.WndProc(ref System.Windows.Forms.Message) C#
> System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref
> System.Windows.Forms.Message) C#
> System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref
> System.Windows.Forms.Message) C#
> System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr, int,
> System.IntPtr, System.IntPtr) C#
> [Native to Managed Transition]
> [Managed to Native Transition]
>
>
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.Unsaf
> eNativeMethods.IMsoComponentManager.FPushMessageLoop(int, int, int) C#
> System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int,
> System.Windows.Forms.ApplicationContext) C#
> System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int,
> System.Windows.Forms.ApplicationContext) C#
> System.Windows.Forms.Application.Run(System.Windows.Forms.Form) C#
> ContextMenuStripTest.Program.Main() C#
>
> As you can see, it is the Button.WndProc that calls base.WndProc which
> finally calls Form.ProcessKeyPreview. Below is the source code of
> Form.ProcessKeyPreview method:
>
> protected override bool ProcessKeyPreview(ref Message m)
> {
> if ((this.formState[Form.FormStateKeyPreview] != 0) &&
> this.ProcessKeyEventArgs(ref m))
> {
> return true;
> }
> return base.ProcessKeyPreview(ref m);
> }
>
> Yes, this method is the key point. This method checks if Form.KeyPreview
> property is true, if so, it will call Control.ProcessKeyEventArgs() method
> to dispatch the Button's KeyDown event to Form.KeyDown event. So, it is
> still only the Button.WndProc receives the WM_KEYDOWN message, but .Net
> Winform internally dispatch this message to Form.KeyDown event for
> processing.
>
> To satisfy your scenario, I inherit from ContextMenuStrip and simulate
what
> Form.ProcessKeyPreview() method internal does, like below:
>
> public class MyContextMenuStrip : ContextMenuStrip
> {
> public MyContextMenuStrip(IContainer container)
> {
> if (container == null)
> {
> throw new ArgumentNullException("container");
> }
> container.Add(this);
> }
>
> public bool KeyPreview = false ;
> protected override bool ProcessKeyPreview(ref Message m)
> {
> if ((this.KeyPreview== true) && this.ProcessKeyEventArgs(ref m))
> {
> return true;
> }
> return base.ProcessKeyPreview(ref m);
> }
> }
>
> Now, in the Form designer, I change all the
> System.Windows.Forms.ContextMenuStrip class to "MyContextMenuStrip" class
> and register the contextMenuStrip1.KeyDown, like below:
>
> private MyContextMenuStrip contextMenuStrip1;
> this.contextMenuStrip1 = new
> ContextMenuStripTest.Form1.MyContextMenuStrip(this.components);


>
> private void Form1_Load(object sender, EventArgs e)
> {

> this.contextMenuStrip1.KeyPreview = true;
> this.contextMenuStrip1.KeyDown += new
> KeyEventHandler(contextMenuStrip1_KeyDown);
> }
>
> void contextMenuStrip1_KeyDown(object sender, KeyEventArgs e)
> {
> MessageBox.Show("contextMenuStrip1_KeyDown");
> }
>
> Based on my test, this will have the same function as Form.KeyPreview
> property. All the key down in the child controls of MyContextMenuStrip
will
> first trigger MyContextMenuStrip.KeyDown. I hope this meets your need.
>
> I have also attached the sample project in this reply. You may download it
> through Outlook Express(can not use IE).

Dave

unread,
Feb 5, 2007, 3:02:14 PM2/5/07
to
Jeffery,

Thanks for all your suggestions. With the information you gave me I was
able to make a single modification to my abstract class to solve the
problem.

Dave


""Jeffrey Tan[MSFT]"" <je...@online.microsoft.com> wrote in message

news:c$RUYQNSH...@TK2MSFTNGHUB02.phx.gbl...
> Hi Dave,
>


> Thanks for your feedback!
>
> Yes, I understand your concern. However, this is somewhat the limitation
of
> Windows control keyboard input model.
>
> Net Winform encapsulates the Win32 Windows controls, such as Edit
> control(TextBox), Combobox, ListView, Button etc..., so it also obeys the
> Win32 control message model and input model. In Windows control keyboard
> input model, the WM_KEYDOWN messages(which maps to .Net Control.KeyDown

> event) will only be sent to the control currently has focus. It will not
be

> private void Form1_Load(object sender, EventArgs e)
> {

> this.contextMenuStrip1.KeyPreview = true;
> this.contextMenuStrip1.KeyDown += new
> KeyEventHandler(contextMenuStrip1_KeyDown);
> }
>
> void contextMenuStrip1_KeyDown(object sender, KeyEventArgs e)
> {
> MessageBox.Show("contextMenuStrip1_KeyDown");
> }
>
> Based on my test, this will have the same function as Form.KeyPreview
> property. All the key down in the child controls of MyContextMenuStrip
will
> first trigger MyContextMenuStrip.KeyDown. I hope this meets your need.
>
> I have also attached the sample project in this reply. You may download it
> through Outlook Express(can not use IE).
>

Dave

unread,
Feb 9, 2007, 9:53:59 AM2/9/07
to
Thanks I'll take a look at it.


""Jeffrey Tan[MSFT]"" <je...@online.microsoft.com> wrote in message

news:K$yogmbSH...@TK2MSFTNGHUB02.phx.gbl...


> Hi Dave,
>
> Thanks for your feedback!
>

> Yes, in this little sample project, I did not move the MyContextMenuStrip
> code into a separate control, so I just modified the original designer
> generated code manually.
>
> In practical using, you may move the code into a separate control, and
once
> your control contains a constructor with the prototype below:
> public MyContextMenuStrip(IContainer container)
>
> The designer will understand it and generate the code to call this special
> constructor:
> this.myContextMenuStrip1 = new
> ContextMenuStripTest.MyContextMenuStrip(this.components);
>
> The article below provides more details of the context of this
constructor:
> "What's that "Windows Form Designer generated code" anyway?"
> http://www.codeproject.com/dotnet/disposable_components.asp?print=true
>
> I have also modified the original project to place the MyContextMenuStrip
> code into a separate control. I have attached this sample project in this
> reply, for your information.
>
> Hope it helps.

Jeffrey Tan[MSFT]

unread,
Feb 11, 2007, 10:36:12 PM2/11/07
to
Ok, if you still need any help or have anything unclear, please feel free
to tell me, thanks.
0 new messages