Tricks of the Windows Game Programming Gurus:Advanced Windows Programming

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

As I said, processing the `WM_SIZE` message can be very important for windowed games because when the window is resized, the graphics display must be scaled to fit. This will never happen if your game is running in full-screen, but in a windowed game, you can count on the user trying to make the window larger and smaller. When this happens, you must recenter the display and scale the universe or whatever to keep the image looking correct. As an example of tracking the `WM_SIZE` message, `DEMO3_9.CPP` prints out the new size of the window as it’s resized. The code that tracks the `WM_SIZE` message in `DEMO3_9.CPP` is shown here:

    case WM_SIZE:

             {

             // extract size info

             int width = LOWORD(lparam);

             int height = HIWORD(lparam);

             // get a graphics context

             hdc = GetDC(hwnd);

             // set the foreground color to green

             SetTextColor(hdc, RGB(0,255,0));

             // set the background color to black

             SetBkColor(hdc, RGB(0,0,0));

             // set the transparency mode to OPAQUE

             SetBkMode(hdc, OPAQUE);

             // draw the size of the window

             sprintf(buffer,

             "WM_SIZE Called - New Size = (%d,%d)", width, height);

             TextOut(hdc, 0,0, buffer, strlen(buffer));

             // release the dc back

             ReleaseDC(hwnd, hdc);

             } break;

> Warning: You should know that the code for the `WM_SIZE` message handler has a potential problem: When a window is resized, not only is a `WM_SIZE` message sent, but a `WM_PAINT` message is sent as well! Therefore, if the `WM_PAINT` message was sent after the `WM_SIZE`, the code in `WM_PAINT` could erase the background and thus the information just printed in `WM_SIZE`. Luckily, this isn’t the case, but it’s a good example of problems that can occur when messages are out of order or when they aren’t sent in the order you think they are.

Last, but not least, let’s take a look at the `WM_MOVE` message. It’s almost identical to `WM_SIZE`, but it is sent when a window is moved rather than resized. Here are the details:

Message: `WM_MOVE`

Parameterization:

    xPos = (int) LOWORD(lParam); // new horizontal position in screen coords

    yPos = (int) HIWORD(lParam); // new vertical position in screen coords

`WM_MOVE` is sent whenever a window is moved to a new position, as shown in Figure 3.21. However, the message is sent after the window has been moved, not during the movement in real time. If you want to track the exact pixel-by-pixel movement of a window, you need to process the `WM_MOVING` message. However, in most cases, processing stops until the user is done moving your window.

Figure 3.21 Generation of the `WM_MOVE` message.

As an example of tracking the motion of a window, `DEMO3_10.CPP` and the associated executable `DEMO3_10.EXE` print out the new position of a window whenever it’s moved. Here’s the code that handles the `WM_MOVE` processing:

    case WM_MOVE:

             {

             // extract the position

             int xpos = LOWORD(lparam);

             int ypos = HIWORD(lparam);

             // get a graphics context

             hdc = GetDC(hwnd);

             // set the foreground color to green

             SetTextColor(hdc, RGB(0,255,0));

             // set the background color to black

             SetBkColor(hdc, RGB(0,0,0));

             // set the transparency mode to OPAQUE

             SetBkMode(hdc, OPAQUE);

             // draw the size of the window

             sprintf(buffer,

            "WM_MOVE Called - New Position = (%d,%d)", xpos, ypos);

             TextOut(hdc, 0,0, buffer, strlen(buffer));

             // release the dc back

             ReleaseDC(hwnd, hdc);

             } break;

Well, that’s it for window manipulation messages. There are a lot more, obviously, but you should have the hang of it now. The thing to remember is that there is a message for everything. If you want to track something, just look in the Win32 Help and sure enough, you’ll find a message that works for you!

The next sections cover input devices so you can interact with the user (or yourself) and make much more interesting demos and experiments that will help you master Windows programming.

#### Banging on the Keyboard

Back in the old days, accessing the keyboard required sorcery. You had to write an interrupt handler, create a state table, and perform a number of other interesting feats to make it work. I’m a low-level programmer, but I can say without regret that I don’t miss writing keyboard handlers anymore!

Ultimately you’re going to use DirectInput to access the keyboard, mouse, joystick, and any other input devices. Nevertheless, you still need to learn how to use the Win32 library to access the keyboard and mouse. If for nothing else, you’ll need them to respond to GUI interactions and/or to create more engaging demos throughout the book until we cover DirectInput. So without further ado, let’s see how the keyboard works.

The keyboard consists of a number of keys, a microcontroller, and support electronics. When you press a key or keys on the keyboard, a serial stream of packets is sent to Windows describing the key(s) that you pressed. Windows then processes this stream and sends your window keyboard event messages. The beauty is that under Windows, you can access the keyboard messages in a number of ways:

  • With the `WM_CHAR` message
  • With the `WM_KEYDOWN` and `WM_KEYUP` messages
  • With a call to `GetAsyncKeyState()`

Each one of these methods works in a slightly different manner. The `WM_CHAR` and `WM_KEYDOWN` messages are generated by Windows whenever a keyboard keypress or event occurs. However, there is a difference between the types of information encapsulated in the two messages. When you press a key on the keyboard, such as A, two pieces of data are generated:

  • The scan code
  • The ASCII code

The scan code is a unique code that is assigned to each key of the keyboard and has nothing to do with ASCII. In many cases, you just want to know if the A key was pressed; you’re not interested in whether or not the Shift key was held down and so on. Basically, you just want to use the keyboard like a set of momentary switches. This is accomplished by using scan codes. The `WM_KEYDOWN` message is responsible for generating scan codes when keys are pressed.

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.