Problem trying to trap key down event on WinForm....

J

JDeats

If you create a new C# Windows Application project in Visual
Studio.NET 2003 or 2005 and proceed to.

1. Make default form size 800x600
2. Drop a CheckBoxList control and dock it to the left
3. Drop a webBrowser control and dock it to the top
4. Drop a panel control and dock it to fill

Make the web browser about 60% of the form height height and make the
panel control about 40% of the height.

5. Set the form properties so that KeyPreview is set to true.
6. Create an event handler for KeyDown on the form

In the KeyDown event handler do a MessageBox.Show() to show the key
value.

All that will take about 3 minutes to setup thanks to the wonder of
Visual Studio, now if you launch the app you'll notice on any key
press you get the expected key value.... Unless you happen to do a few
specific things.

Here are two test that anyone can perform to reproduce the problem
with the KeyDown event handler.

A. Close the app (if it's open) and relaunch it. Immediately when it
opens, before hitting any keys, proceed to single-click on the web
browser area of the form, then hit any key, you'll notice the event
apparently is not being fired or not being handled.

B. Close the app (if it's open) and relaunch it. Immediately when it
opens, before hitting any keys, proceed to mouse left-click many times
on the panel area (click 5 or 6 times rapidly) then hit any key on the
keyboard, the key press event handler no longer gets triggered. You
can proceed to click on any other portion of the win form and the
keydown handler will start working again, but if you rapidly click on
the panel area (5-10 left-clicks), the KeyDown event handler seemingly
randomly stops working.

Following these steps this problem is easy to reproduce for anyone.
I've done it now on three systems, for reference I'm using Visual
Studio.NET 2005
 
J

JDeats

I found a solution. You have to create a new class that implements the
IMessageFilter interface and then in Program.cs you have to add the
MessageFilter and then pass it to your Form class through the
constructor. Then you inside your Form constructor you have to create
an event handler to the KeyPressed event (see code below for how
KeyPressed is defined in KeyboardMsgFilter). This solution is much
more reliable than setting KeyPreview = true and trapping on the
WinForms KeyPress or KeyDown events. The later approach has some
issues of my first post to this thread details.


public class KeyboardMsgFilter : IMessageFilter
{
public delegate void KeyboardEvent(object source, string
keyVal);
public event KeyboardEvent KeyPressed;

public bool PreFilterMessage(ref Message m)
{
string key = "";
const int WM_KEYDOWN = 0x0100;

if (m.Msg == WM_KEYDOWN)
{

int keycode = Convert.ToInt32(m.LParam.ToString());
switch (keycode)
{
case 1179649 :
key = "E";
break;
case 1245185 :
key = "R";
break;
case 2031617 :
key = "S";
break;

}

if (key != "")
{
KeyPressed(null, key);
}

}
return false;
}
}



static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
KeyboardMsgFilter kmf = new KeyboardMsgFilter();
Application.AddMessageFilter(kmf);

Application.Run(new Form1(kmf));
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top