Welcome!

Microsoft Cloud Authors: Janakiram MSV, Pat Romanski, Steven Mandel, John Basso, Liz McMillan

Related Topics: Microsoft Cloud

Microsoft Cloud: Article

.NET Makes Window Subclassing Easy - Tap into Windows OS messages

.NET Makes Window Subclassing Easy - Tap into Windows OS messages

Imagine you are coding a .NET application that must perform some logic when a CD is inserted into the drive. Unfortunately, there is no standard event visible to your application that gets fired when a CD is inserted. Windows knows when a user puts a CD in the drive, but how can it notify your application? In fact, Windows does notify your app by sending a Windows message - your app just isn't listening for it. Subclassing gives us the ability to listen for that message and handle it appropriately. In this article, you'll learn how to use subclassing to handle the many Windows messages that are sent by the OS but not exposed through .NET's eventing model. We'll start with the basics of Windows messaging, discuss how to subclass in .NET, and finally we'll look at some more advanced techniques.

Introduction
Subclassing can be defined as intercepting window message processing in an attempt to modify the default behavior. Window subclassing gives us the ability to tap into the various messages that the Windows operating system sends and to use this ability to change our application's behavior. Windows subclassing is different from object-oriented (OO) subclassing. Windows subclassing deals with overriding a window's message handler, while OO subclassing refers to deriving a class from a base class. An implementation of Windows subclassing can be a form of OO subclassing. We'll see more about that when we discuss the various Windows subclassing implementations. But first, to truly understand Windows subclassing (hereafter referred to as simply subclassing) you must understand how the Windows operating system uses messages.

Basics of Windows Messaging
The Windows operating system is a message-based system, which means it communicates by sending messages. The OS communicates with all running applications through messages. When an application should be minimized, the OS sends a message. When an application should be closed, the OS sends a message. When a user moves a scroll bar, the OS sends a message. So what are these messages? The .NET structure created to represent a message looks like this:

