Click here to Skip to main content
Click here to Skip to main content

Using IMessageFilter to create a generic filter for operating system events

By , 15 Oct 2003
 

Introduction

The IMessageFilter class in .NET framework allows an application to capture a windows OS message before it is dispatched to a control or form. A class that implements the IMessageFilter interface can be added to the application's message pump to filter out a message or perform other operations before the message is dispatched to a form or control. Disabling the keys at the forms level leads to lot of code repetition and something that doesn’t look very elegant. The solution provides a generic solution to the problem by separating the implementation from the UI.

Background

The requirement that lead to this solution was, conditional Enabling/Disabling specified keys on a windows form.

Using the code

On click of button3 the keys passed are disabled and enabled again on click of button4. Although the solution addresses the Key_Pressed event only, it can be extended to filter any operating system event.

private void button3_Click(object sender, System.EventArgs e) 
{ 
  mobjMessageFilter = new MessageFilter(); 
  mobjMessageFilter.KeysToRestrict=new int[]{
    Convert.ToInt32(MessageFilter.VirtualKeys.VK_F2), 
    Convert.ToInt32(MessageFilter.VirtualKeys.VK_F1)}; 
  Application.AddMessageFilter(mobjMessageFilter); 
}
 
private void button4_Click(object sender, System.EventArgs e) 
{ 
  Application.RemoveMessageFilter(mobjMessageFilter); 
} 

The MessageFilter Class

MessgeFilter class implements the IMessageFilter interface and gives the concrete implementation of the Message Filter.

public class MessageFilter:IMessageFilter

The VirtualKeys enumeration

This Enumeration contains virtual key values sent by the operating system when a key is pressed.

public enum VirtualKeys : int 
{ 
VK_LBUTTON = 0x01, 
VK_RBUTTON = 0x02, 
VK_CANCEL = 0x03, 
VK_MBUTTON = 0x04, 
VK_XBUTTON1 = 0x05, 
VK_XBUTTON2 = 0x6, 
VK_BACK = 0x08, 
VK_TAB = 0x09, 
VK_RETURN = 0x0D, 
VK_SHIFT = 0x10, 
VK_CONTROL = 0x11, 
VK_ESCAPE = 0x1B, 
VK_SPACE = 0x20, 
VK_LEFT = 0x25, 
VK_UP = 0x26, 
VK_RIGHT = 0x27, 
VK_DOWN = 0x28, 
VK_DELETE = 0x2E, 
VK_F1 = 0x70, 
VK_F2 = 0x71, 
VK_F3 = 0x72, 
VK_F4 = 0x73, 
VK_F5 = 0x74, 
VK_F6 = 0x75, 
VK_F7 = 0x76, 
VK_F8 = 0x77, 
VK_F9 = 0x78, 
VK_F10 = 0x79, 
VK_F11 = 0x7A, 
VK_F12 = 0x7B, 
VK_F13 = 0x7C, 
VK_F14 = 0x7D, 
}

The WindowsMessages enumeration

This enumeration contains the WindowsMessage value for various Operating System events. Included code contains an exhaustive listing of windows messages.

private enum WindowsMessages: int 
{ 
WM_KEYDOWN = 0x0100 
}

And now to the implementation of the MessageFilter class. It in fact is very simple, all we have to do is give an implementation for the PreFilterMessage method, I have created a property int[] KeysToRestrict to accept the values of the keys to be filtered. And here is what the method looks like,

private enum WindowsMessages: int
{
  WM_KEYDOWN = 0x0100
}

public bool PreFilterMessage(ref Message objMessage)
{
  //Check if the Message is a windows Key down message
  if(objMessage.Msg == Convert.ToInt32(WindowsMessages.WM_KEYDOWN))
  {
    for(int i=0;i<marrKeysToRestrict.Length;i++)
    {
      //Check if the Message's WParam(the key value) is 
in the restricted keys list
      if( objMessage.WParam.ToInt32() == 
marrKeysToRestrict[i])
      //Disable message propagation
      return true;
    }
  }
 return false;
} 

The method returns true if the Message objects WParam property is equal to any element in the array thus disabling the key.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

sbkar
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionIMessageFilter does not work on Dialog boxesmemberRoss Brigoli21 Jan '09 - 17:52 
I am using WebBrowser control on my Form. When the IE's "Find" dialog is displayed, it seems like the windows messages is directed to the dialog and not to the main form.
 
Do you have any solution on how to capture messages received by the modal dialog?
 
-Ross

GeneralMesage FiltersmemberRoryHerman18 Sep '08 - 21:55 
Thank you for the example.
GeneralWonderful Articlememberanupamaroy14 Dec '05 - 18:08 
This article is really nice Smile | :)
 
Anupama Roy
Questionpossible to use with a wedge barcode scanner?memberyogiberr22 Nov '05 - 8:45 
hiya,
 
I am trying to use a wedge barcode scanner in a winforms app.
I think the best way is to use the IMessageFilter.
 
Is there a way to capture the entire multidigit output of the wedge barcode scanner in the "PreFilterMessage"? If I could, then I could decide if the input is valid.
 
