*********************************************** * A beginners guide to programming * * the Win32 SDK. * * By Stephen Haunts * * * * PART 1 * * T H E B A R E B O N E S * *********************************************** This document serves as a basic introduction to Win32 programming. If your interested in games delevopment with DirectX then you will probable write your programs in a different style to what is explained here for the purposes of speed. But even so, you still need to know the basics. Before you can get a good grasp of windows programming with the Win32 it is recommended that you have a fairly strong understanding of writting DOS applications in C and/or C++. Although this document covers the bare bones of Win32 programming it is quite a heavy read if your not familiar with this system. It may take a while to get a good grasp of the underlying system behind Win32. The method of programming is quite different to that of DOS based programming in C. The bit that throws most people is the idea of message maps ect. The some people that the Win32 ways look quite alien and un C like sometimes. But don't worry. If I can learn Win32 then you can. This document builds up a simple windows style hello world program to illustrate the basic concepts to Win32 programming (The source code for this programm will be bolted on at the end). I will not cover menus and other resources in this document because I dont want to confuse the issue. You have to get a grasp of the basics first. Resources and possiby DirectX will come in different documents. Hell I may even make a series of programming articals relating to different aspects of windows development. What do you think? If you have any constructive comments about this document (spelling mistakes aswell) then please mail me at the following address: S.B.B.Haunts@herts.ac.uk PLEASE NO FLAMING. I GET QUITE NASTY IF PEOPLE FLAME ME FOR SOME STUPID PETTY REASON WITHOUT GIVING A FULL EXPLAINATION. Why Did I Write This Document ? ------------------------------- Good question. I my self am personnaly learning to program in windows. I feel the best way to get complicated issues to stick in my head are to write short notes on them. Because I havn't really found any decent resources on the net for beginners in Win32 I decided to write up my notes and publish them for you all to view/download/print for free. Arn't I nice :-) Who The Hell Am I ? ------------------- My name is Stephen Haunts and I am 20 years old. I am currently studying for a BSc Hons Degree in Computer Science at the University of hertfordshire. I have just completed my 2nd year of studies and am about to start my 1 years industry placement, for whome I will be working for Argonaut Software (those of Star Wing fame on the Super Nintendo console). I have always been a DOS programmer on the PC but my job requires me to train up in Windows programming and DirectX. OK Here we go folks, have fun :-) Intoduction to windows programming 'WinHello' --------------------------------------------- Traditionally the introductory program has always been a hello world message. Under dos such a program could be written in only a few lines but under windows you are looking at more like a 100 lines of code 'OUCH.' Thats even worse than a hello world program in assembler :-). When you are working on a large project though the total size of you windows program may actually end up being less than that of a DOS program (lines of code that is). The WinMain Procedure --------------------- Just as every do DOS C program has a procedure called main at its heart, every windows program has a similar entry point with the title WinMain (and, yes, this title is case sensative). Also, just as a DOS C program may include provisions within the main procedure declaration to retrieve command-line parameters, the WinMain declaration includes a similar provision in the lpszCmdParam parameter, even though command-line parameters are rarely used under windows. However, unlike in DOS programming, the declarations used for WinMain are not optional and must be declared exactly in the order and form shown, regardless of whether each specific argument will be used or ingored. Also note that the reserved word PASCAL is used in al exported function declarations, indicating to the compiler that Pascal rather than C ordering is used for all arguments(values) pused onto the stack. While C commonly uses inverted ordering, placing the least-significant bytes first on the stack, windows ises pascal ordering which, like Unix, places the most-significant bytes first. Here is the declaration used for WinMain: int PASCAL WinMain ( HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow ) Of the four calling arguments, the first two are of primary importance. The data type HANDLE refers to a 32-bit, unsigned value; the hInstance and hPrevInstance are unique identifiers supplied by windowsNT and 95 systems. Inlike DOS applications where where only one program (TSRs excepted) is active at a time, multitasking systems require unique identification, not only for each application, but also for each instance of an application of an application that may be executing. Ergo, the hInstance and hPrevInstance parameters are assigned only when an application instance becomes active. they provide equivalents of the "task ID" and "process ID" values common in other multitasking environments. The hPrevInstance (previous instance) identifier is the hInstance identifier previously assigned to the most recent instance of an application that is already excuting. If there is no previous instance of the application currrently running, which is frequently the case, this argument will by null(0). The reason for this second process identifier will be demonstrated presently. The third prameter, lpszCmdParam, is a long (FAR) pointer to a null-terminated (ASCIIZ) string containing any command-line parameters passed to the program instance. The fourth calling parameter, nCmdShow, is simply an integer argument indicating whether the newly launched application will be displayed as a normal window or initially displayed as an icon. Next, following the procedure declaration itself, a brief list of local variable declarations appears. { static char szAppName[] = "WinHello"; HWND hwnd; MSG msg; WNDCLASS wc; The data types used in the declaration will be covered in more detail later in the document. Here is a quike rundown: * HWND identifies a window handle * MSG identifies a message value * WNDCLASS refers to a recford structure used to pass a number of values relevant to the application's main window. Registering a Window Class -------------------------- The first task accomplished within the WinMain procedure depends on the hPrecInstance argument passed. If a previous instance of this application is already active, there's no need to register the window class a second time. But it's more likely, of course, that this is the first instance of the app- lication (hPrevinstance is null) and, therefore, the window class definitions must be assigned and the window class registered. The wc srtructure is defined in Windows.H (which must be included in all windows applications). Of the WNDCLASS record fields, the second of the fields can usually remain unchanged from one application to another The first field is the window-style specification. In this example, it is assigned two style flag values combined by ORing bitwise. These flags are defined in windows.h as 16-bit constants and shall be explained later. Here the CS_HREDRAW and CS_VREDRAW flags indicate that the following windows should be redrawn completely anytime the horizontal or vertical size changes. Thus, for the WinHello demo, if the window size changes, the window display is completely redrawn, with the hello message string recentered in the new display. if (! hPrevInstance ) { wc.style = CS_HREDRAW | CS_VREDRAW; cs.lpfnWndProc = WndProc; The second field in the WNDCLASS structure, lpfnWndProc, is a pointer to the exported procedure WndProc, in this example - which will handle all windows messages for this application. The type prefix lpfn identifies this field as a "long pointer to function." But realize that these prefic conventions are provided for the beifit of the programmer. Tey are not absaolutes, nor do these designations place any contraints on the compiler. The next two record fields are integers, which are resereved to specify extra information about the class or window styles. Commonly, neither is required and, by default, both are initialized as zeros (0). Incidentally, the cb_ prefix stands for count of bytes. wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; The next field, hInstance, is simply the recipient of the hInstance argument passed by windows when the program is initially called. This is also one field assignment that can be considered constant for all applications. The next three data fields currently assign default values for the application's icon, cursor, and background color and pattern. wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wc.hCursor = LoadCursor( Null, IDC_ARROW ); wc.hbrBackground = GetStockObject( WHITE_BRUSH ); The default IDI_APPLICATION specification for the icon assigns the pre- defined image of a white square with a black border. The IDC_ARROW cursor assigns the stock cursor graphic of a slanted arrow. In the third asignment, the hbrBackground field contains the background colour and pattern used for the application's client region. The hbr stands for handle to brush, where "brush" refers to a pixel patterm used to fill or paint an area. Next, since this application does not have a menu assigned, the menu name is entered as a null value. The class name (lpszClassName) is assigned the null- terminated (ASCIIZ) string defined previously. wc.lpszMenuName = NULL; wc.lpszClassName = szAppName; RegisterClass( &wc ); } And last within this conditional subprocess, the RegisterClass function is called with the wc structure passed as a paramater (by address) to register this window class definition with the NT/95 operating system. Creating an Application Window ------------------------------ While the previous step, registering a window class, has defined char- acteristics that are common to all instances of the application, this is not yet created the application window itself. Instead, unlike the RegisterClass function call, which is called only once, every instance of the application must call the CreateWindow function to produce the actual window display. The handle to the application window that is returned by the CreateWindow function will be used later as an argument in other function calls as a unique itentifier for the actual window belonging to the application instance. But, while many properties of the application class have already been defined, other properties have already been defined, other properties specific to this instance of the application have not; they are passed now as parameters to the CreateWindow function. hWnd = CreateWindow( szAppName, // window class name "Hello, World - NT Style", // window caption WS_OVERLAPPEDWINDOW, // window style CW_USERDEFAULT, // initial X position CW_USERDEFAULT, // initial Y position CW_USERDEFAULT, // initial X size CW_USERDEFAULT, // initial Y size The first two parameters passed are the application class name - the same ASCIIZ string that was used when the class was registered - and the app- lication's initial window aption. If you don't want a caption, then pass this as null. The third parameter defines the window style, generically, is passed as WS_OVERlAPPEDWINDOW, a value that is a combination of individual flags defined in windows.h. The fourth through seventh parameter established the applicaiton window's initial position and size. They can be passed as explicit values or, more often, as CW_USERDEFAULT. This parameter instructs windows to use the default values for an overlapped window, positioning each successive overlapped window at a stepped horizontal and vertical offset from the upper- left corner of the screen. The next parameter is passed as null for the simple reason that this application is not associated with a parent window. Alternatively, if this window were to be called as a shild process belonging to another aplication, the parent's window hadle would be passed as a parameter here. NULL, // parent window handle NULL, // window menu handle The ninth parameter using in calling the CreateWindow function is also passed as null, directing the appliation to use the default system menu. Note, however that the menu in question is the windows fram's pull-down menu (upper -left icon on most window frames), not the menu (or toolbar), which is defined as an application resource and assigned during application class registration. The tenth calling parameter, which can never be passed as null, is the same instance handle originally supplied by the NT/95 system. hInstance, // program instance handle NULL ); // creation parameters The final parameter, again null in this example, may in other cases provide a pointer to additional data for use either by the application window or by some subsequent process. In most examples, however, this will be an empty (null) argument. Now, after CreateWindow has been called, the application window has been created internally in NT/95 "world view" but does not yet appear on the actual screen display. Therefore, the next step is to call the ShowWindow function, passing as parameters the hwnd value returned by CreateWindow and the nCmdShow argument supplied when Winmain was initially called. ShowWindow( hwnd, nCmdShow ); UpdateWindow( hwnd ); The ShowWindow function, however, contrary to what you might assume, does only a portion of the task of creating (painting) the window display. It is principally responsible for creating the window frame, caption bar, menu bar, and minimize/maximize buttons. But what this function does not create is the client window area -the display area specific to the application itself. Therefore, one more function call is necessary before the window display is complete: a call to the UpdateWindow function with the hwnd window handle as an argument (which actually posts a WM_PAINT message to the application instructing it to repaint its own window area- a process that will be discussed in a moment. The Message-Handling Loop ------------------------- Windows creates and manages a seperate message queue for each active windows program instance. Thus, when and keyboard or mouse event occurs, windows translates this event into a message value. This value is placed in the application's message queue. where it waits until it is retrieved by the applicationsinstance, which is precisely the purpose of the message-handling loop. The message handling loop begins by calling the GetMessage function to retrieve messages from the application instance's message queue. As long as the message retrieved is not a WM_QUIT message (0x0012), GetMessage will return a TRUE (nonzero) result. The actual message value is returned in the msg structure which was passed by address. while( GetMessage( &msg, NULL, 0, 0) ) { The syntax for the GetMessage function is defined as: BOOL GetMessage( lpMsg, HWND, wMsgFilterMin, wMsgFilterMax ) In most cases, only the first parameter is actually used (to return the message itself). The remaining three parameters are usually passed as null or zero. The initial parameter is a pointer to a message structure to receive the message information retrieved and, subsequently, to pass this data on though to the TranslateMessage and DispatchMessage functions. And, obviously, without this parameter, there would be little point in calling the GetMessage function at all. The third and fourth parameters provide filter capabilities, restricting the message types returned. When both parameters are passed as 0, no filtering occurs. Alternatively, constants such as WM_KEYFIRST and WM_KEYLASY could be passed as filter values to restrict message retrieval to keyboard events or, by using WM_MOUSEFIRST and WM_MOUSELAST, to retrieve only mouse-related messages. filters and window selection aside, however, the GetMessage function (together with the PeekMessage and WaitMessage functions) has another important char- acteristic. Conventionally, loop statements monopolize the system until terminated, thus preempting or preventing other operations for the duration of the loop. And, in other circumstances -remember this as a caution -even under windows, loop operations can tie up system resources. The GetMessage function, however, has the ability to preemp the loop operation to yield control to other applications when no messages are available for the current application, or when WM_PAINT or WM_TIMER messages directed to other tasks are available. Thus, it can give other applications their share of CPU time to execute. For the present, when the aplication recieved an event messsage (other than WM_QUIT), the message value is passed. First, it goes to the windows Translate- Message function for and keystroke translation that may be specific to the application. Then it is passed to the DispatchMessage handler, where the message information is passed to the next appropriate message-handling procedure (back to windows, either for immediate handling or, indirectly, for forwarding to the exported WndProc procedure). TranslateMessage( &msg ); DispatchMessage( &msg ); } Finally, when the message-processing loop terminates, the wParam argument from the final message retrieved is, in turn, returned to the calling application -the NT/95 desktop itself. return msg.wParam; } Messages and Event-Driven Programming ------------------------------------- In its simplest form, message driven programming (also known as event driven programming) is a process by which various subprocesses and/ or applications communicate. In windows, messages are the process used by windows itself to manage a multitasking system and to share keyboard, mouse, and other resources by distributing information to applications, application instances, and processes within an application. Thus, under windows, instead of applications recieving information directly from the keyboard or the mouse driver, the NT/95 operating system intercepts all input information, packaging this information using the MSG message structure and then forwarding the prepared messages to the appropriate recipients. In turn, the recipient aplications use TranslateMessage for application-specific interpretation (particularly accelerator key assignments) before calling DispatchMessage to forward individual traffic items to their appropriate handlers. Furthor more, the process descipbed is not limited to keyboard and mouse events. Instead, this includes all input devices (including ports), as well as messages generated by application and child subprocesses, windows timers, or, quite frequently by windows itself. Abstract descriptions, however, provide only a theoretical outline without really illustrating how these processes function. The Message Record Structure ---------------------------- The MSG (message structure) record type is defined in WinUser.h as typedef struct tagMSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG; The POINT data type is defined in WinDef.h as: typedef struct tagPOINT { int x; int y; } POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT; The message-event fields are used as: - hWnd: The handler of the specific window to which the message is directed. Please note that each application is itself composed of a series of seperate windows. These windows include the frame, the caption bar, the system menu, and minimize and maximize buttome, as well as the application's main display window. Normally, only messages directed to the client window will be forwarded, by the DispatchMessage proc', to the application's WndProc procedure. Messages directed to other application windows are generally handled indirectly by NT/95, even though this may result, in turn, in further messages being sent to the client window. - message: A 16bit value identifying the message. Constants corresponding to all message values are provided though windows.h and begin with the WM_ prefix (which stands for windows message). For example, a mouse button event message might be identified by the constant WM_LBUTTON. - wParam: A 32bit (double word) message parameter. The value format and meaning depend on the primary event message type. Variously, the wParam argument might convey a coordinate point pair, use the low word value to identify a secondary message type, provde some other type of data, of be ignored entirely. In many cases, the wParam value will be treated as two seperate word values with different functions. - lParam: A 32bit (long) message parameter. The value and meaning of this parameter depend on the primary event message type. Variously, the lParam argument might provide a pointer to a string or record structure; break down as a group of word, byte, or flag values; or, quite frequently, be completely unused. - time: The double word time value identifies the time the message was placed in the message queue. - pt: This field contains the mouse coordinates at the time the message was placed in the message queue (irrespective of the message-event type or origin). Note that these last two fields are not passed to the WndProc procedure. Instead, these two fields are used only by NT/95, principally to resolve any conflict over the order of events and, of course, to determine where a specific event should be addressed. The WndProc Procedure --------------------- The WndProc procedure is the point where each application actually begins to function. Remember, the WndProc procedure recieves messages indirectly from the NT/95 operating system, but the WndProc procedure determines the application's response to the messages received. Previously, when the application window class was registered, the address of the WndProc subroutine wassed to windows as: wc.lpfnWndProc = WndProc; And, given this address, windows calls WndProc directly, passing event messages in the form of four parameters, as: long FAR PASCAL WndProc( HWND hwnd, UINT msg, UINT wParam, LONG lPARAM ) The four calling parameters received correspond to the first four fields of the message structure described above, beginning with the hwnd parameter. identifying the window to which the message is directed. Since most applications have only one client window that will be addressed thus, this parameter may seem superfuous. This parameter will, however, frequently be needed as an argument for use by other processes. At the present, it's the second calling parameter, msg, that is immediately crucial and identifies the window event message. The third and fourth parameters, wParam and lParam, provide amplifying information to accompany the window event message. Typically, the WndProc procedure does relatively little or nothing itself outside the switch...case responding to the msg parameter. In the hello program demo, local response is provided for only two event messages: the WM_PAINT and WM_DESTROY messages. All other event messages handled are by default (by the NT/95 operating systems). The first of these two, WM_PAINT, is a message that is generally not issued directly. It will be issued indirectly anytime an application window is created, moved, resized, restored from an icon, uncovered by a change in some other application window, or something else has occured -in this or in some other application- to invalidate the client area of the present application. The DOS equivalent of the Hello program would consist principally of a print statement, possibly with an optional clear screen statement. For the windows version, however, there are differences for two main reasons: * Because the response to the WM_PAINT message is not a one-time occurance. * Because a bit more is accomplished than simply dumping the text to the screen. The first requirement, before anything can be written to the client window, is for the application to retrieve a handle (hdc) to the device context (the output device or, in this example, the screen). After the screen update is finished, this handle will be released by calling the endpaint function. switch( msg ) { case WM_PAINT: hdc = BeginPaint( hwnd, &ps ); GetClientRect( hwnd, &rect ); After retrieving the device context handle, the GetClientRect procedure is called to retrieve the rect structure with coordinates describing the client window. The rect structure consists of four fields, which report coordinates for the client window. However, the coordinates reported are relative to the client window itself. Therefore, the left and top fields are returned as zeros, and the right and bottom fields return the current width and hight of the client window (reported in pixels). Once the window coordinates have been retreived, the rect structure can be used as an argument in the next step to specify the region where the actual message will be drawn. DrawText( hdc, "Hello World", -1, &rect, DT_SINGLELINE | DT_CENTRE | DT_VCENTER ); Since print statements, per se, cannot be used in windows (because they are unsuited for a graphics display environment), the DrawText function is used instead. DrawText begins with the hdc argument providing access to the active display, followed by the string (text) to be drawn. The third parameter, -1, indicates that the string argument is a null-terminated string. Alternatively, this parameter could be a value specifying the string length, with the second parameter an indirect reference to a character array. The fourth argument is the address of the rect structure, identifying an area where the string will be drawn. The fifth argument is a combination of flags that set alignment and ristrict the text drawn to a single display line. Last, the EndPaint function is called, again with the client window handle and the paint structure (ps) as argument. This function releases the device context and validates the now-restored client area, and incidentally, completes the response to the WM_PAINT message. EndPaint( hwnd, &ps ); return( 0 ); The second application message requiring a local resonse is the WM_DESTROY message, which is issued when the application is ready to close. This message can be generated via several channels. For this example though it is issued only if/when the system menu close option is selected. case WM_DESTROY: PostQuitMessage(0); break; The WM_DESTROY message is issued to give the application an opportunity to do any necessary cleanup before shutting down. Therefore, as circumstances demand the application response at this point could include provisions for calling a dialog box to requiest confirmation, for closing/saving files, or for any other final tasks required for a smooth exit. Finally (unless, of course, termination is to be aborted), the WN_DESTROY response is completed by calling the PostQuitMessage function, which in turn, places a WM_QUIT message in the application's message queue to terminate the message loop in WinMain. Explicit handling has been provided for only two of the messages that might be sent to this application. Provisions are also required to return to windows for procesing all mssages that have not been explicitly handled here, as a default case. default: // is msg unprocessed return( // return to windows DefWindowProc( hwnd, msg, wParam, lParam ) ); } return( NULL ); } This default provision returns the message -precisely as it was originally received- to windows, then also returns the results from DefWindowProc to the windows calling process. This final provision should be considered standard for all WndPoc message-handler procedures. For a windows program the .C source code is only a part of the story. In most cases, the application will also incorporate an .H header file and, almost always, a .RES resource file. Here is the complete source code for the hello world program. You can just cut out the program from this document and compile it straght off. The code should work under any windows compiler with the Win32 libraries. I have only tested the code so far under Microsoft Visual C v4. 8<-----------------Cut-out-this-code-and-compile-it-------------------------- //===================================// // Hello.C // // HELLO WORLD // //===================================// #include long APIENTRY WndProc( HWND hwnd, UINT msg, UINT wParam, LONG lParam ) { HDC hdc; PAINTSTRUCT ps; RECT rect; switch( msg ) { case WM_PAINT: hdc = BeginPaint( hwnd, &ps ); GetClientRect( hwnd, &rect ); DrawText( hdc, "Hello, World! Muddy Funsters", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER ); EndPaint( hwnd, &ps ); return( 0 ); case WM_DESTROY: // message: window being destroyed PostQuitMessage(0); break; default: // if msg unproccessed, // return to Windows return( DefWindowProc( hwnd, msg, wParam, lParam ) ); } return TRUE; } int APIENTRY WinMain( HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow ) { static char szAppName[] = "WinHello"; HWND hwnd; MSG msg; WNDCLASS wc; if( ! hPrevInstance ) { wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = GetStockObject( WHITE_BRUSH ); wc.lpszMenuName = NULL; wc.lpszClassName = szAppName; RegisterClass( &wc ); } hwnd = CreateWindow( szAppName, // window class name "Muddy Funster Software", // window caption WS_OVERLAPPEDWINDOW, // window style 100, // initial X position 100, // initial Y position 400, // initial X size 200, // initial Y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL ); // creation parameters ShowWindow( hwnd, nCmdShow ); UpdateWindow( hwnd ); while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } return msg.wParam; } 8<-------------------------------------------------------------------------- Windows Conventions and Data Types ---------------------------------- This following section describes some windows NT/95 conventions for naming, as well as some of the windows data types, data structures, and handle identifiers. Variable Names and Hungarian Notation ------------------------------------- As programs have become more complex in terms both of size and of the proliferation of data types, many programmers have adopted a variable-naming convention, which is commonly fered to as Hungarian notation (named in honor of Microsoft programmer, Charles Simonyi). Using Hungarian notation, variable names begin with one or more lowercase letters, which denote the variable type, thus providing an inherent identification. For example, the prefix h is used to identify a handle, as in hWnd or hDlg, refering to a window and dialog handles, respectively. In like fasion, the prefix lpsz identifies a long pointer to a null-terminated (ASCIIZ) string. The followng table summarizes the Hungarian notation conventions. These aren't cast in stone though, you can come up with variations. ---------------------------------------------------- | PREFIX | DATA TYPE | |-----------+--------------------------------------| | d | boolean | | by | byte or unsigned char | | c | char | | cx/cy | short used as size | | dw | DWORD, double word or unsigned long | | fn | function | | h | handle | | i | int | | l | long | | n | short int | | s | string | | sz | ASCIIZ null-terminated string | | w | WORD unsigned int | | x,y | short used as coordinates | |--------------------------------------------------| Predefined Constants -------------------- Windows also uses an exclusive list of predefined constants, which are used as messages, flag values, and other operational parameters. These constants values are always uppercase, and most include a two or three letter prefix set off by an underscore. Here are some examples. CS_HREDRAW CS_VREDRAW CW_USERDEFAULT DT_CENTER DT_SINGLELINE DT_VCENTER IDC_ARROW IDI_APPLICATION WM_DESTROY WM_PAINT WS_OVERLAPPEDWINDOW In the case of constant identifiers, the prefixes indicate the general category or the constant. The table below shows the meaning of the prefixes. ---------------------------------------------------- | PREFIX | CATEGORY | |-----------+--------------------------------------| | CS | Class style | | CW | Create window | | DT | Draw text | | IDC | Cursor ID | | IDI | Icon ID | | WM | Window message | | WS | Window style | ---------------------------------------------------- Data Types ---------- Windows also uses a wide variety of new data types and type identifiers, most of which are defined in either the WinDef.h or WinUser.H header files. ------------------------------------------------------ | DATA TYPE | MEANING | |-----------+----------------------------------------| | FAR | Same as far | | PASCAL | Same as pascal | | WORD | Unsigned integer (16 bits) | | UINT | unsigned integer, same as word | | DWORD | double word, unsigned long int (32bits)| | LONG | signed long pointer to character string| | LPSTR | long (far) pointer to character string | ------------------------------------------------------ Data Structures --------------- Similarly, windows adds a variety of new data structures. Again, most are defined in either WinDef.h or WinUser.h. --------------------------------------------------------------- | STRUCTURE | EXAMPLE | MEANING | |--------------+---------+------------------------------------| | MSG | msg | Message structure | | PAINTSTRUCT | ps | Paint structure | | PT | pt | Point structure (mouse position) | | RECT | rect | Rectangle struc',2 coordinate pairs| | WNDCLASS | wc | Window class structure | --------------------------------------------------------------- Handle Identifiers ------------------ In like fasion, a variety of handles are defined for use with different windows elements. Like constants, the handle types use all uppercase. The following table shows a few examples. ---------------------------------------------------------------- | HANDLE TYPE | EXAMPLES | MEANING | |--------------+-------------+---------------------------------| | HANDLE |hnd or hdl | Generic handle | | HWND |hwnd or hWnd | Window handle | | HDC |hdc or hDC | Device context handle (CRT) | | HBRUSH |hbr or hBrush| Paint brush handle | | HPEN |hpen or hPen | Drawing pen handle | ----------------------------------------------------------------