Tricks of the Windows Game Programming Gurus:The Windows Programming Model

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

I’m going to talk about device contexts in detail in Chapter 3, “Advanced Windows Programming,” but basically they are used as data structures for graphics rendering into a window. Hence, if you want to do graphics, you need to request a device context for the particular window you are interested in. Alas, if you set the Windows class so that it has its own device context via `CS_OWNDC`, you can save some time since you don’t have to request one each time you want to do graphics. Did that help at all, or did I make it worse? Windows is like that—the more you know, the more you don’t. Anyway, here’s how to set the `style` field:

    winclass.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC | CS_DBLCLICKS;

The next field of the `WNDCLASSEX` structure, `lpfnWndProc`, is a function pointer to the event handler. Basically, what you are setting here is a callback function for the class. Callback functions are fairly common in Windows programming and work like this: When something happens, instead of you randomly polling for it, Windows notifies you by calling a callback function you’ve supplied. Then, within the callback function, you take whatever action needs to be taken.

This process is how the basic Window event loop and event handler work. You supply a callback function to the Windows class (with a specific prototype, of course). When an event occurs, Windows calls it for you, as Figure 2.6 shows. Again, we will cover this more in later sections. But for now, just set it to the event function that you’ll write in a moment:

    winclass.lpfnWndProc = WinProc; // this is our function

Figure 2.6 The Windows event handler callback in action.

> Tip: If you’re not familiar with function pointers, they are like virtual functions in C++. If you’re not familiar with virtual functions, I guess I have to explain them <BG>. Let’s say you have two functions that operate on two numbers:

>        int Add(int op1, int op2) {return(op1+op2);}

>        int Sub(int op1, int op2) {return(op1-op2);}

> You want to be able to call either function with the same call. You can do so with a function pointer, like this:

>        // define a function pointer that takes two int and returns

>        an int

>        int (Math*)(int, int);

>        Then you can assign the function pointer like this:

>        Math = Add;

>        int result = Math(1,2); // this really calls Add(1,2)

>        // result will be 3

>        Math = Sub;

>        int result = Math(1,2); // this really calls Sub(1,2)

>        // result will be –1

> Cool, huh?

The next two fields, `cbClsExtra` and `cbWndExtra`, were originally designed to instruct Windows to save some extra space in the Windows class to hold extra runtime information. However, most people don’t use these fields and simply set them to `0`, like this:

    winclass.cbClsExtra = 0; // extra class info space

    winclass.cbWndExtra = 0; // extra window info space

Moving on, next is the `hInstance` field. This is simply the `hinstance` that is passed to the `WinMain()` function on startup, so just copy it in from `WinMain()`:

    winclass.hInstance = hinstance; // assign the application instance

The remaining fields relate to graphical aspects of the Windows class, but before I discuss them, I want to take a quick moment to review handles.

Again and again you’re going to see handles in Windows programs and types: handles to bitmaps, handles to cursors, handles to everything. Remember, handles are just identifiers based on an internal Windows type. In fact, they are really integers. But Microsoft might change this, so it’s a good idea to be safe and use the Microsoft types. In any case, you’re going to see more and more “handles to [fill in the blank],” so don’t trip out on me! And remember, any `type` prefixed by `h` is usually a handle. Okay, back to the chalkboard.

The next field sets the type of icon that will represent your application. You have the power to load your own custom icon, but for now you’re going to use a system icon, which—you guessed it—you need a handle for. To retrieve a handle to a common system icon, you can use the `LoadIcon()` function, like this:

    winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

This code loads the standard application icon—boring, but simple. If you’re interested in the `LoadIcon()` function, take a look at its prototype below, and see Table 2.7 for various icon options:

    HICON LoadIcon(HINSTANCE hInstance,  // handle of application instance

      LPCTSTR lpIconName);  // icon-name string or icon resource identifier

Here, `hInstance` is the instance of the application to load the icon resource from (more on this later), but for now just set it to `NULL` to load one of the standard icons. And `lpIconName` is a null-terminated string containing the name of the icon resource to be loaded. However, when `hInstance` is `NULL`, `lpIconName` can be one of the values in Table 2.7.

Table 2.7 Icon Identifiers for `LoadIcon()`

Value | Description
--- | ---

`IDI_APPLICATION` | Default application icon
`IDI_ASTERISK` | Asterisk
`IDI_EXCLAMATION` | Exclamation point
`IDI_HAND` | Hand-shaped icon
`IDI_QUESTION` | Question mark
`IDI_WINLOGO` | Windows logo

All right, we’re about halfway through all the fields. Take another breath, and let’s forge on to the next field: `hCursor`. This is similar to `hIcon` in that it’s a handle to a graphics object. However, `hCursor` differs in that it’s the handle to the cursor that will be displayed when the pointer enters the client region of the window. `LoadCursor()` is used to obtain a handle to a cursor that’s a resource or a predefined system cursor. We will cover resources a bit later, but they are simply pieces of data, like bitmaps, cursors, icons, sounds, etc., that are compiled into your application and can be accessed at runtime. Anyway, here’s how to set the cursor for the Windows class:

    winclass.hCursor = LoadCursor(NULL, IDC_ARROW);

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.