WndProc in .NET
Why would you use WndProc in .NET? Isn't everything taken care by CLR? Well, here's one case that I had.
I have a TextBox and a DataGridView in a Form. So this TextBox is basically a ‘filter’ for the DataGridView. When I type stuff in it, I want it to be updated directly to the DataGridView. Okay, big deal.. Why would you need WndProc anyway? Well, I haven’t mentioned that I want to be able to move selected row in DataGridView from TextBox (By pressing Up or Down).
I’m not saying that this is the only solution, or it’s the “smartest” solution, but it’s the one that I choose, because logically it’s the simplest one for me (Just propagating any Up or Down key pressed from one control to another). So I came up with 2 approaches, the hard-way and the easy-way.
Hard-Way
If you have some experience in Win32 programming (which is basically the ‘low-level’ programming, lol), you might have heard something like DefWndProc, or SendMessage. Just some review (Please correct me if I’m wrong, because I haven’t touched any of these for almost half-decade lol). DefWndProc is the default window message procedure (you might know this as ‘event handler’ for WinForms) implemented by the OS. Messages in here refers to any interaction or events occurring on the control, including key pressed, window resized, and even painting the window. For example: if you press a Down arrow button, OS will send WM_KEYDOWN message to the window’s WndProc (usually forwarded to DefWndProc). SendMessage is how you can send window message to other controls (using its handle, usually called hWnd). So, this is the ‘core’ of the hard way. By using SendMessage, we can ‘simulate’ events as if it is really happening; we can simulate key pressed event too =)
Okay, so the hard-way involves SendMessage methods. But the problem is that it’s not included in .Net Framework; it’s in Win32 API. So we have to do Interop. Below is the interop code (Taken from MSDN)
C# [DllImport(“user32.dll”)] private static extern Int32 SendMessage(IntPtr hWnd, Int32 msg, Int32 wParam, Int32 lParam); VB.NET <DllImport(“user32.dll”)> Private Shared Function SendMessage(ByVal hWnd as IntPtr, ByVal msg As Int32, ByVal wParam as Int32, ByVal lParam as IntPtr) As Int32 EndFunction |
After doing the interop, all that is left is to call it. However, I haven’t tried it. If you have tried it, you can post it here =)
Easy-Way
In a way, it’s quite similar with the hard-way, but at least no interop =) In processing window messages, CLR uses System.Windows.Forms.NativeWindow class. It provides access to DefWndProc just by defining the window handle, and the message (encapsulated by System.Windows.Forms.Message class). Below is the working code snipplet I used:
txtFilter.KeyDown += delegate(object kSender, KeyEventArgs kE) { if (kE.KeyCode == Keys.Up || kE.KeyCode == Keys.Down) { NativeWindow nWnd = new System.Windows.Forms.NativeWindow(); nWnd.AssignHandle(dgDataGrid.Handle); int WM_KEYDOWN = 0x100; IntPtr wparam, lparam; // For details about wParam and lParam, you can find it in MSDN. wparam = new IntPtr((kE.KeyCode == Keys.Up) ? 0x26 : 0x28); // wparam: 0x26 = Up; 0x28 = Down lparam = new IntPtr((kE.KeyCode == Keys.Up) ? 0x1480001 : 0x1500001); Message m = Message.Create(dgDataGrid.Handle, WM_KEYDOWN, (IntPtr)wparam, (IntPtr)lparam); dgDataGrid.Focus(); nWnd.DefWndProc(ref m); (kSender as Control).Focus(); } }; |
Anyway, that’s just some simple usage of WndProc. I hope you find it useful in more challenging case =)
Cheers,
Ferry Mulyono (Microsoft Student Partner – Bina Nusantara International)