I notice that WinForms have many methods that process commands or keys (Process*()
) and to (pre)filter system's messages, but their respective purposes remain unclear to me.
The official documentation is somewhat obscure and I haven't found any clear and complete response.
I speak about the following methods:
PreFilterMessage(ref Message m)
ProcessCmdKey(ref Message msg, Keys keyData)
WndProc(ref Message m)
ProcessDialogKey(Keys keyData)
PreProcessMessage(ref Message msg)
ProcessKeyMessage(ref Message m)
ProcessKeyPreview(ref Message m)
Some are for intercept keys (like ProcessCmdKey
or ProcessDialogKey
) and some for intercept messages (each others). But why as many methods? What are their purposes and their use cases ?
I suppose that the execution order for each method is different.
Here is what I know (or I think know):
PreFilterMessage
: first to intercept messages. You can stop the distribution of the message for all following methods here!ProcessCmdKey
: intercepts ALL keys, even combinaisons, special and command keys. Good to detect key shortcuts on the entire form (like Ctrl + D). You can stop the distribution of the keys here.WndProc
: second to intercept messages after filtering? I use it only to detect if user click on the upper right "X", but I suppose that is possible on another method!ProcessDialogKey
: intercepts ONE key only, probably after the ProcessCmdKey
and before all key's events of controls.PreProcessMessage
: before WndProc
and after PreFilterMessage
? I don't know exactly why it is used.ProcessKeyMessage
: intercepts key message. It seems that it is rarely used.ProcessKeyPreview
: intercepts key before preview event? Rarely used too.In depth, I think that it is the correct execution order:
Why so many steps?
Any informations or concrete use cases will be appreciated!
A native Windows GUI application normally has one message loop, underlying winapi call is GetMessage(). But has many windows that get messages, underlying winapi call is DispatchMessage(). In your .NET app you have one call to Application.Run() but many WndProc() methods, one for each control. Most of them are hidden in .NET Framework code, exposed only if you override it.
There is in general a need to hook into the message loop, intercepting a message before it is dispatched to the control and arrives in WndProc(). The most obvious reason is keyboard shortcuts, you want to act on them regardless which control has the focus. It would of course be very painful if you had to use KeyDown on every control to detect the shortcut. And less obvious reasons, ActiveX controls are notable for having to negotiate with their host for example.
Winforms gives lots of extension points to intercept messages. Too many, really, but a somewhat inevitable side-effect of not wanting to predict in which cases they might be useful. In order:
A twisty maze indeed.
Trying to keep it sane, always override ProcessCmdKey() to implement shortcut keys. Override IsInputKey() to let your control see the navigation keys. And only override WndProc() to customize existing controls.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With