Click here to Skip to main content
11,924,825 members (55,167 online)
Rate this:
Please Sign up or sign in to vote.
See more: C#
Hey all,

I'm feeling really stupid asking this, but I just can't get it to work. I need to capture the KeyDown / KeyUp events in a C# application to determine the ScanCodes and Virtual Key Codes of the keys.

I simply overrided the WndProc method and checked if the Msg is equal to one of the KeyDown / KeyUp events. The code is shown below:

using System.Windows.Forms;
namespace ProcTest
    public partial class Form1 : Form
        public Form1()
        const int WM_KEYDOWN = 0x0100, WM_KEYUP = 0x0101, WM_CHAR = 0x0102, WM_SYSKEYDOWN = 0x0104, WM_SYSKEYUP = 0x0105;
        protected override void WndProc(ref Message m)
            if (m.Msg == WM_KEYDOWN || m.Msg == WM_KEYUP || m.Msg == WM_CHAR || m.Msg == WM_SYSKEYDOWN || m.Msg == WM_SYSKEYUP)
            base.WndProc(ref m);

The application is a standard Windows Form - with a simple textbox in it (to allow me to type in it), however I can't get it to work. The WndProc method is being called, however no Msg seems to match the defined set of integers (therefore, the 'Test' message box is never shown).

What am I missing?

Edit: I know I can use the TextBox events, but I believe that the best way to capture the keys Scan Codes and Virtual Key Codes is through the WndProc.
Posted 3-Feb-13 8:41am
Edited 3-Feb-13 22:00pm

1 solution

Rate this: bad
Please Sign up or sign in to vote.

Solution 1

The solution of this problem in full is shown in the demo application which comes with my CodeProject article: Dynamic Method Dispatcher[^].

If you need to extract more information from the events, you can easily modify my code. It would be easy to do, because it is not written in such an ad-hoc style as yours. Smile | :) .

Trapper-Hell 3-Feb-13 15:11pm
Your project seems really detailed and should also prove to be helpful for my application. However, can you kindly point out what I have done wrong or why this is not working? Thanks
It seems impractical as it is implemented in ad-hoc way and so can only be useful as some research step. As such, it should work. If you override this method for a right class though... What class is that, by the way?
Trapper-Hell 4-Feb-13 3:01am
I updated the question to include the complete code of the class (form). There is nothing much to it really, since it's just meant as a simple test. I will use your application, since it seems really useful, but for now I'm just trying to understand why the WndProc is never having a Msg equal to the set of integers I defined.

Looks correct, but I believe it's only one part of partial class. Do you have other controls, the form's children? It can be the problem. As some of them can get keyboard focus, the keyboard events can be dispatched to some child instead of the form. To make sure everything else is correct, try a form without any children. If that works, try Form.KeyPreview...
Trapper-Hell 4-Feb-13 3:41am
Correct! I removed the textbox and the WndProc started working correctly (showing the 'Test' message box).

I have then re-inserted the textbox and enabled the form's KeyPreview property, however it is still not capturing the keys in the WndProc. Is there a way to capture the keys in WndProc while having the textbox focused?

Thanks a lot!
Needs some thinking... Apparently, true KeyPreview value allows you to handle KeyUp and KeyDown events of the form, but I don't know exactly how it's implemented in Forms. By the way, what's wrong with just handling of the events? As you only need keyboard events, it will give you the same results... (In contrast to my demo where I wanted to show a number of arbitrary messages, to demonstrate the concept.)
Trapper-Hell 4-Feb-13 5:27am
The reason why I want to handle the key events through the WndProc is to get the Scan Codes and Virtual Key codes, and it seems to be far more practical to retrieve those values through the WndProc. However, ideally I would be able to display the characters being typed anyway (besides tracking their scan & virtual key codes).

If you come up with any idea on how this can be established let me know. I am however willing to accept your answer as the solution.
OK. It looks like KeyPreview does not work on WndProc (which is not the native window procedure, by the way). But! Your text box also has WndProc. So, you can override this method, where it is applicable, for this child and other children. You can develop a universal method (static, for example, with explicit instance parameter instead of "this") and call it from all overridden WndProc method. Alternatively, you can call parent's DefWndProc from the child's WndProc and do all the processing in parent.

Other alternatives include:
1) Replace Application.Run with the raw GetMessage/DispatchMessage methods you can get via P/Invoke
2) Use Windows hooks (not global, so you won't need a native DLL), also using P/Invoke.

I can provide you with some detail; if something is not clear, your follow-up questions are welcome.

Trapper-Hell 5-Feb-13 3:51am
Researching on what you have said, I can create a custom Textbox (inheriting the base Textbox) and be able to handle the WndProc events then. So yes, that definitely does answer the question.

If you would like, for the sake of being thorough, can you kindly provide more insight on which P/Invoke entry points to use through the alternative methods mentioned - and how the GetMessage / DispatchMessage differs from the the WndProc message?

I will accept your solution though for the time taken on this issue and the thoroughness in your answers. Thank you so much :)
Unfortunately, I don't know some detail of implementation of Forms.Application, but of course they are different things. GetMessage/Dispatch message makes a main message loop of application, but the WndProc is a CLI method called withing of the "real" window procedure of a raw Windows window (not application, which has more then one window; your TextBox is a windows, for example). This is clear.

What I don't know exactly, is how KeyPreview is implemented, I can only speculate. It looks like the system collects all keyboard events of all windows (such as controls) which can handle such events and "artificially" dispatches it to the Form events (invoke them on events from children). And does not dispatch to WndProc... Actually, FCL source code is available for debugging purpose, so it can be download from Microsoft and studied; so, if you need it...

OK, thanks for accepting the answer; the question was interesting enough.
Good luck, call again.
Trapper-Hell 7-Feb-13 3:14am
Great insight and descriptive answer. Also thanks for your thoughts about how the textbox might actually work, and for suggesting FCL.
FCL simply means "Framework Class Library", just a collection of assemblies installed in GAC, all what comes with .NET Framework... My suggestion was about debug version of .NET available from Microsoft. I used it long time ago, so I would need to do the search again to find it.

You are very welcome.
Good luck, call again.
Espen Harlinn 3-Feb-13 18:58pm
Now, that's a really useful link :-D
Thank you, Espen.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month

Advertise | Privacy | Mobile
Web04 | 2.8.151125.3 | Last Updated 4 Feb 2013
Copyright © CodeProject, 1999-2015
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100