Welcome!

Microsoft Cloud Authors: David Bermingham, Jayaram Krishnaswamy, Dana Gardner, Yung Chou, Pat Romanski

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
    SYS-CON Events announced today that Alert Logic, Inc., the leading provider of Security-as-a-Service solutions for the cloud, will exhibit at SYS-CON's 18th International Cloud Expo®, which will take place on June 7-9, 2016, at the Javits Center in New York City, NY. Alert Logic, Inc., provides Security-as-a-Service for on-premises, cloud, and hybrid infrastructures, delivering deep security insight and continuous protection for customers at a lower cost than traditional security solutions. Ful...
    SYS-CON Events announced today that Interoute, owner-operator of one of Europe's largest networks and a global cloud services platform, has been named “Bronze Sponsor” of SYS-CON's 18th Cloud Expo, which will take place on June 7-9, 2015 at the Javits Center in New York, New York. Interoute is the owner-operator of one of Europe's largest networks and a global cloud services platform which encompasses 12 data centers, 14 virtual data centers and 31 colocation centers, with connections to 195 ad...
    Companies can harness IoT and predictive analytics to sustain business continuity; predict and manage site performance during emergencies; minimize expensive reactive maintenance; and forecast equipment and maintenance budgets and expenditures. Providing cost-effective, uninterrupted service is challenging, particularly for organizations with geographically dispersed operations.
    SYS-CON Events announced today that Avere Systems, a leading provider of enterprise storage for the hybrid cloud, will exhibit at SYS-CON's 18th International Cloud Expo®, which will take place on June 7-9, 2016, at the Javits Center in New York City, NY. Avere delivers a more modern architectural approach to storage that doesn’t require the overprovisioning of storage capacity to achieve performance, overspending on expensive storage media for inactive data or the overbuilding of data centers ...
    SYS-CON Events announced today that Commvault, a global leader in enterprise data protection and information management, has been named “Bronze Sponsor” of SYS-CON's 18th International Cloud Expo, which will take place on June 7–9, 2016, at the Javits Center in New York City, NY, and the 19th International Cloud Expo, which will take place on November 1–3, 2016, at the Santa Clara Convention Center in Santa Clara, CA. Commvault is a leading provider of data protection and information management...
    SYS-CON Events announced today that VAI, a leading ERP software provider, will exhibit at SYS-CON's 18th International Cloud Expo®, which will take place on June 7-9, 2016, at the Javits Center in New York City, NY. VAI (Vormittag Associates, Inc.) is a leading independent mid-market ERP software developer renowned for its flexible solutions and ability to automate critical business functions for the distribution, manufacturing, specialty retail and service sectors. An IBM Premier Business Part...
    With an estimated 50 billion devices connected to the Internet by 2020, several industries will begin to expand their capabilities for retaining end point data at the edge to better utilize the range of data types and sheer volume of M2M data generated by the Internet of Things. In his session at @ThingsExpo, Don DeLoach, CEO and President of Infobright, will discuss the infrastructures businesses will need to implement to handle this explosion of data by providing specific use cases for filte...
    Fortunately, meaningful and tangible business cases for IoT are plentiful in a broad array of industries and vertical markets. These range from simple warranty cost reduction for capital intensive assets, to minimizing downtime for vital business tools, to creating feedback loops improving product design, to improving and enhancing enterprise customer experiences. All of these business cases, which will be briefly explored in this session, hinge on cost effectively extracting relevant data from ...
    Cognitive Computing is becoming the foundation for a new generation of solutions that have the potential to transform business. Unlike traditional approaches to building solutions, a cognitive computing approach allows the data to help determine the way applications are designed. This contrasts with conventional software development that begins with defining logic based on the current way a business operates. In her session at 18th Cloud Expo, Judith S. Hurwitz, President and CEO of Hurwitz & ...
    SYS-CON Events announced today that Pythian, a global IT services company specializing in helping companies adopt disruptive technologies to optimize revenue-generating systems, has been named “Bronze Sponsor” of SYS-CON's 18th Cloud Expo, which will take place on June 7-9, 2015 at the Javits Center in New York, New York. Founded in 1997, Pythian is a global IT services company that helps companies compete by adopting disruptive technologies such as cloud, Big Data, advanced analytics, and DevO...
    With the Apple Watch making its way onto wrists all over the world, it’s only a matter of time before it becomes a staple in the workplace. In fact, Forrester reported that 68 percent of technology and business decision-makers characterize wearables as a top priority for 2015. Recognizing their business value early on, FinancialForce.com was the first to bring ERP to wearables, helping streamline communication across front and back office functions. In his session at @ThingsExpo, Kevin Roberts...
    As enterprises work to take advantage of Big Data technologies, they frequently become distracted by product-level decisions. In most new Big Data builds this approach is completely counter-productive: it presupposes tools that may not be a fit for development teams, forces IT to take on the burden of evaluating and maintaining unfamiliar technology, and represents a major up-front expense. In his session at @BigDataExpo at @ThingsExpo, Andrew Warfield, CTO and Co-Founder of Coho Data, will dis...
    SYS-CON Events announced today that iDevices®, the preeminent brand in the connected home industry, will exhibit at SYS-CON's 18th International Cloud Expo®, which will take place on June 7-9, 2016, at the Javits Center in New York City, NY. iDevices, the preeminent brand in the connected home industry, has a growing line of HomeKit-enabled products available at the largest retailers worldwide. Through the “Designed with iDevices” co-development program and its custom-built IoT Cloud Infrastruc...
    Eighty percent of a data scientist’s time is spent gathering and cleaning up data, and 80% of all data is unstructured and almost never analyzed. Cognitive computing, in combination with Big Data, is changing the equation by creating data reservoirs and using natural language processing to enable analysis of unstructured data sources. This is impacting every aspect of the analytics profession from how data is mined (and by whom) to how it is delivered. This is not some futuristic vision: it's ha...
    Silver Spring Networks, Inc. (NYSE: SSNI) extended its Internet of Things technology platform with performance enhancements to Gen5 – its fifth generation critical infrastructure networking platform. Already delivering nearly 23 million devices on five continents as one of the leading networking providers in the market, Silver Spring announced it is doubling the maximum speed of its Gen5 network to up to 2.4 Mbps, increasing computational performance by 10x, supporting simultaneous mesh communic...
    The cloud promises new levels of agility and cost-savings for Big Data, data warehousing and analytics. But it’s challenging to understand all the options – from IaaS and PaaS to newer services like HaaS (Hadoop as a Service) and BDaaS (Big Data as a Service). In her session at @BigDataExpo at @ThingsExpo, Hannah Smalltree, a director at Cazena, will provide an educational overview of emerging “as-a-service” options for Big Data in the cloud. This is critical background for IT and data profes...
    SYS-CON Events announced today that Men & Mice, the leading global provider of DNS, DHCP and IP address management overlay solutions, will exhibit at SYS-CON's 18th International Cloud Expo®, which will take place on June 7-9, 2016, at the Javits Center in New York City, NY. The Men & Mice Suite overlay solution is already known for its powerful application in heterogeneous operating environments, enabling enterprises to scale without fuss. Building on a solid range of diverse platform support,...
    One of the bewildering things about DevOps is integrating the massive toolchain including the dozens of new tools that seem to crop up every year. Part of DevOps is Continuous Delivery and having a complex toolchain can add additional integration and setup to your developer environment. In his session at @DevOpsSummit at 18th Cloud Expo, Miko Matsumura, Chief Marketing Officer of Gradle Inc., will discuss which tools to use in a developer stack, how to provision the toolchain to minimize onboa...
    SYS-CON Events announced today that Fusion, a leading provider of cloud services, will exhibit at SYS-CON's 18th International Cloud Expo®, which will take place on June 7-9, 2016, at the Javits Center in New York City, NY. Fusion, a leading provider of integrated cloud solutions to small, medium and large businesses, is the industry's single source for the cloud. Fusion's advanced, proprietary cloud service platform enables the integration of leading edge solutions in the cloud, including clou...
    Most people haven’t heard the word, “gamification,” even though they probably, and perhaps unwittingly, participate in it every day. Gamification is “the process of adding games or game-like elements to something (as a task) so as to encourage participation.” Further, gamification is about bringing game mechanics – rules, constructs, processes, and methods – into the real world in an effort to engage people. In his session at @ThingsExpo, Robert Endo, owner and engagement manager of Intrepid D...