Deterministic WM_CLOSE and Encountering Window Messages in .NET Framework#

While programming in a desktop application which uses a legacy COM object to communicate with IVR, a colleague encountered the need to determine “End Task” call for his program to cleanup after a RCW interop and catch respective exceptions.

As defined in MSKB 77135If the user chooses End Task in the Windows Task Manager, the Task Manager posts a WM_CLOSE message to the application's main window” and “People need to remember that the .NET Framework's OnClosing() is the managed version of Win32's WM_CLOSE and not WM_DESTROY.” It leads to a conclusion that a .NET application needs to encounter the message queue as Win32 SDK app would.

Microsoft provides an example in .NET Framework Class Library Reference, Control.WndProc Method. It overrides the WndProc method and handles the window messages to know how an application become active. Here's the source from MSDN.

 

protected override void WndProc(ref Message m)
        {
            // Listen for operating system messages.
            switch (m.Msg)
            {
                // The WM_ACTIVATEAPP message occurs when the application
                // becomes the active application or becomes inactive.
                case WM_ACTIVATEAPP:

                    // The WParam value identifies what is occurring.
                    appActive = (((int)m.WParam != 0));

                    // Invalidate to get new text painted.
                    this.Invalidate();

                    break;               
            }
            base.WndProc(ref m);
        }

Extending this implementation, one can handle further windows messages in a managed code application like in traditional win32 SDK App. Here’s a Win32 scenario of handling window Messages and getting over WM_Close conditionally.

End Task and End process acts differently; for further details of process termination handling in C#, this thread (How to take actions upon program termination) will be helpful.

 

“The main function of the message pump is the GetMessage fuction, it gets  the message from the queue (placing in a MSG struct). And returns a non-zero value, however if the message is WM_QUIT it returns 0 (thus breaking the loop). And with the loop broken the message never gets translated or dispatched (to the callback procedure). (That's the way it works in c(++) code, none of this fancy "managed code")

 

But once out of the loop, execution continues normally. Which means that you could nest the message pump (loop) inside of another while loop so it would start right back up.

 

It is true that the NT Task Manager sends the WM_CLOSE message to the window, but that is only on the Applications tab. On the Processes tab it uses the (appearently unstoppable) TerminateProcess function which performs a karate chop on the process (without the use of messages).

 

Here is what happens (from msdn):

 

Terminating a process causes the following:

    1. All object handles opened by the process are closed.

    2. All threads in the process terminate their execution. Each thread exits when all its pending I/O has been completed or canceled. The process exits after all its threads exit.

    3. The state of the process object becomes signaled, satisfying any threads that had been waiting for the process to terminate. The process object is deleted when the last handle to the process is closed.

    4. The states of all threads of the process become signaled, satisfying any threads that had been waiting for the threads to terminate.

    5. The termination status of the process changes from STILL_ACTIVE to the exit value of the process.

 

Further the info for TerminateProcess says:

"Neither the process nor any DLLs attached to the process are notified that the process is terminating. A process cannot prevent itself from being terminated.

 

Terminating a process does not generate notifications for WH_CBT hook procedures."

 

The following listing explains it further; text and listing courtesy Ken Nign.

 

/*     Include some standard headers     */

#include <WINDOWS.H>

#include <STDIO.H>

#include <STRING.H>

 

LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)

{

    switch(Msg)

    {

       case WM_CLOSE:

              MessageBox(NULL, "WM_CLOSE", "Testing", 0);

              PostQuitMessage(WM_QUIT);

       return 0;

       default:

              //MessageBox(NULL, strMsg, "Testing", 0);

return DefWindowProc(hWnd, Msg, wParam, lParam);

       return 0;

    }

 

return 1;

}

 

