|
Welcome to the first tutorial in the Windows tutorial series. In this tutorial we will talk about the basic setup of a Win32 application. We'll go over a few important details first. This is a quick overview of the steps taken to create an empty window application:
1. Write the Event Handler function The main function & The Event Handler A basic 32-bit windows application must always contain two important functions. The first one is the event handler(I'll talk about this one in the following tutorials) and the second one is the main function(WinMain from now on). If you're a DOS veteran, WinMain is similar to DOS' main function. Windows Messages Windows programming introduces us to messages. A message could be easily described as a collection of data (which sometimes is a struct, other times a single variable parameter) that gets sent to the event handler which then tells the window what action should be taken. A message's name is prefixed with WM(Which stands for Windows Message, how simple is that?). The average window processes thousands and in many cases millions of messages during its existence. However we'll focus on some of the most basic ones in this tutorial, and talk about other messages later on. You can use Window Messages in many ways. For example, the message WM_CREATE, can be used to initializate (e.g.: create) a window, it gets sent to the window when it's created. WM_PAINT is used when you want to draw something on the screen, and so on, you get the idea. Most of the messages get sent to the window automatically, for example when you move your mouse around the window area, you send a message to windows. Any similar action, such as resizing the window, or moving the window will also send a message to that window. You can also send a message to your window yourself, but in this tutorial we'll stick to intercepting the generic messages that are already sent to our windows by the Operating System. You will see how it works in a minute. Windows Handles. You will see a lot of Handles when coding for the Win API. Handles are integers and they are used as identifiers for objects and the miscellaneous matters such as icons, windows menus, title bar text, cursors, sounds and so forth. Handles are often prefixed with an H. For example HICON is a handle to the icon that your window will use, very simple. Other handles include HDLG - to a dialog box, HWND - to a window, HMENU - to a menu. When you create a Windows program "from scratch", the first thing you want to be concerned about is the event handler(sometimes called the message handler) function. This is the first function that you want to write when starting a new windows program. As I said above, the event handler function takes care of all the messages that the window might send to it. After that you'll write your WinMain function; that's where you take care of the window class structure and finally create the window. So, what else is going on within the basic WinMain function? You will need to know the structure of the window class because you have to fill it in before creating the window itself. There are two window class structures WNDCLASS, and WNDCLASSEX. They are very similar, but the biggest difference is that WNDCLASS is the outdated class. For obvious reasons, you'll want to use the EX one and it looks like this: typedef struct _WNDCLASSEX The truth is: you will need to fill the above structure with some useful info before creating any window. After you're done with that you will need to register this class. To register a class you make a call to RegisterClassEx(&ex_class), you have to pass the pointer of the structure to it. If you decided to use WNDCLASS instead of WNDCLASSEX (for some reason) also use RegisterClass(&class) (without the Ex at the end). After that, you're ready to create your window. In our case you create a window with CreateWindowEx that takes a chunk of parameters. I'll write about them in the next tutorial, but basically all you do is tell the window what it should look like visually, define its name, and so forth. Let's look at the function prototype: HWND CreateWindowEx(DWORD dwExStyle, // window extended style Now we're ready to create the WinMain function After learning about the Event Handler and the WinMain function, you create the main event loop. Ok, it's time to write some code. But before I dive into the code I wanna say something about handles. You already know what they are. The following are some of the most important(to these tutorials) handles you will need to know about. For obvious reasons, you can name them anything you want, but here's what they are defined as in my programs: HWND hwnd; // handle to the window The device context handle won't be used in this tutorial but you still need to know about it. Why not? Because it'll be used mostly for drawing inside the window in the next tutorials. What about the window handle? It will be used during creation of the window. So here we go. This is the starting point of your Windows program: #include "windows.h" First you will need to include the windows.h header and define the window class name. You already know what those 2 handles are, so I'll skip their explanation here. The quit flag will indicate whether the program is running or not. As soon as you set the quit flag to true the program terminates. You will see how this works in the main loop which I'll show you in a few moments. // THE WINDOW EVENT HANDLER This is the even handler function, let's call it WinProc( ) for window processor, or process; whichever one you prefer. In reality, it processes all the messages that are being sent to the window. The only message we will worry about right now is the WM_CLOSE message. It is sent when the window is being closed. There's also a function called DefWindowProc at the end of WinProc which is being returned. That function takes care of the rest of the messages that you don't have to think about. Moving on to the most important function - WinMain( ). It will create and show the window. // WINMAIN Not a lot is going on over there actually, as it might seem at first. Most of the code is just flags and properties of the window followed by the message loop. That's all it takes to create a window. I'll briefly go over the most important flags used to create the window in WinMain( ) and the message loop to make it clear for you. I'll skip a few details that are obvious and don't need explanation. You'll just have to figure them out on your own (I did), it's not that hard. Of course, if you're a prodigy you can skip the rest of the tutorial and just type the code in and you're good to go. First you declare the message(msg) and the window class structure(ex). Then you have to fill in all of the data required by the ex structure. What's in this structure? This data will specify all kinds of properties, the window style, and assign the event handler function to the window to let the window know which function takes care of the messages(WinProc) being received by the window. The styles assigned to the window through ex.style can be combined by using the bitwise OR (|) operator. You can find a decent number of styles in the MVC Docs but you won't need to worry about all of them. We only need to OR three of them. By ORing the three flags: CS_HREDRAW|CS_VREDRAW|CS_OWNDC to the style parameter you tell the window to redraw the entire window if a movement or size adjustment changes the width(CS_HREDRAW) or the height(CS_VREDRAW) of the client area and that you want to allocates a unique device context for each window in the class(CS_OWNDC). The next two parameters(cbClsExtra and cbWndExtra) are always 0. They really have no high importance at this time. The icon and cursor parameters are obvious, you simply load them and they appear in your window. I use the default icon and cursor although you can load your own from a resource. You'll need to cast the GetStockObject(BLACK_BRUSH)'s result to (HBRUSH) and you'll have a black backgrounded window. I assign NULL to ex.lpszMenuName because it is used to attach a menu to the window and we are not doing this yet. ex.lpszClassName takes our previously defined Window Class Name string. Now we're ready to register the class by calling RegisterClassEx(&ex); The next part is actually creating the window and setting its width, height and position. The function CreateWindowEx( ) does that for us. Let's take a look at the parameters. The first parameter is an extended style and we never need that, it has to deal with the appearance of the window on the screen and we only need a plain window for a start, set that to NULL. You can always look up stuff in the MVC Docs so I don't have to rewrite a lot of text that's been written in there already. To describe all the possible extended styles would require a new tutorial. Let's get back to the second parameter, and it is as simple as the window class name string. The next parameter is a pointer to a null terminated string that will appear in the window's title bar as the window's name. The next parameter specifies the style of the window. This is a little different than the first parameter(the extended style) and we need to let the window know what it will look like, will it have a title bar?, and so forth. For a typical window with a title bar you will use the WS_OVERLAPPEDWINDOW flag. It is actually a combo of a bunch of other flags but they don't have to be OR'ed together so you would just use this flag alone to create a simple window quickly. Again, you can look up a whole horde of styles in the Docs or heck, on Google. Good luck! I want to go a little off topic of this tutorial and talk about full screen vs. window modes. For full-screen applications this flag (4th parameter of the CreateWindowEx function) would have been set to WS_POPUP and it would have created a void window with no controls or borders. So now you know that even if it's a full-screen app it is still a window, it just has no controls and is stretched over the whole size of your monitor's current screen resolution size, covering the rest of windows and makes you feel like nothing is behind. Moving on. The rest of parameters is very obvious. The x and y position of the window on the screen (0,0) and its width and height (300 x 300). Don't forget to pass the instance of the app. to WindowCreateEx( ). The parameters I set to NULL are not needed for this tutorial and you can just ignore them for now. Another useful option is to look them up in the MVC Docs or on Google. Okay, this was the last time I mentioned the MVC Docs on this web-site so, calm down and remember that they are always out there waiting for you to open them (unless you forgot to install it). After the CreateWindowEx( ) is called you have to show what-cha got. In other words you have to finally show the window on the screen. You do that by calling ShowWindow(SW_SHOW) followed by UpdateWindow(HWND hwnd) to "refresh" the window. At this point you have a successfully created window. The next part is creating the message loop. This is the loop your window goes around in until the user closes the window or hits Alt-F4. The message loop is nothing hard to comprehend. The program repeats itself while the quit flag is set to false. Whenever you set the quit flag to true the program should close the window and un-initialize itself. You have to see if there was a message and if there was you will process it. That's exactly what if(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)) { ... } does. Then you test whether the message is WM_QUIT and if it is, break the loop by assigning true to the quit flag. It's done with a simple test in my program: if(msg.message == WM_QUIT) quit = true; If you omit these two lines the window will disappear after you close it, however the loop will go on and you'll end up with a "lost" application. We then must call two generic windows functions: TranslateMessage(&msg) and DispatchMessage(&msg). At the ending point of your program you return control to Windows. It's like calling return 0; from a console application. And that's it; by this time you should have your window up and running.
Other articles you might like:
|
© 2007-09 Authentic Society Only information matters. Page load time: 0.024ms