December 24th, 2002 07:51 PM
Win32 API Programming with C (PART 2)
Part 2 - Win32 API Programming series
Today we are going to first understand the process behind creating and using windows, and we will uncover a little of how the message driven structure of Windows works. The windows.h header file has a bunch of pre-defined function prototypes, typedefs structures and more. You will only become familiar with them if you experiment and practice. I strongly encourage you to download the Win32 Programmer's Reference or visit http://msdn.microsoft.com and look up the functions. This way you can become familiar with the arguments and their meanings. Teaching after all is really giving guidance and helping students overcome hurdles, but spoon feeding does not benefit anyone.
I included an atachement example complete with comments. It should compile and work with no problems. Be sure to read the comments and examine the code. Try to understand how it works. This tutorial is therefor aimed at getting your feet wet. The only code example in this tutorial is the atachemnt, so be sure to download the atachemnt and criticize my work.
In our last code example used the MessageBox function to create a small window. But much of the work involved in the creation of the window was done in the background for you. Lucky for you, you were saved from seeing all the neat stuff. Lets now try to understand the process of creating and using a window:
Drawing the window: (WM_PAINT, WM_MOVE: The Body)
First we know that the window was drawn onto the screen, in DOS we would have had to worry about the graphics mode or screen mode, but in Win32 that is all taken care of for us. When we drag the window to a new position the window must re-draw itself in the new window position, this makes sense. In the Win32 API the message WM_PAINT and WM_MOVE are sent when the window moves and when the window should re-paint itself. (See the window procedure below)
But how do we draw the window? Well if you think about a bike, you know that every bike has some common features, all bikes have a frame, all bikes have wheels, and all bikes have a handle bar. But yet all bikes have their own unique features such as color, size and speed. For this we have a blueprint for a bike. And from this blueprint we can make changes and thus we can make any kind of bike we want. Well windows are similar, except instead of calling it a blue print, we call it a window class. In the case of our MessageBox function this was all taken care of for us, and the class was pre-made. But if we want to create our own custom window with the CreateWindow function, we will need to make our own class or use a predefined class. We make a class first by filling in the members of a WNDCLASS structure, then passing the structure as an argument to the RegisterClass function. The header file windows.h defines a WNDCLASS structure so all we do is make an instance, and then fill in our instance. Once a window class is registered we can use it in subsequent calls to CreateWindow, or the newer CreateWindowEx function.
Windows are message driven: (Window procedure: The Brain)
Windows is message driven, every time the user types on the keyboard or clicks the mouse button, a message is sent. Every time the window is dragged it is sent a message. A message is composed of wParam and lParam values which are both 32 bit values to be discussed another day. So now we know that the window received messages but what does it do with these messages? Does it just sit there and do nothing or does it flash fancy animations on the screen? For this we need a window procedure. The window procedure is a function that will be called every time the window receives a message. The arguments to the window procedure are filled in for us by the operating system. The procedure is responsible for apropriatly handling these messages. A pointer to the window procedure function is stored in the WNDCLASS structure that we filled in before creating the window. This way we attach the procedure to the window, as a application may have many procedures.
Dispatching the messages: (The Heart)
Ok so far we have a brain, thats our window procedure and it handles all the messages. We also have drawn the window. So we have the body and the brain, but just like a human we need a heart. Ok so the user moved the window, and the message WM_MOVE gets sent to the window to tell it we want it to move right? Well not exactly. When the user does something such as clicking the mouse, this message goes into a message quote, it sits in the message quote until we are ready, then we dispatch the message to the window procedure.
So how do we do this and why didn't we have to worry about this with MessageBox? First the MessageBox function is pre written to do all this work for us, but when we use the CreateWindow function to make our own window, now we have to worry about all this small detail. For handling messages in the message quote we have some functions that we made for us. We will only concern ourselfs with GetMessage, TranslateMessage and DispatchMessage. First we use GetMessage to retrieve a message from the message quote. Next we use TranslateMessage which basically does some parsing of virtual key messages, without this some things wont work, so be nice and translate. Once we have "gotten" the message from the top of the message quote, did some parsing, now we can dispatch it to our destination window, which, as you guessed gets processed by our window procedure. But if we only did this once, only one message would get processed. But as we know windows is message driven, so we can expect to receive more messages in our quote. So using a loop we can continue to get messages and dispatch them to the appropriate window.
Lets take a look at a example of a window that will weave all of our new found knowledge together: (ATTACHMENT ONLY) Be sure to remove the txt extension, leaveing cpp inctact