/*     Our main entry point */

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{

int i;

MSG Msg;

WNDCLASSEX WndClsEx;

HWND hWnd;

 

/*     Init the winclass for the main window    */

WndClsEx.cbSize        = sizeof(WNDCLASSEX);

WndClsEx.style         = CS_HREDRAW | CS_VREDRAW;

WndClsEx.lpfnWndProc   = WndProc;

WndClsEx.cbClsExtra    = 0;

WndClsEx.cbWndExtra    = 0;

WndClsEx.hCursor       = LoadCursor(NULL, IDC_ARROW);

//WndClsEx.hIcon         = LoadIcon(hInstance, "A_VPICON");

WndClsEx.hbrBackground = GetSysColorBrush(COLOR_3DFACE);

WndClsEx.hInstance     = hInstance;

WndClsEx.lpszMenuName  = "IDR_MAINFRAME";

WndClsEx.lpszClassName = "Msgtest";

//WndClsEx.hIconSm       = LoadIcon(hInstance, "A_VPICON");

 

RegisterClassEx(&WndClsEx);

 

hWnd = CreateWindow("Msgtest",

       "Win cap",

       WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE,

       0, 0,

       490, 200,

       NULL,

       NULL,

       hInstance,

       NULL);

 

/*     Finally show the window    */

    ShowWindow(hWnd, nCmdShow);

    UpdateWindow(hWnd);

 

printf("hi low from above the message pump\n\n");

//MessageBox(NULL, "testing", "MB", 0);

 

while( GetMessage(&Msg, NULL, 0, 0) )

{

printf("%li\n", Msg.message);

TranslateMessage(&Msg);

DispatchMessage(&Msg);

 

}      // while's

 

while( GetMessage(&Msg, NULL, 0, 0) )

{

printf("%li\n", Msg.message);

TranslateMessage(&Msg);

DispatchMessage(&Msg);

 

}      // while's

MessageBox(NULL, "testing below the pump", "MB", 0);

ExitProcess(0);

}

 

Rui Reis's also have demonstrated handling of Windows Messages in Managed code which would be a useful reading.

References





4/26/2004 7:42:09 PM (Pacific Standard Time, UTC-08:00) #    Comments [6]  |  Trackback

 

Design Patterns with David Wells – Los Angeles .NET Developers Group#

Design patterns capture best user practices and describe the possible solutions to a problem in context; depicting generic example of real life scenarios. Last night in LA . NET developers’ group meeting, David Wells, President OCIUG and OCNSUG spoke about software design patterns and their implementation in development frameworks. This event about software reusability techniques was held in UCLA Dodd’s hall with Scott Robertson, President LA .NET Developers group’s opening keynote and usual announcements. Jeffrey Hasan announced he’ll be delivering next months’ presentation on “Build Message-Based Web Services for Service Oriented Applications” on 3rd May 2004. 

David’s speech was a breadth first approach to Design patterns; He began with examples from classical texts; Addison-Wesley’s Design Patterns which is considered a-must-read for Software design Engineers. This book is commonly known as GOF (Gang of four) after authors Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides. A detailed overview of GOF Patterns and there frequency of usage in projects can be found here. David’s listed patterns in the following unclassified order.

Software Patterns

Design Patterns
. NET patterns
Use Case Patterns
Enterprise Patterns
Analysis Patterns
Data Model Patterns
Business Rules Patterns
Framework Patterns
UML & Patterns
Extreme Programming
Test Driven development
Object Modeling
UML
Anti-Patterns

 One can always disagree with this list and there could various additions for instance I miss “Agile development” and aspect oriented programming.  

Software patterns, as he defined them, are classified into three major categories; Behavioral, Creational and Structural patterns. He later elaborated each of the types as follows.

Behavioral Patterns

Creational patterns

Structural patterns

Chain of responsibility
Command
Interpreter
Iterator
Mediator
Memento
Observer
State
Strategy
Template method
Visitor

Abstract factory
Builder
Factory method
Prototype
Singleton 

Adapter
Bridge
Composite
Decorator
Facade
Flyweight
Proxy

 

David’s presentation can be downloaded from OCIUG website as he promised to upload the latest version soon; Observer and  Singleton Presentation & code samples are already uploaded. For Singleton Design Pattern, Exploring the Singleton Design Pattern by Mark Townsend of Microsoft Corporation is a good reading. (David Wells used the illustration in this article during the presentation). Observer is implemented in both major development frameworks in the form of delegates and call back features; System.IO.FileSystemWatcher is a good example of Observer Pattern. It is mostly low-level implementation (multithreaded event handler attachment), and appears in its entirety as part of other important patterns (e.g. ModelViewController).

Couple of things which he emphasized on during the talk, and I remembered, other than classical Singleton and Factory patterns were Refactoring and XP. Refactoring is code oriented optimization approach defined as “is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior.” In simple words its better & optimized code. There is a collection of tools available for different IDE’s and platforms on Martin Fowler’s Refactoring.com; (also includes my favorite C# refactory listed). Refactoring in Whidbey by Scott Water, Refactoring in VS.NET Whidbey hands on labs PDC  Visual C# "Whidbey": IDE Enhancements For C# Devlopers  are good articles to read for those interested in up coming IDE’s support for Refactoring.

Extreme Programming is the approach to create better, deliberate and disciplined software projects; most suitable for dynamic and altering requirement projects (Iterative Model of Software Engineering), XP revolves around planning, coding, designing and testing phases which are defined here in greater detail as XP rules.

Later during discussion data access patterns, business object patterns, use case patterns, . NET patterns, CRC (Class, Responsibilities, and Collaborators) cards were being explained. Anti Patterns are bad approaches combined together for developers to beware of potential development pitfalls; David stated what’s mentioned on Anti-Patterns HomeA survey of hundreds of corporate software development projects indicated that five out of six software projects are considered unsuccessful. About a third of software projects are canceled. The remaining projects delivered software that was typically twice the expected budget and took twice as long to developed as originally planned [Johnson 95].” Some of the anti-patterns are Blob, Lava flow, Spaghetti code etc.

I found another good definition of Anti-Patterns here.An AntiPattern is a pattern that tells how to go from a problem to a bad solution. (Contrast to an AmeliorationPattern, which is a pattern that tells how to go from a bad solution to a good solution.)”

The presentation ended with a raffle and I won a cool LA . NET developers group coffee mug :D

Recommended Readings





4/8/2004 7:54:32 PM (Pacific Standard Time, UTC-08:00) #    Comments [2]  |  Trackback

 

Longhorn and WinFS - MSDN Show#

A new MSDN Show is launched today on the long awaited topic, Longhorn and WinFS. Details as on website...

"The file system lies at the heart of almost any operating system. It is the core code that allows applications to store, retrieve, and interact with stored information. File systems have evolved fairly slowly compared to the other systems technologies that programmers use, but we will see that "WinFS", the code name for the file system in "Longhorn", changes all of that. "

Read More...





4/1/2004 7:58:23 PM (Pacific Standard Time, UTC-08:00) #    Comments [17]  |  Trackback

 

SQL Server 2000 Reporting Services comparison Metric#

After official launch of SQL Server 2000 Reporting Services, Microsoft is pitching this promising product with amazing features in all major events; from PDC to VSLive, Reporting Services can be seen and heard in all keynote sessions.

I'm looking forward to gather some feature comparison data among prominent reporting tools (Data Dynamic's ActiveReports and Business Object's Crystal Reports). Nilkanth tried collecting some during beta launch; Now when the release and the word is out, it would be great to know what developers think of Reporting Services? Do real experiences agree with MS case studies or does this technology need to be mature to face competitors? I’ll wait for input.





4/1/2004 12:24:22 AM (Pacific Standard Time, UTC-08:00) #    Comments [13]  |  Trackback

 

All content © 2008, Adnan Masood
About the Author
On this page
Calendar
<October 2008>
SunMonTueWedThuFriSat
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678
Archives
Sitemap
Blogroll OPML