Home

Finalizing an Application

 

Window Registration

After initializing the window class, you must make it available to the other controls that will be part of your application. This process is referred to as registration. To register the window class, call the RegisterClass() for a WNDCLASS variable. If you created your window class using the WNDCLASSEX structure, call the RegisterClassEx() function. Their syntaxes are:

ATOM RegisterClass(CONST WNDCLASS *lpWndClass);
ATOM RegisterClassEx(CONST WNDCLASSEX *lpwcx);

The function simply takes as argument a pointer to a WNDCLASS or WNDCLASSEX. This call can be done as follows:

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
               LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX WndClsEx;

	. . .

	RegisterClassEx(&WndClsEx);

	return 0;
}
 

Window Creation

The WNDLCLASS and the WNDCLASSEX classes are used to initialize the application window class. To display a window, that is, to give the user an object to work with, you must create a window object. This window is the object the user uses to interact with the computer.

To create a window, you can call either the CreateWindow() or the CreateWindowEx() function. We will come back to these functions.

You can simply call this function and specify its arguments after you have registered the window class. Here is an example:

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX	WndCls;

	. . .

    	RegisterClassEx(&WndClsEx);

    	CreateWindow(. . .);
}

If you are planning to use the window further in your application, you should retrieve the result of the CreateWindow() or the CreateWindowEx() function, which is a handle to the window that is being created. To do this, you can declare an HWND variable and initialize it with the create function. This can be done as follows:

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine, int nCmdShow)
{
	HWND	hWnd;
	WNDCLASSEX	WndClsEx;

	. . .

    	RegisterClassEx(&WndClsEx);

    	hWnd = CreateWindow(. . .);
}

We will come back to the other characteristics of a window in future lessons.

 

Window's Message Decoding

Once a window has been created, the user can use it. This is done by the user clicking things with the mouse or pressing keys on the keyboard. A message that a window sends is received by the application. This application must analyze, translate, and decode the message to know what object sent the message and what the message consists of. To do this, the application uses the GetMessage() function. Its syntax is:

BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);

The lpMsg argument is a pointer to the MSG structure. The MSG structure is defined as follows:

typedef struct tagMSG {
    HWND   hwnd; 
    UINT   message; 
    WPARAM wParam; 
    LPARAM lParam; 
    DWORD  time; 
    POINT  pt; 
} MSG, *PMSG;

The hWnd argument identifies which window sent the message. If you want the messages of all windows to be processed, pass this argument as NULL.

The wMsgFilterMin and the wMsgFilterMax arguments specify the message values that will be treated. If you want all messages to be considered, pass each of them as 0.

Once a message has been sent, the application analyzes it using the TranslateMessage() function. Its syntax is:

BOOL TranslateMessage(CONST MSG *lpMsg);

This function takes as argument the MSG object that was passed to the GetMessage() function and analyzes it. If this function successfully translates the message, it returns TRUE. If it cannot identify and translate the message, it returns FALSE.

Once a message has been decoded, the application must send it to the window procedure. This is done using the DispatchMessage() function. Its syntax is:

LRESULT DispatchMessage(CONST MSG *lpMsg);

This function also takes as argument the MSG object that was passed to GetMessage() and analyzed by TranslateMessage(). This DispatchMessage() function sends the lpMsg message to the window procedure. The window procedure processes it and sends back the result, which becomes the return value of this function. Normally, when the window procedure receives the message, it establishes a relationship with the control that sent the message and starts treating it. By the time the window procedure finishes with the message, the issue is resolved (or aborted). This means that, by the time the window procedure returns its result, the message is not an issue anymore. For this reason you will usually, if ever, not need to retrieve the result of the DispatchMessage() function.

This translating and dispatching of messages is an on-going process that goes on as long as your application is running and as long as somebody is using it. For this reason, the application uses a while loop to continuously check new messages. This behavior can be implemented as follows:

while( GetMessage(&Msg, NULL, 0, 0) )
{
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
}

If the WinMain() function successfully creates the application and the window, it returns the wParam value of the MSG used on the application.

 

 
 

Practical Learning Practical Learning: Creating a Sample Application

  1. Replace the file with the following (the file in Borland C++ Builder contains some lines with #pragma; you don't need to delete these files because their presence or absence will not have  a negative impact on the compilation of the program):
     
    #include <windows.h>
    
    LPCTSTR ClsName = L"BasicApp";
    LPCTSTR WndName = L"A Simple Window";
    
    LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg,
    			      WPARAM wParam, LPARAM lParam);
    
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow)
    {
    	MSG        Msg;
    	HWND       hWnd;
    	WNDCLASSEX WndClsEx;
    
    	// Create the application window
    	WndClsEx.cbSize        = sizeof(WNDCLASSEX);
    	WndClsEx.style         = CS_HREDRAW | CS_VREDRAW;
    	WndClsEx.lpfnWndProc   = WndProcedure;
    	WndClsEx.cbClsExtra    = 0;
    	WndClsEx.cbWndExtra    = 0;
    	WndClsEx.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    	WndClsEx.hCursor       = LoadCursor(NULL, IDC_ARROW);
    	WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    	WndClsEx.lpszMenuName  = NULL;
    	WndClsEx.lpszClassName = ClsName;
    	WndClsEx.hInstance     = hInstance;
    	WndClsEx.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    
    	// Register the application
    	RegisterClassEx(&WndClsEx);
    
    	// Create the window object
    	hWnd = CreateWindow(ClsName,
    			  WndName,
    			  WS_OVERLAPPEDWINDOW,
    			  CW_USEDEFAULT,
    			  CW_USEDEFAULT,
    			  CW_USEDEFAULT,
    			  CW_USEDEFAULT,
    			  NULL,
    			  NULL,
    			  hInstance,
    			  NULL);
    	
    	// Find out if the window was created
    	if( !hWnd ) // If the window was not created,
    		return 0; // stop the application
    
    	// Display the window to the user
    	ShowWindow(hWnd, SW_SHOWNORMAL);
    	UpdateWindow(hWnd);
    
    	// Decode and treat the messages
    	// as long as the application is running
    	while( GetMessage(&Msg, NULL, 0, 0) )
    	{
                 TranslateMessage(&Msg);
                 DispatchMessage(&Msg);
    	}
    
    	return Msg.wParam;
    }
    
    LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg,
    			   WPARAM wParam, LPARAM lParam)
    {
        switch(Msg)
        {
        // If the user wants to close the application
        case WM_DESTROY:
            // then close it
            PostQuitMessage(WM_QUIT);
            break;
        default:
            // Process the left-over messages
            return DefWindowProc(hWnd, Msg, wParam, lParam);
        }
        // If something was not done, let it go
        return 0;
    }
  2. To execute the program, if you are using Borland C++ Builder, press F9
    If you are using Microsoft Visual C++, press Ctrl + F5 and click Yes
     
    A Simple Window
  3. To close the window, click its system Close button and return to your programming environment.
 

Previous Copyright © 2003-2015, FunctionX Next