home

Tutorial Index

GDI Tutorial 5: Message handling 2

Knowing how message handling works and using it properly is fairly different. In the previous tutorial you saw how it works, what you need to know to go on, but if you tried to do something with that, you probably had little luck.

First of all, you may get a compiler error for hwnd. Any other errors should be about things that are being redefined, just remove the declarations, but for hwnd to do it's job, not only you need to define it, but to retrieve it. hwnd is a handle to your window, this is not quite defined in your seemingly infinite loop, so you have to find out the handle. This you do with the FindWindow(LPCTSTR, LPCTSTR) function.The two arguments are lpClassName and lpWindowName, but since they are optional, you can place NULL in both and it will retrieve the handle to the topmost window, and you should probably not be trying to get anything else.

However, this seems to be getting the window into a frenzy and will give you a constant busy cursor, so it is actually better to leave it NULL. Now we have to do some work on the message. It is somewhat hard to check the lParam from the current loop, so you want to send it into WndProc, where you can just call it lParam and access it straightaway. Thus you have to add TranslateMessage(&msg) and DispatchMessage(&msg).

It is also worth noting that you can use an if instead of the while to process the messages (where you call PeekMessage).

Now, down to WndProc().

Here you have to take care of a small detail. We used an fDone boolean variable to keep the program running. This means that the loop will run even after the program successfully executed PostQuitMessage(). To solve this, add fdone = true; right after every call to PostQuitMessage. If you got the aforementioned problem and have Visual Studio in running mode, hit Shift + F5 to stop execution, if you are using another IDE, check the corresponding debug tab in the menu bar for a "stop debugging" or similar command.

Now, to process the messages, You want to check what kind of message it is, and what it contains. make a switch based on msg, and place cases for that, the one I will use is WM_KEYDOWN, as it was mentioned in the previous tutorial. As mentioned, lParam can be directly accessed, so nest another switch based on lParam this time, to get the info you really want. To read keys, you need the Virtual Key codes. Some are fairly straightforward, like VK_ESCAPE for the escape key, VK_RETURN, VK_LEFT, VK_UP and so on, for Enter and the cursor keys. The keys referring to the alphabet and numbers are referred to with theyr actual numbers (it's all integers, the Virtual Key codes just #define some names, so you can extend them in a header of your own). The full list can be found on this page on MSDN. Note that as the codes for letters and numbers are continuous, you can treat them the same way you would treat the ASCII codes, i.e. you can retrieve numbers with the code minus 30, and the letters with A being 41, and thus each next letter being one above.

An issue you will meet as soon as you start trying to manipulate variables through WndProc, is that WndProc cannot see what is in WinMain, because they are separate functions and ones variables are outside the scope of the other's. Now, you can either modify WndProc to take another parameter, but you will soon find out that it's like trying to simulate a processor, you will have to make WndProc get data in one cycle and then tell it what to do with it, and that is both inefficient and vastly tiring, though admitedly very, very fascinating. The solution is using global variables. If you have some decent programming experience, you will know that it can get very messy, with stray variables here and there, but you will probably have thought of hwat I do, which is having a separate header file with all my variables stored there, variables.h is a sound name. If you want to further categorize variables, you can #include the other headers into that header, so you will only include variables.h in your main code.

So far, you can probably just make a custom control to exit the window, in the next lesson we'll get to show something into our window, to get it a bit more meaningful. Make sure you do what has been taight so far manually, here is the main code in case you're missing something, I've made it exit the window when the left arrow key is pressed.

In the following lessons we'll try to make a tactical game, using buttons, input fields but also trying to select units with the mouse cursor, to make it close to something you would see in real life.