The reaon I want to do this is that I want avoid having to use business logic in the winforms app user layer.
 
I hope this question makes sense Smile | :)
 
can I clarify anything?
 
many thanks,
yogi

 
kitesurfin,
bass-slappin
AnswerRe: possible to use with a wedge barcode scanner? [modified]memberDapo Onawole25 May '07 - 6:26 
I understand ur question and I have the same problem at the moment. Were u able to get thru this?
 

-- modified at 13:22 Friday 25th May, 2007
QuestionDisposing the IMessageFilter?memberJediMasterYoder10 Jun '05 - 11:01 
Do I need to dispose the IMessageFilter before exiting the program?
QuestionVB6 Implementation?memberTAlvord@kavlico.com6 Dec '04 - 7:32 
Is there something similar available for VB6? I want to trap all TitleBar Double-Clicks...
 
Thanks,
 
Tim
GeneralThx a lotmemberSteven Wilssens28 Apr '04 - 2:20 
Thx great article!Smile | :)
GeneralJust a notememberLee Alexander16 Oct '03 - 6:24 
It's all very well using IMessageFilter but be aware that it won't work if the control is part of a COM control. We had a problem where we were using it and it worked fine in the WindowsForms application, but never got called whilst running under an MFC application via COM. The reason for this being the hosting application is in charge of the message pump. We got around this by creating hook a policy. Under COM the policy invoked was one that used windows hooks, and under pure windows forms we used the IMessageFilter approach.
 
Just my two pennies worth Poke tongue | ;-P
 
Regards
Lee
GeneralRe: Just a noteeditorHeath Stewart20 Nov '03 - 2:18 
You bogged down the system with Windows Hooks just for a single control? OMG | :OMG:
 
Why didn't you just override WndProc in the control which is the window callback procedure. All messages go through it and won't hamper the system. This would be no different than if the COM control had been written in C/C++. It's what you're "supposed" to do.
 
 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
GeneralRe: Just a notememberLee Alexander23 Nov '03 - 22:21 
>You bogged down the system with
>Windows Hooks just for a single control?
No there not global so they wouldn't "bog down the system". They are also only hooked whilst there is a listener.
 
We wanted control at this level specifically to catch keyboard input and mouse movement (without mouse capture) for a special pop up window (auto complete) that does not take windows activation but in reality does. This was needed so that when the auto-complete window popped up the current popup window (could be a dialog or framewindow) did not lose activation.
 
Regards
Lee
GeneralRe: Just a noteeditorHeath Stewart24 Nov '03 - 4:37 
You're right - when the listener is active and the hook is registered is the only time that hook is active - but it's still active for the whole system and this bogs down the system.
 
The auto-complete Window - if it doesn't use the WS_EX_NOPARENTNOTIFY extended style - would still pass messages to its parent. It's better to handle such notifications at a granular scale rather than using a system hook that intercepts ALL system messages of a particular type.
 
 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
GeneralRe: Just a notememberLee Alexander28 Nov '03 - 0:12 
>but it's still active for the whole system and this bogs down the system.
Do you mean system as in application or system as in OS? The only only hooks we use are application specific, not OS global ones.
 
>The auto-complete Window - if it doesn't use
>the WS_EX_NOPARENTNOTIFY extended style -
>would still pass messages to its parent.
I'm not sure what you mean here. The point with the hooks was to stop the frame from being de-activated because the auto-complete window has WS_POPUP style which is needed (I'm pretty sure) so as to get it top-level. We needed to stop the auto-complete being activated so the frame didn't lose its activation but a side effect of that is you no longer get keyboard messages and losing focus behaviour. If it were merely a child then it would be obscured by the "parent" editor window in certain circumstances.
GeneralRe: Just a notememberSantosh Rao17 Aug '05 - 20:18 
Hi,
 
I encountered a similar problem, when hosting a Windows Forms User Control, in IE. The IMessageFilter will not just work.
 
Would it be possible to point what how to go about "creating the hook" or getting hold of the message pump. The User Control is developed in Windows Form and .NET 2.0.
 
It will be really helpful.
 
Regards,
Santosh Rao
GeneralRe: Just a notememberLee Alexander17 Aug '05 - 21:37 
There's quite a few articles on CodeProject about hooks using the framework.
GeneralRe: Just a notememberSantosh Rao17 Aug '05 - 22:32 
Thanks for the same.
 
This thing about Message Pumps and Framework got me quite irritated.
 

What would .NET have been with DLLIMPORT
 
As usual Code Project is still the good old place for all Goodies
 
http://www.codeproject.com/csharp/globalhook.asp[^]
 
http://www.codeproject.com/csharp/GlobalSystemHook.asp[^]
GeneralRe: Just a notememberSantosh Rao17 Aug '05 - 22:29 
Hi,
 
Got the solution. Just thought of sharing.
 
HOW TO: Set a Windows Hook in Visual C# .NET
 
http://support.microsoft.com/?kbid=318804
 
Regards,
Santosh Rao

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 16 Oct 2003
Article Copyright 2003 by sbkar
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid