You are on page 1of 7

Johnnie's Win32 API Tutorial

by Johnnie Rose, Jr. If you're a Windows programming novice, retrieve your favorite beverage, sit back, and take a quick trip over to MSDN or download the code for the entire tutorial. You're about to become a Windows developer.

Tutorial Hotspots: Creating the


Window Class

As such, you are placed in the peculiar position of holding the Instant power to directly interact with the operating system via your Messaging programs. The first function with which you must become The Window comfortable is WinMain(). Windows passes control to this function Procedure after program code and data have been loaded from the More Tutorials and Links executable, paging tables readied, memory reserved and allocated, etc. Window-creation code is traditionally placed within or "close to" WinMain(), though not every Windows program has a See Also: Johnnie's main window. Before we get into specifics, let's see a structural Winsock outline:
Tutorial

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) hInstance is a handle to this application's executable used to load resources into the program's memory space, an operation you'll witness later on. hPrevInstance is a handle to the previous instance of the program, usually NULL. As its name might suggest, lpCmdLine is a string specifying the name and arguments sent to the program. Finally, nCmdShow specifies the current show state of the window. To generate something visually appealing, we need to put some code in WinMain() to create a window. This involves telling the system about the window, displaying the window, and arranging the system such that the window can receive messages.

Bookmark
(MSIE only)

Print

for offline reading

View

the links and books Johnnie recommends

Creating the Window Class