public struct System.Windows.Forms.Message
{
public IntPtr HWnd { get; set;
}
public IntPtr LParam { get;
set; }
public int Msg { get; set; }
public IntPtr Result { get;
set; }
public IntPtr WParam { get;
set; }
}
The message is basically a structure used to package up and send data between windows and the OS. Let's take a look at the properties of a message:
  • HWnd: The window handle that identifies which window the message should be sent to. A window handle is basically a unique identifier for a window.
  • LParam: Contains information used to process the message. This data varies by message type.
  • Msg: Identifies the type of message that was sent.
  • Result: The return value. This is what is sent back to the OS after the message is handled.
  • WParam: Contains information used to process the message. This data varies by message type.

    If you wonder why these parameters have strange C-style names such as WParam, it's because this .NET structure is wrapping an existing C structure (MSG). Now that you understand what a message looks like, let's see how a message flows from the OS to a window.

    When a user clicks a button on a window, the mouse's device driver captures the click event. The device driver puts the event into the system message queue, which is basically a FIFO data structure set up by the OS to receive all hardware events. The OS then pulls the hardware event off the system message queue and converts it into a true Windows message. The OS then posts the message to the local message queue on the thread that is running the clicked window. The application that owns that window constantly polls the local queue for messages.

    This constant polling of the local message queue is basically a while loop that looks something like this:

    while(GetMessage(ref msg, null, 0, 0))
    {
    TranslateMessage(ref msg);
    DispatchMessage(ref msg);
    }
    This loop is built into an application by the WinForms framework. It is often referred to as the "message loop" or "message pump" because its job is to send or pump messages to the application. Let's look at some of the win32 API calls used in the message loop:
  • GetMessage: Retrieves a message from the calling thread's message queue
  • TranslateMessage: Translates virtual-key messages into character messages
  • DispatchMessage: Posts the message to the appropriate window procedure

    A message loop is required for any thread that displays a window. A message loop is created by the WinForms framework when the application code calls Application.Run. If you look at the code that is created with a new WinForms project, you'll see something that looks like this:

    static void Main()
    {
    Application.Run(new Form1());
    }
    The one line in the main method starts a message loop for the current thread and shows Form1. A message loop can be destroyed by calling Application.Exit. This method posts a WM_QUIT message to the current thread's message queue. This special message causes the GetMessage function to return false and break out of the loop.

    Now that we have a loop to retrieve messages from our thread's message queue, we have to get those messages to the appropriate window and process them. That is just what the DispatchMessage function does - it takes the message and posts it to the appropriate window. DispatchMessage uses the Hwnd associated with the message to determine which window to post the message to. To be even clearer, the DispatchMessage function actually calls a special function called the window procedure, passing in the message as a parameter. The window procedure is the function that is created to handle window messages sent to the window. It looks something like Listing 1.

    The window procedure usually consists of a big case statement. Different actions are taken depending on the window message. If a WM_PAINT is sent, the window will repaint itself. If a WM_DESTROY is sent, the window will post another message to break out of its message loop and shut down. Finally, after processing the messages, the default window procedure for the class is called. This ensures that all necessary window message handling is performed by the base window class. Subclassing consists of overriding this window procedure and providing our own custom logic to handle messages. I'll show how that is done in the next section.

    How to Subclass in .NET
    .NET truly makes subclassing easy. And for those of you used to subclassing in VB6, you no longer have to worry about General Protection Faults (GPFs) occurring if you make a mistake. In .NET there are three ways to subclass: overriding the Control.WndProc method, creating a class derived from NativeWindow, and implementing IMessageFilter. We will look at all three options, along with their pros and cons. First let's see how to override WndProc.

    One of the easiest ways to subclass in .NET is to override the WndProc method of the form you are working on. Listing 2 shows how to do this. That's it!

    .NET makes it easy for you because it exposes the virtual WndProc method on the Control class, which all windows inherit from. In order to handle a message you need to know the unique number that identifies it. The definitions for windows messages and their ID numbers can be found in the <install drive>:Program FilesMicrosoft Visual Studio .NETVc7PlatformSDKIncludeWinUser.h file. Once you know the number, it is trivial to create a constant and hook that message the way the sample code does for the double-click message. (All of the code for this article is available for download from www.sys-con.com/dotnet/sourcec.cfm.) As a side note, apart from demonstration purposes, you don't really want to show message boxes in your WndProc because that will stop the procedure from processing messages until the user clicks OK. Any messages that are not handled by your custom code are passed on to the Control's WndProc to be handled by calling base.WndProc. This allows you to handle only the messages you are interested in without having to re-implement the base Windows procedure and handle all possible messages sent to the window. The call to the base WndProc is critical, as this window will not function if key messages are not handled.

    For demonstration purposes I handled the double-click, but you may wonder what the point is of handling a message that .NET already exposes as a form event. There would be no reason to handle the double-click other than to show how subclassing works. The real power of subclassing comes from handling messages that are not exposed through the .NET eventing model. We'll look at some of those messages later, but first let's look at the second way to subclass in .NET - by using NativeWindow.

    Overriding WndProc is definitely the easiest way to subclass in .NET but it does have its drawbacks, mainly the fact that your subclassing code is now tied to one window. What if you want to use the same subclassing code on two other windows? Wouldn't it be better if you could define subclassing logic on a generic window and then use that code with other windows?

    The System.Windows.Forms .NativeWindow class does just that. It is basically an encapsulation of a Windows handle and a window procedure. It represents the roots of a window. Listing 3 shows how we use the NativeWindow class to achieve our goal of reusable message-handling code.

    Note that this code is very similar to the subclassing code shown in Listings 1 and 2. We still override WndProc, but the main difference is that we do it inside a class that inherits from NativeWindow. Remember, the NativeWindow class consists of a window procedure that we have overridden and a window handle that we assign via the AssignHandle method. We can now associate our subclassing code with any window by using the AssignHan dle method.

    There is one other way to assign subclassing code to multiple windows. We can implement the System.Windows.Forms.IMessageFilter interface. This will allow us to filter and react to all messages sent to a thread's message loop. The difference between this method and the other two is that this method intercepts messages right after they leave the thread's message loop, while the others do not intercept the messages until they are dispatched to the appropriate window. This gives us a much more global approach in that we can capture all messages sent to all windows on a thread (see Listing 4).

    Again the code looks very similar to the other examples, but instead of deriving from a base or overriding a method, we implement an interface. The one method of the interface, PreFilterMessage, passes us the message that was sent to the thread's message queue. We now have a chance to process it before this message is sent to any window. We can take action based on the message, modify it or even discard it. If the PreFilterMessage method returns true, the message is sent to the appropriate window(s). If the method returns false, then the message is discarded without being sent to any windows.

    One thing to note in regard to this method of subclassing is that not all messages go through the thread's message queue and therefore through this method. Messages can be sent in one of two ways - by being dispatched through the message queue or by being sent directly to the window and bypassing the queue. The latter type will not flow through our filter because they will go directly to the window. The way a message is sent is determined by the sender. They can use a variant of two win32 API calls:

  • SendMessage: Sends the message directly to the window
  • PostMessage: Dispatches the message to the window thread's message queue

    So the filter intercepts messages earlier than the other two subclassing methods, but as a consequence it will not receive messages that are sent directly to the window.

    Overriding WndProc is the easiest way to subclass and will intercept all messages whether posted or sent, but the subclassing code is not reusable. Inheriting from NativeWindow provides a way to receive all messages and reuse code but requires you to pass the handle of all windows whose messages should be intercepted. Finally, implementing IMessageFilter intercepts the messages for all windows created on a thread, but does not receive messages that are sent directly to the window. Now that you know the various ways to subclass in .NET, let's look at a practical example of what we can do with subclassing.

    Adding New Events Through Subclassing
    The true power in subclassing can be seen when you begin to handle messages that are not already exposed as events. For example, the DoubleClick event is already exposed as an event of a Form, but there is no event that is raised when a CD is inserted in the drive and ready for use. A good use of subclassing is to capture these kind of events that the OS communicates through Windows messages but the WinForms framework does not expose as events. Listing 5 shows how we would capture device changes such as CD inserted and removed:

    For this example we've taken the simplest approach of overriding WndProc. I want to intercept only the messages for the application's main window, so there's no need to use NativeWindow or IMessageFilter. In my overridden WndProc I simply look for the WM_DEVICECHANGE message that the OS sends to all windows when a CD is inserted or removed. I then check the message's WParam, which provides additional data about the message. In this case it specifies whether a CD was inserted or removed. That's all there is to it.

    Conclusion
    With this example, you can begin to see the possibilities of subclassing. The OS sends many messages that are not incorporated into the WinForms framework. By handling them via subclassing you can easily add new features to an application without resorting to Win32 API calls or unmanaged code.

  • More Stories By Bryant Hankins

    Bryant Hankins is a consultant at Clarity Consulting Inc., a Chicago-based information technology firm and Microsoft Gold Certified Partner. Bryant has designed and developed solutions for Fortune 500 companies in a variety of industries, including financial, accounting, and publishing.

    Comments (7) View Comments

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


    Most Recent Comments
    ramesh.kumar 06/20/09 03:22:00 AM EDT

    Wonderful article indeed. Loads of information at one place. Just one correction about the PrefilterMessage return value of the IMessageFilter :
    "If the PreFilterMessage method returns true, the message is sent to the appropriate window(s). If the method returns false, then the message is discarded without being sent to any windows."
    Isn't it other way round?
    If the method returns true, the message is discarded and if return false the message is sent to appropriate window(s).

    Rajesh 01/30/08 05:10:55 PM EST

    Hi

    It really a nice article. The way you have written the article is simply wonderful.

    Mahesh Kumara 12/15/06 07:05:53 AM EST

    I want to monitor the Windows CE OS Messages.
    But the MessageWindow Class In CompactFramework doesn't support to achive that.
    Is there any other way to achive this?
    Thanks very much
    Mahesh Kumara

    Andrew Hallonquist 10/18/06 11:42:56 AM EDT

    Thank you for this very helpful article. I was trying to implement IMessageFilter to intercept private messages from another legacy application and it just was not working. Your article not only explained why it was not working, it gave me 2 other possible implementations and taught me a lot about how this all works. Thanks

    sbuchmann 09/22/05 08:03:41 AM EDT

    Good article !
    But the 3 samples you give are only concenring the Application scope.
    Can you provide some more informations on the way to treat window messages raised by other applications or by the Desktop for exemple ?
    Is there a .NET way of doing that or do we have to use hooks and APIs ?
    Thanks.

    J Parsons 10/28/04 05:55:57 PM EDT

    VB code for Listing 5: CD Insert

    Private Const WM_DEVICECHANGE As Integer = 537
    Private Const DBT_DEVICEREMOVECOMPLETE As Integer = 32772
    Private Const DBT_DEVICEARRIVAL As Integer = 32768

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    'Handle the CD messages
    Select Case m.Msg
    Case WM_DEVICECHANGE
    If (m.WParam.ToInt32() = DBT_DEVICEREMOVECOMPLETE) Then
    MessageBox.Show("CD Removal Complete!")
    ElseIf (m.WParam.ToInt32() = DBT_DEVICEARRIVAL) Then
    MessageBox.Show("CD Now Avaiable!")
    End If
    Case Else
    'Call base WndProc for default handling
    MyBase.WndProc(m)
    End Select
    End Sub

    Grig Petrescu 09/24/04 04:43:37 AM EDT

    Great !.
    Thank you.

    @ThingsExpo Stories
    With so much going on in this space you could be forgiven for thinking you were always working with yesterday’s technologies. So much change, so quickly. What do you do if you have to build a solution from the ground up that is expected to live in the field for at least 5-10 years? This is the challenge we faced when we looked to refresh our existing 10-year-old custom hardware stack to measure the fullness of trash cans and compactors.
    The emerging Internet of Everything creates tremendous new opportunities for customer engagement and business model innovation. However, enterprises must overcome a number of critical challenges to bring these new solutions to market. In his session at @ThingsExpo, Michael Martin, CTO/CIO at nfrastructure, outlined these key challenges and recommended approaches for overcoming them to achieve speed and agility in the design, development and implementation of Internet of Everything solutions wi...
    Cloud computing is being adopted in one form or another by 94% of enterprises today. Tens of billions of new devices are being connected to The Internet of Things. And Big Data is driving this bus. An exponential increase is expected in the amount of information being processed, managed, analyzed, and acted upon by enterprise IT. This amazing is not part of some distant future - it is happening today. One report shows a 650% increase in enterprise data by 2020. Other estimates are even higher....
    Why do your mobile transformations need to happen today? Mobile is the strategy that enterprise transformation centers on to drive customer engagement. In his general session at @ThingsExpo, Roger Woods, Director, Mobile Product & Strategy – Adobe Marketing Cloud, covered key IoT and mobile trends that are forcing mobile transformation, key components of a solid mobile strategy and explored how brands are effectively driving mobile change throughout the enterprise.
    Today we can collect lots and lots of performance data. We build beautiful dashboards and even have fancy query languages to access and transform the data. Still performance data is a secret language only a couple of people understand. The more business becomes digital the more stakeholders are interested in this data including how it relates to business. Some of these people have never used a monitoring tool before. They have a question on their mind like “How is my application doing” but no id...
    Smart Cities are here to stay, but for their promise to be delivered, the data they produce must not be put in new siloes. In his session at @ThingsExpo, Mathias Herberts, Co-founder and CTO of Cityzen Data, will deep dive into best practices that will ensure a successful smart city journey.
    DevOps at Cloud Expo, taking place Nov 1-3, 2016, at the Santa Clara Convention Center in Santa Clara, CA, is co-located with 19th Cloud Expo and will feature technical sessions from a rock star conference faculty and the leading industry players in the world. The widespread success of cloud computing is driving the DevOps revolution in enterprise IT. Now as never before, development teams must communicate and collaborate in a dynamic, 24/7/365 environment. There is no time to wait for long dev...
    Identity is in everything and customers are looking to their providers to ensure the security of their identities, transactions and data. With the increased reliance on cloud-based services, service providers must build security and trust into their offerings, adding value to customers and improving the user experience. Making identity, security and privacy easy for customers provides a unique advantage over the competition.
    SYS-CON Events announced today that 910Telecom will exhibit at the 19th International Cloud Expo, which will take place on November 1–3, 2016, at the Santa Clara Convention Center in Santa Clara, CA. Housed in the classic Denver Gas & Electric Building, 910 15th St., 910Telecom is a carrier-neutral telecom hotel located in the heart of Denver. Adjacent to CenturyLink, AT&T, and Denver Main, 910Telecom offers connectivity to all major carriers, Internet service providers, Internet backbones and ...
    Almost two-thirds of companies either have or soon will have IoT as the backbone of their business in 2016. However, IoT is far more complex than most firms expected. How can you not get trapped in the pitfalls? In his session at @ThingsExpo, Tony Shan, a renowned visionary and thought leader, will introduce a holistic method of IoTification, which is the process of IoTifying the existing technology and business models to adopt and leverage IoT. He will drill down to the components in this fra...
    Internet of @ThingsExpo, taking place November 1-3, 2016, at the Santa Clara Convention Center in Santa Clara, CA, is co-located with 19th Cloud Expo and will feature technical sessions from a rock star conference faculty and the leading industry players in the world. The Internet of Things (IoT) is the most profound change in personal and enterprise IT since the creation of the Worldwide Web more than 20 years ago. All major researchers estimate there will be tens of billions devices - comp...
    Data is the fuel that drives the machine learning algorithmic engines and ultimately provides the business value. In his session at Cloud Expo, Ed Featherston, a director and senior enterprise architect at Collaborative Consulting, will discuss the key considerations around quality, volume, timeliness, and pedigree that must be dealt with in order to properly fuel that engine.
    There is growing need for data-driven applications and the need for digital platforms to build these apps. In his session at 19th Cloud Expo, Muddu Sudhakar, VP and GM of Security & IoT at Splunk, will cover different PaaS solutions and Big Data platforms that are available to build applications. In addition, AI and machine learning are creating new requirements that developers need in the building of next-gen apps. The next-generation digital platforms have some of the past platform needs a...
    19th Cloud Expo, taking place November 1-3, 2016, at the Santa Clara Convention Center in Santa Clara, CA, will feature technical sessions from a rock star conference faculty and the leading industry players in the world. Cloud computing is now being embraced by a majority of enterprises of all sizes. Yesterday's debate about public vs. private has transformed into the reality of hybrid cloud: a recent survey shows that 74% of enterprises have a hybrid cloud strategy. Meanwhile, 94% of enterpri...
    SYS-CON Events announced today Telecom Reseller has been named “Media Sponsor” of SYS-CON's 19th International Cloud Expo, which will take place on November 1–3, 2016, at the Santa Clara Convention Center in Santa Clara, CA. Telecom Reseller reports on Unified Communications, UCaaS, BPaaS for enterprise and SMBs. They report extensively on both customer premises based solutions such as IP-PBX as well as cloud based and hosted platforms.
    Pulzze Systems was happy to participate in such a premier event and thankful to be receiving the winning investment and global network support from G-Startup Worldwide. It is an exciting time for Pulzze to showcase the effectiveness of innovative technologies and enable them to make the world smarter and better. The reputable contest is held to identify promising startups around the globe that are assured to change the world through their innovative products and disruptive technologies. There w...
    The 19th International Cloud Expo has announced that its Call for Papers is open. Cloud Expo, to be held November 1-3, 2016, at the Santa Clara Convention Center in Santa Clara, CA, brings together Cloud Computing, Big Data, Internet of Things, DevOps, Digital Transformation, Microservices and WebRTC to one location. With cloud computing driving a higher percentage of enterprise IT budgets every year, it becomes increasingly important to plant your flag in this fast-expanding business opportuni...
    I wanted to gather all of my Internet of Things (IOT) blogs into a single blog (that I could later use with my University of San Francisco (USF) Big Data “MBA” course). However as I started to pull these blogs together, I realized that my IOT discussion lacked a vision; it lacked an end point towards which an organization could drive their IOT envisioning, proof of value, app dev, data engineering and data science efforts. And I think that the IOT end point is really quite simple…
    Personalization has long been the holy grail of marketing. Simply stated, communicate the most relevant offer to the right person and you will increase sales. To achieve this, you must understand the individual. Consequently, digital marketers developed many ways to gather and leverage customer information to deliver targeted experiences. In his session at @ThingsExpo, Lou Casal, Founder and Principal Consultant at Practicala, discussed how the Internet of Things (IoT) has accelerated our abil...
    Is the ongoing quest for agility in the data center forcing you to evaluate how to be a part of infrastructure automation efforts? As organizations evolve toward bimodal IT operations, they are embracing new service delivery models and leveraging virtualization to increase infrastructure agility. Therefore, the network must evolve in parallel to become equally agile. Read this essential piece of Gartner research for recommendations on achieving greater agility.