Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# KeyDown
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()
        {
            InitializeComponent();
        }
 
        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)
            {
                MessageBox.Show("Test");
            }
 
            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 7:41am
Edited 3-Feb-13 21:00pm
v3

1 solution

Rate this: bad
good
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 | :) .
 
Cheers,
—SA
  Permalink  
Comments
Trapper-Hell at 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
Sergey Alexandrovich Kryukov at 3-Feb-13 18:42pm
   
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?
—SA
Trapper-Hell at 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.
 
Thanks
Sergey Alexandrovich Kryukov at 4-Feb-13 3:16am
   
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...
—SA
Trapper-Hell at 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!
Sergey Alexandrovich Kryukov at 4-Feb-13 3:47am
   
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.)
—SA
Trapper-Hell at 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.
Sergey Alexandrovich Kryukov at 4-Feb-13 10:30am
   
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.
 
—SA
Trapper-Hell at 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 :)
Sergey Alexandrovich Kryukov at 5-Feb-13 11:58am
   
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.
—SA
Trapper-Hell at 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.
Sergey Alexandrovich Kryukov at 7-Feb-13 8:45am
   
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.
—SA
Espen Harlinn at 3-Feb-13 18:58pm
   
Now, that's a really useful link :-D
Sergey Alexandrovich Kryukov at 3-Feb-13 19:20pm
   
Thank you, Espen.
—SA

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

  Print Answers RSS
0 OriginalGriff 205
1 Sergey Alexandrovich Kryukov 165
2 jlopez788 109
3 Rob Philpott 100
4 Prakriti Goyal 97
0 OriginalGriff 6,837
1 Sergey Alexandrovich Kryukov 5,589
2 Maciej Los 3,479
3 Peter Leow 3,323
4 DamithSL 2,505


Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 4 Feb 2013
Copyright © CodeProject, 1999-2014
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