Using VS - DevSource
DevSource: Microsoft Developer Resource DevSource Home Sponsored by Microsoft Home Add Ons Architecture Languages Techniques Using VS Forums
Home arrow Using VS arrow Page 3 - Working with Windows Messages in .NET
Working with Windows Messages in .NET
By John Mueller

Rate This Article: Add This Article To:

Working with Windows Messages in .NET - ' Capturing Windows Messages '
( Page 3 of 4 )

Capturing Windows Messages

If you spent several hours with Spy++, you'd quickly conclude that Windows and the applications it hosts are throwing messages all over the place. In fact, there are too many messages for most applications to use, and even Windows ignores many of them.

ADVERTISEMENT

The point is to monitor the message traffic and to extract only the messages you need. The .NET Framework already monitors a host of messages for you. Every time someone clicks a button, the system generates the four messages shown in Figure 3.

The .NET Framework monitors the message traffic and automatically generates a WM_COMMAND message for you that results in an event. If you have an event handler set up for the control, the system directs the message to it.

Now, think about your .NET code for a moment. The Sender argument that appears as part of every event handle actually obtains a copy of the Sender object using the FromHandle() method associated with that control type. If you look at the .NET documentation, you see that this method accepts a handle in the form of an IntPtr. The IntPtr value comes from the WM_COMMAND message, as shown in Figure 3.

Understandably, the .NET Framework doesn't capture every message, so you might encounter a few messages that you really need for your application that the .NET Framework doesn't support. For example, you might not always need to know when the system is going to shut down, but sometimes it's a handy piece of information when the user has an open document she needs to save. Unfortunately, the .NET Framework doesn't monitor this message, so you might think you're out of luck. Fortunately, the .NET Framework does provide a convenient method to add support to your application for this need, as shown in Listing 1.

Listing 1: Adding Support for the Windows Shutdown Event

// Create a delegate for the custom shutdown event.
public delegate void DoSDCheck(
   object sender, System.EventArgs e);

// Create an event based on the delegate.
public static event DoSDCheck ThisSDCheck;

// Define an event handler for the custom event.
public static void HandleShutdown(
   object sender, System.EventArgs e)
{
   // Display a simple message box.
   MessageBox.Show("The system is about to shut down.");
}

The code shows the order in which you should add the code to your application. Begin by creating a custom delegate to generate the internal event based on the Windows shutdown message. Once you create the delegate, create an event based on that delegate. Finally, create an event handler to handle the events generated by the message. You glue all of these pieces together by adding a single line of code to the application constructor, as shown here.

// Add the event handler to the event.
ThisSDCheck += new DoSDCheck(HandleShutdown);

Now that you have all of the pieces in place for reacting to the event, you need some means of generating the event. You need two pieces of information to perform this task. First, you'll need the messages that the application wants to monitor. Second, you'll need to override the WndProc() method that performs the task of monitoring messages for your application. This particular method is part of the .NET message pump, a component of your application that processes messages. Listing 2 shows both of these pieces.

Listing 2: Monitoring New Messages in an Application

// We need to know which message to monitor.
public const Int32 WM_QUERYENDSESSION = 0x0011;
public const Int32 WM_ENDSESSION = 0x0016;

// Override the default message processing to add
// the new event.
protected override void WndProc(ref Message ThisMsg)
{
   // See which message Windows has passed.
   if ((ThisMsg.Msg == WM_QUERYENDSESSION) ||
       (ThisMsg.Msg == WM_ENDSESSION))
   {
      // Fire the event.
      ThisSDCheck.Invoke(this, null);

      // No more processing needed.
      return;
   }

   // If this isn't an session end message, then pass the
   // data onto the base WndProc() method. You must do this
   // or your application won't do anything.
   base.WndProc(ref ThisMsg);
}

Windows generates the WM_QUERYENDSESSION and WM_ENDSESSION before it ends the current session. Before you accuse me of grabbing values out of thin air, you need to consider how to obtain these message values for yourself. Generally, you need to look through the Visual C++ .h (header) files, because Microsoft doesn't document the values in MSDN. In this case, you'll find the values in WinUser.h, which is probably the most important header file for you to check. Of course, you might wonder why I went to the extra trouble of even defining these values as shown. You want to make it clear which messages you want to monitor, so it's important that you go through this extra documentation step.

The code to override WndProc() monitors just the two additional messages we need for this example. If it detects either message, the code invokes the event, and you see a message box displayed on screen.

There's more to the ThisMsg object than meets the eye. The object includes the WParam, LParam, and HWnd values shown in Figure 3. In addition, you can return a result, in many cases, using the Result property. The Result property brings up an important difference between the WM_QUERYENDSESSION and WM_ENDSESSION messages. When working with the WM_QUERYENDSESSION message, you can return True or False in the Result property. When your application returns False, it means that it can't terminate, and Windows will stop the shutdown process. On the other hand, the WM_ENDSESSION message tells you that Windows is going to shut down whether you want it to or not, and you'd better prepare your application as best as you can.

Always call base.WndProc() when you can't process a message yourself. Failure to make this call will cause your application to freeze. Absolutely nothing will work. Buttons won't push, menus won't operate, nothing will happen besides the actions you have programmed as part of your override. This is one exceptionally important line of code and you should always check for its presence before you begin testing.



 
 
>>> More Using VS Articles          >>> More By John Mueller
 



HD VOIP Has Arrived (with Tony Konstner)

Play Video >

All Videos >

Google and blonde jokes?

Read now >

Favorite books!

Read now >

View Now
DevSource RSS FEEDS
XML Want an easy way to keep up with breaking tech news? And the Get DevSource headlines delivered to your desktop with RSS.