Please consider a donation to the Higher Intellect project. See https://preterhuman.net/donate.php or the Donate to Higher Intellect page for more info.

Programming the Win32 SDK: Difference between revisions

From Higher Intellect Vintage Wiki
No edit summary
No edit summary
 
Line 833: Line 833:
</pre>
</pre>


[[Category:Computing]][[Category:Microsoft]][[Category:Programming]]
[[Category:Microsoft]][[Category:Programming]]

Latest revision as of 00:13, 4 August 2020

               ***********************************************
               *       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 development 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 writing 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 etc.

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 program 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?


Why Did I Write This Document ?

Good question. I my self am personally 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 haven'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. Aren'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 whom 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 :-)


Introduction 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 sensitive). 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 ignored.

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) pushed onto the stack. While C commonly uses inverted ordering, placing the least-significant bytes first on the stack, windows uses 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.

Unlike 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 executing. If there is no previous instance of the application currently 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 quick 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 application (hPrevinstance is null) and, therefore, the window class definitions must be assigned and the window class registered.

The wc structure 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 prefix conventions are provided for the benefit of the programmer. They are not absolutes, nor do these designations place any constraints on the compiler.

The next two record fields are integers, which are reserved 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 assignment, 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 pattern 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 parameter (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 characteristics 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 identifier 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 application's initial window caption. 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 application 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 child process belonging to another application, the parent's window handle 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 application to use the default system menu. Note, however that the menu in question is the windows frame'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 separate 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 characteristic.

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 preempt 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 application received an event message (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 receiving 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 applications use TranslateMessage for application-specific interpretation (particularly accelerator key assignments) before calling DispatchMessage to forward individual traffic items to their appropriate handlers.

Further more, the process described 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 receives 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 passed 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 superfluous. 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 occurred -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 occurrence.
  • 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 height of the client window (reported in pixels).

Once the window coordinates have been retrieved, 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 restrict 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 response 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 request 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 processing all messages 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 straight 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 <windows.h>

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 referred 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, referring to a window and dialog handles, respectively. In like fashion, the prefix lpsz identifies a long pointer to a null-terminated (ASCIIZ) string.

The following 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 fashion, 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              |
      ----------------------------------------------------------------