We'll need to identify a structure to continue: WNDCLASS: Structure utilized to access and set vital attributes of a window. The exposed attributes include the window's associated icon, menu, and background color. struct WNDCLASS { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance;

// // // // //

Any combination of many styles Address of this window's procedure Extra bytes (not required) Extra bytes (not required) This window's instance

HICON window HCURSOR you'd like HBRUSH LPCTSTR LPCTSTR };

hIcon; hCursor; hbrBackground; lpszMenuName; lpszClassName;

//

Handle to an icon to use with this // Specifies the kind of cursor

// // //

Background color Name of the menu we would use User-defined, custom name for the class

Alright, let's start off our WinMain():

#include <windows.h>

// windows.h must be included

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { We need to define one of these structures in WinMain(): WNDCLASS wc; wc.style = CS_VREDRAW | CS_HREDRAW; // Basically repaint the window anytime its size changes wc.lpfnWndProc = MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // Default application icon wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Plain, default cursor wc.hbrBackground = (HBRUSH)(COLOR_SCROLLBAR+1); // Grey background wc.lpszMenuName = 0; wc.lpszClassName = "MyWin32App";

lpszClassName can be any name you like; here it's the descriptive "MyWin32App." lpfnWndProc is a very important option. This function receives all the messages for the window, and is generally responsible for keeping it up to date with the rest of the operating system. (More about messages later.) style denotes all the possible class styles you can type to customize how your class acts. As you might have noticed, a trick to get two or more styles into one field is to separate them with the OR operator | (also known as the vertical pipe), which will be used frequently in Windows programming. The remainder of the fields are set to default values. Had we wanted to attach a menu to our window, we would have specified the menu's name in the lpszMenuName field. The next step is to register the class with Windows so we can use it, with a little error checking:

if (!RegisterClass(&wc)) wasn't registered, return 0;

// If the class // Exit

Now, we use CreateWindow() to set up the graphical portion:

HWND hwnd; hwnd = CreateWindow("MyWin32App", registered class "Johnnie's Win32 Example", WS_OVERLAPPEDWINDOW, of many window styles CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, window's parent NULL, hInstance, hInstance NULL); parameter to window if (hwnd == NULL) creation failed return 0; // // // // // // // // // // // // // Name of Window name/title Any combination X coordinate Y coordinate Width Height Handle to this Handle to a menu Handle to Optional If window Exit

Using WS_OVERLAPPEDWINDOW ensures that the window is created with all the common attributes, including a minimize and maximize button, title bar, and distinct border. CW_USEDEFAULT keeps us from having to determine the initial position and size of the window, letting the system do the grunt work instead. Both the Y coordinate and height fields are set to 0 because CreateWindow() ignores these parameters when CW_USEDEFAULT is implemented. Finally, the window is displayed on screen using the fourth argument to WinMain():

ShowWindow(hwnd, nCmdShow); used the first time called in WinMain()

// //

nCmdShow MUST be ShowWindow() is

Instant Messaging
Microsoft being the naturally innovative company that it is (consider that last statement sarcastic if you like), it had to come up with new management since programs now had to appear as though they could process user input and respond to system events simultaneously. (In case you were wondering, that's not actually what happens. As with all multi-tasking, only one thing can really happen at a time, and so the CPU allots specific amounts of processing time to each thread. Even then, time is only given to "important" threads.) A messaging system was created as a result of this new requirement, where the system and other windows communicate with your window via messages. For example, clicking the close button on your browser window sends a WM_DESTROY message, the browser performs any final tasks it needs to, and gives up its CPU time share, formally ending its execution. Since you're creating a window, you can control how these messages affect your program. All this logic is done inside a function called a window procedure, which was

specified when the window class was created in the lpfnWndProc field. Thankfully, there's a DefWindowProc() that will handle messages we don't process so we don't have to implement every possible message. Whenever a message is sent to a window, the command is added to the window's queue, and those entries must be translated and sent to the window procedure to be of any use. This loop of getting a message, translating it, and dispatching to a procedure is called the message loop, and usually continues until the program ends. There are many variations, but the following is the most basic and will appear in our WinMain():

MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { into MSG variable TranslateMessage(&msg); keyboard-specific messages DispatchMessage(&msg); the window procedure } } // // // Put a message Translate Send it off to

That process continues until the program signals that it's ready to be destroyed and posts a quit message. So, what's this window procedure look like?

The Window Procedure


A quick search on MSDN reveals WindowProc()'s definition to be:

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) hwnd is the window we're talking about. uMsg, of course, is the identifier telling the function what message has been sent. As their names might suggest, wParam and lParam are additional parameters containing information dependent on the message. DefWindowProc() has essentially the same definition, making it extremely easy to pass it un-processed messages for default action. The most common practice for coding window procs is to have a massive switch statement at the base with case statements representing possible messages. With that in mind, let's start off our MainWndProc():

LRESULT WINAPI MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { default: return DefWindowProc(hwnd, msg, wParam, lParam); // We don't deal with it, let somebody else do it break;

The obscenely important reason why procedures are introduced so early is because that call to CreateWindow() will fail if the function sees a WM_CREATE message isn't intercepted. Interestingly enough, we could run our window just off of the above code and let DefWindowProc() handle everything for us. To process a message, add a case statement with the message identifier as the switch value and appropriate code below. For example, if we wanted the program to tell us when it's created (and ease whining from CreateWindow()):

case WM_CREATE: // If the message is WM_CREATE, display alert MessageBox(NULL, "The sweet smell of success.", "Indication", MB_OK); break;

Note:

MessageBox() displays a dialog box with an OK button and message. Here, the dialog box is not directly associated with our window. WM_CREATE, by the way, is a very good time to initialize any other graphical elements you may have. A rather large list of messages that can be sent to a window can be found here. Now let's make sure the close button (X) will work and the user can exit without using Ctrl+Alt+Del:

case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: imminent PostQuitMessage(0); share/give OS control break; } }

// // // //

User wants out Calls WM_DESTROY If termination is Give up time

And the finished procedure covers three messages; the program at a lean 63 lines.

More Tutorials and Links


This tutorial was designed to introduce you to fundamental concepts that will allow you to directly interact with any Windows operating system. You now have the ability to write Windows applications! To supplement your knowledge, see the following texts and other Web-based tutorials:

theForger's Win32 API Tutorial


Comprehensive.

the Stromcode Win32/C++ Tutorial


A 19-page beast of a tutorial covering much.

@Amazon: Programming Windows, Fifth Edition


Programming Windows is perhaps the most celebrated book dedicated to the intricacies of Windows programming. I have yet to meet a professional Windows developer who did not have this text sitting on a nearby bookshelf poised for instant reference. Charles Petzold's work provides an in-depth look into many areas of Windows, including chapters covering the messaging model, various window types and graphical controls, and multimedia. Other subjects include memory models, multithreading, and network programming. View More Information & Reviews
@ Amazon.com

@Amazon: Programming Windows with MFC


Would you prefer not to dabble in the specifics of window creation and message retrieval? Would you like to use a framework of helper classes that allows you to quickly bypass rewriting common code and frees you to concentrate your efforts toward meeting your application's goals (within that deadline)? This framework, named the Microsoft Foundation Classes, or MFC, does exist and is particularly well-documented in Jeff Prosise's Programming Windows with MFC. If you're considering MFC for your next project and favor clear, concise explanations, Programming Windows with MFC is an admirable addition to your development library. View More Information & Reviews
@ Amazon.com

@Amazon: Programming Applications for Microsoft Windows


Programming Applications for Microsoft Windows is designed for those developers who feel compelled to uncover what's hidden under the hood of the Windows operating systems. Harness the power of threads, fibers, and thread pools, or put to use advanced DLL techniques to create a custom, extensible plugin system for your application. Or, learn of structured exception handling, Unicode, and exactly what the Windows memory manager does when you desire a couple bytes of fresh scratch space. Next, discover memory-mapped files, said to be the most efficient method of file manipulation, peruse thread local storage, and finally read that last chapter on hardware communication to round out your knowledge. View More Information & Reviews
@ Amazon.com

the Microsoft Developer Network


Microsoft's online reference guide.

You might also like