Welcome!

Microsoft Cloud Authors: Liz McMillan, David H Deans, Pat Romanski, Janakiram MSV, Jnan Dash

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 CA Technologies has been named “Platinum Sponsor” of SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY, and the 21st International Cloud Expo®, which will take place October 31-November 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. CA Technologies helps customers succeed in a future where every business – from apparel to energy – is being rewritten by software. From ...
    Web Real-Time Communication APIs have quickly revolutionized what browsers are capable of. In addition to video and audio streams, we can now bi-directionally send arbitrary data over WebRTC's PeerConnection Data Channels. With the advent of Progressive Web Apps and new hardware APIs such as WebBluetooh and WebUSB, we can finally enable users to stitch together the Internet of Things directly from their browsers while communicating privately and securely in a decentralized way.
    SYS-CON Events announced today that HTBase will exhibit at SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. HTBase (Gartner 2016 Cool Vendor) delivers a Composable IT infrastructure solution architected for agility and increased efficiency. It turns compute, storage, and fabric into fluid pools of resources that are easily composed and re-composed to meet each application’s needs. With HTBase, companies can quickly prov...
    SYS-CON Events announced today that Outlyer, a monitoring service for DevOps and operations teams, has been named “Bronze Sponsor” of SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. Outlyer is a monitoring service for DevOps and Operations teams running Cloud, SaaS, Microservices and IoT deployments. Designed for today's dynamic environments that need beyond cloud-scale monitoring, we make monitoring effortless so you ...
    SYS-CON Events announced today that MobiDev, a client-oriented software development company, will exhibit at SYS-CON's 20th International Cloud Expo®, which will take place June 6-8, 2017, at the Javits Center in New York City, NY, and the 21st International Cloud Expo®, which will take place October 31-November 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. MobiDev is a software company that develops and delivers turn-key mobile apps, websites, web services, and complex softw...
    In his General Session at 17th Cloud Expo, Bruce Swann, Senior Product Marketing Manager for Adobe Campaign, explored the key ingredients of cross-channel marketing in a digital world. Learn how the Adobe Marketing Cloud can help marketers embrace opportunities for personalized, relevant and real-time customer engagement across offline (direct mail, point of sale, call center) and digital (email, website, SMS, mobile apps, social networks, connected objects).
    SYS-CON Events announced today that Hitrons Solutions 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. Hitrons Solutions Inc. is distributor in the North American market for unique products and services of small and medium-size businesses, including cloud services and solutions, SEO marketing platforms, and mobile applications.
    With the introduction of IoT and Smart Living in every aspect of our lives, one question has become relevant: What are the security implications? To answer this, first we have to look and explore the security models of the technologies that IoT is founded upon. In his session at @ThingsExpo, Nevi Kaja, a Research Engineer at Ford Motor Company, will discuss some of the security challenges of the IoT infrastructure and relate how these aspects impact Smart Living. The material will be delivered i...
    Your homes and cars can be automated and self-serviced. Why can't your storage? From simply asking questions to analyze and troubleshoot your infrastructure, to provisioning storage with snapshots, recovery and replication, your wildest sci-fi dream has come true. In his session at @DevOpsSummit at 20th Cloud Expo, Dan Florea, Director of Product Management at Tintri, will provide a ChatOps demo where you can talk to your storage and manage it from anywhere, through Slack and similar services ...
    SYS-CON Events announced today that Cloudistics, an on-premises cloud computing company, has been named “Bronze Sponsor” of SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. Cloudistics delivers a complete public cloud experience with composable on-premises infrastructures to medium and large enterprises. Its software-defined technology natively converges network, storage, compute, virtualization, and management into a ...
    Keeping pace with advancements in software delivery processes and tooling is taxing even for the most proficient organizations. Point tools, platforms, open source and the increasing adoption of private and public cloud services requires strong engineering rigor - all in the face of developer demands to use the tools of choice. As Agile has settled in as a mainstream practice, now DevOps has emerged as the next wave to improve software delivery speed and output. To make DevOps work, organization...
    My team embarked on building a data lake for our sales and marketing data to better understand customer journeys. This required building a hybrid data pipeline to connect our cloud CRM with the new Hadoop Data Lake. One challenge is that IT was not in a position to provide support until we proved value and marketing did not have the experience, so we embarked on the journey ourselves within the product marketing team for our line of business within Progress. In his session at @BigDataExpo, Sum...
    SYS-CON Events announced today that Ocean9will exhibit at SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. Ocean9 provides cloud services for Backup, Disaster Recovery (DRaaS) and instant Innovation, and redefines enterprise infrastructure with its cloud native subscription offerings for mission critical SAP workloads.
    DevOps is often described as a combination of technology and culture. Without both, DevOps isn't complete. However, applying the culture to outdated technology is a recipe for disaster; as response times grow and connections between teams are delayed by technology, the culture will die. A Nutanix Enterprise Cloud has many benefits that provide the needed base for a true DevOps paradigm.
    With major technology companies and startups seriously embracing Cloud strategies, now is the perfect time to attend @CloudExpo | @ThingsExpo, June 6-8, 2017, at the Javits Center in New York City, NY and October 31 - November 2, 2017, Santa Clara Convention Center, CA. Learn what is going on, contribute to the discussions, and ensure that your enterprise is on the right path to Digital Transformation.
    SYS-CON Events announced today that T-Mobile will exhibit at SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. As America's Un-carrier, T-Mobile US, Inc., is redefining the way consumers and businesses buy wireless services through leading product and service innovation. The Company's advanced nationwide 4G LTE network delivers outstanding wireless experiences to 67.4 million customers who are unwilling to compromise on ...
    SYS-CON Events announced today that SoftLayer, an IBM Company, has been named “Gold Sponsor” of SYS-CON's 18th Cloud Expo, which will take place on June 7-9, 2016, at the Javits Center in New York, New York. SoftLayer, an IBM Company, provides cloud infrastructure as a service from a growing number of data centers and network points of presence around the world. SoftLayer’s customers range from Web startups to global enterprises.
    SYS-CON Events announced today that CrowdReviews.com has been named “Media Sponsor” of SYS-CON's 20th International Cloud Expo, which will take place on June 6–8, 2017, at the Javits Center in New York City, NY. CrowdReviews.com is a transparent online platform for determining which products and services are the best based on the opinion of the crowd. The crowd consists of Internet users that have experienced products and services first-hand and have an interest in letting other potential buyers...
    The taxi industry never saw Uber coming. Startups are a threat to incumbents like never before, and a major enabler for startups is that they are instantly “cloud ready.” If innovation moves at the pace of IT, then your company is in trouble. Why? Because your data center will not keep up with frenetic pace AWS, Microsoft and Google are rolling out new capabilities In his session at 20th Cloud Expo, Don Browning, VP of Cloud Architecture at Turner, will posit that disruption is inevitable for c...
    SYS-CON Events announced today that Infranics will exhibit at SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. Since 2000, Infranics has developed SysMaster Suite, which is required for the stable and efficient management of ICT infrastructure. The ICT management solution developed and provided by Infranics continues to add intelligence to the ICT infrastructure through the IMC (Infra Management Cycle) based on mathemat...