Broad Network


Basics of Creating Windows and the Window Class Procedure

Getting to know Windows – Part 6

Volume - Windows User Interface

Forward: In this part of the series we look at the Basics of Creating Windows and the Window Class Procedure.

By: Chrysanthus Date Published: 28 Aug 2012

Introduction

This is part 6 of my series, Getting to know Windows. I assume you have read all the previous tutorials before this one. You should be reading the tutorials in the order given. In this part of the series we look at the Basics of Creating Windows and the Window Class Procedure.

Note: If you cannot see the code or if you think anything is missing (broken link, image absent), just contact me at forchatrans@yahoo.com. That is, contact me for the slightest problem you have about what you are reading.

Creating a Window
An application typically creates the main window as its first window before it can go on to create other windows. You create a window using the CreateWindowEx function. Before creating a window, you have to register the class of the window first, and then provide a window procedure for the class; then you can create the window.

A class has the characteristics of a window. Some of these characteristics can be given when creating the window in the CreateWindowEx function. If you do not give a characteristic in the CreateWindowEx function, make sure you give it in the class description (see details later), unless the characteristic is optional.

The CreateWindowEx Function
There is a predefined function called CreateWindowEx, which is used to create a window. Two other functions are normally used with the CreateWindowEx function. The functions are ShowWindow and UpdateWindow. The CreateWindowEx, ShowWindow and UpdateWindow are in-built functions and we shall not look at their internal code. An example code of the use of these functions is:

HINSTANCE hinst;
HWND hwndMain;

hwndMain = CreateWindowEx(0, "MainWClass", "Main Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, (HWND) NULL, (HMENU) NULL, hinst, NULL);                  

if (!hwndMain)
    return FALSE;

ShowWindow(hwndMain, SW_SHOWDEFAULT);
UpdateWindow(hwndMain);

The first thing in the code is the declaration of the identifier that will hold the instance handle of the class (HINSTANCE is the instance data type). Next you have the declaration of the identifier that will hold the handle of the window created. The CreateWindowEx function returns the handle of the window it has created. This will be held by hwndMain.

The CreateWindowEx function has many arguments. The second argument is the name of the class; it is a string in double quotes. The third argument is the name of the window, which will be displayed in the title bar of the window. It is a string in double quotes and it can have spaces. One of the arguments is the identifier for the class instance handle.

There is an if-construct. This if-construct checks if the window was successfully created. If it was not successfully created, the if-statement returns FALSE to the calling environment (operating system). The condition, (!hwndMain) will result in False if the window was not created (successfully). Note the NOT (!) inside the condition.

When the window is created by the CreateWindowEx function it is not displayed. The ShowWindow predefined function displays the window. It first argument is the handle of the window. We shall talk about its second argument later. As the window is just displayed, it does not have a color. The UpdateWindow predefined function paints the window’s client area. Its argument is the window handle. The uses of the last two functions do not look logical; but that is how things are with Windows.

Destroying a Window
Closing a window does not destroy the window. Destroying a window means the window has to save its system data and then free the memory that the window was using and free any resources that were allocated to the window, so that other applications can use the resources (and memory). We shall see more about this, as we go along.

Structure of the Window Class Procedure
The window class procedure takes four parameters and returns a single value. The set of four parameters is the message from the system queue. We have talked about this before. The body of the procedure uses a switch construct like that for C++. You can have nested switch constructs.

A Typical Window Procedure
The following is a typical window procedure code:

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{

    switch (uMsg)
    {
        case WM_CREATE:
            // Initialize the window.
            return 0;

        case WM_PAINT:
            // Paint the window's client area.
            return 0;

        case WM_CLOSE:
            // Finalize.
            return 0;

        case WM_DESTROY:
            // Clean up window-specific data objects.
            return 0;

        //
        // Process other messages.
        //

        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

Each CASE block has one or more statements. Everything being equal, the last statement for a CASE should be “return 0;”. For the CASES above the message is received by the uMsg parameter. The parts of the message in the wParam and lParam parameters are not important for us now (assume that). In this part of the series, we consider only what is of uMsg

The WM_CREATE message is sent to the procedure just after your window is created. For this CASE in the procedure, you can do some initializing of the window, such as writing some initial text on the window. We shall see details later. Read the above procedure code if you have not already done so.

From above, remember that after you create the window, you call the UpdateWindow function for painting the window’s client area. This function sends the WM_PAINT message to the system queue. The message quickly arrives in the procedure (sent by the WHILE Loop). The statements you type for CASE WM_PAINT in the procedure, should paint the window. We shall see details later. However, I hope you are beginning to appreciate Windows User Interface coding. I delayed the coding and now I am delaying the details. We have to take things step by step. I hope you are beginning to understand the coding. You still need some patience so far as the details are concerned.

When you click the Close button of a window, the WM_CLOSE message is sent to the queue by the window. From the queue it is quickly sent to the procedure (by the WHILE Loop). The statements you type for CASE WM_CLOSE in the procedure should finalize the application. In your life, you must have clicked the Close button of certain application windows and a small window would pop up asking you if you really want to close (exit) the application. You can click Yes or No in the pop up window. It is in this CASE in the procedure that you code such a thing.

When the Close button of a window is clicked, the WM_CLOSE message arrives at the procedure. Everything being equal, the WM_DESTROY message arrives shortly after. The WM_CLOSE does not destroy the window. It is the statements for the CASE WM_DESTROY that removes the window from the screen and frees all the recourses that the window was using. If you do not have this CASE in the procedure, the default behavior would be used.

In the switch construct above, there is a default CASE. This default case has just one statement, which calls and returns the result of the default procedure, DefWindowProc, using the arguments received by the window class procedure.

If there is no CASE code in the procedure, the DefWindowProc procedure processes all the messages, with default behaviors. You would not like some of the results. So you should do some processing for some CASES; we shall see details later.

Everything being equal, the procedure should return zero. That is why you have “return 0;” at the end, after the switch construct.

Note: The procedure can still send a message to the system queue. The message will finally come back to the procedure to be handled by a different CASE.

We have seen much in this part of the series. Let us take a break here and continue in the next part.

Chrys

Related Courses

C++ Course
Relational Database and Sybase
Windows User Interface
Computer Programmer – A Jack of all Trade – Poem
NEXT

Comments

Become the Writer's Fan
Send the Writer a Message