Blog
Articles and information on C# and .NET development topics

Using message filters in Windows Forms applications

For a utility application, I wanted to add an item in the system menu. It's been quite a long time since I last did this (and was in VB6), so I decided to find some ready made source code. This class provides a nice little helper for wrapping the system menu to add new commands to it, but it requires the owner form to hook into its window procedure and forward messages on which I felt was an awkward design.

The code snippets below should illustrate my point - first we initialise the instance of the SystemMenu class, but in order for custom commands to be processed we have to override to override the form's WndProc and pass any messages received into the SystemMenu class.

This definitely isn't an ideal situation! As WndProc is protected and there is no equivalent event, perhaps the original author of this code thought this was the only solution. Fortunately there is a (little used?) feature of Windows Forms that can inspect and manipulate source messages at an application level.

Introducing Message Filters

The static Application class has the AddMessageFilter and RemoveMessageFilter methods, both of which accept a single parameter - an object implementing the IMessageFilter interface. This interface has a single method, PreFilterMessage, allowing you to inspect a message and then either allow it to be dispatched or blocked ("eaten").

Warning! Caution is advised when dealing with message filters. The MSDN documentation notes that adding filters can degrade application performance but you can also adversely effect your application if you accidentally block messages you shouldn't.

Implementing a message filter

Lets take the SystemMenu class from the start of the article. I've stripped out as much as the code as possible to try and focus only on message filtering.

This empty implementation returns false to ensure we don't eat any messages. If instead we returned true then our application would be completely broken - it wouldn't paint and you wouldn't be able to interact with anything on it.

With that said, a message filter that doesn't do anything is a bit of a waste, so I'll remove the public HandleMessage method and wrap its code into PreFilterMessage. I also need to adjust OnSysCommandMessage to return a result code as well - again, if you swallow all WM_SYSCOMMAND messages then your custom actions might work but the default ones like Close, Maximize, etc won't - and as this is an application filter it will break all of your application windows.

Also, I added a check to make sure that the WM_SYSCOMMAND message is destined for our owner form - there's no point intercepting it for other forms in our application.

If we now run the application, we'll find that our SystemMenu class is now self contained and working perfectly.

Removing the filter

Once we've finished with the filter we should remove it - in this example, once the form is closed there isn't much point in waiting for messages that will never arrive. We could make the class disposable via the IDisposable interface but as the Form object has a FormClosed event we can use that and free the caller of having to anything except "fire and forget".

Once again, I modify the constructor, this time to wire up the event, and then supply the event handler itself.

As well as removing the handler, I detach the event and free up objects as well, on the assumption that nothing else is going to be done with the class.

Wrapping up

Although you probably won't have much call to use them, message filters can be useful when dealing with certain windows messages. I originally became aware of them when I needed to have mouse wheel scrolling working on a control without focus and now again for this generic system menu class.

About The Author

The founder of Cyotek, Richard enjoys creating new blog content for the site. Much more though, he likes to develop programs, and can often found writing reams of code. A long term gamer, he has aspirations in one day creating an epic video game. Until that time, he is mostly content with adding new bugs to WebCopy and the other Cyotek products.

Leave a Comment

While we appreciate comments from our users, please follow our posting guidelines. Have you tried the Cyotek Forums for support from Cyotek and the community?

Your name:

Your email address: (optional, will never be displayed)

Your URL: (optional)

Comments

Comment

Styling with Markdown is supported

Search

Donate

This content may be used free of charge, but as with all free content there are costs involved to develop and maintain.

If this site or its services have saved you time, please consider a donation to help with running costs and timely updates.