---------------------------------------------------------------------------
    -----------------------------------------------------------------------
            - A L W A Y S   U N D E R    C O N S T R U C T I O N -

           $$$$$$$$   $$$$$$$$  $$$$$$$$$$$$$   $$$$$$$$   $$$$$$$$
          $$$$$ $$$$ $$$$$ $$$$ $$$$$ $$$$ $$$ $$$$$ $$$$ $$$$$ $$$$
          $$$$$ $$$$ $$$$$      $$$$$ $$$$ $$$       $$$$       $$$$
          $$$$$$$$$$  $$$$$$$$  $$$$$ $$$$ $$$  $$$$$$$$   $$$$$$$$
          $$$$$ $$$$       $$$$ $$$$$ $$$$ $$$       $$$$ $$$$$
          $$$$$ $$$$ $$$$$ $$$$ $$$$$ $$$$ $$$ $$$$$ $$$$ $$$$$ $$$$
          $$$$$ $$$$  $$$$$$$$  $$$$$ $$$$ $$$  $$$$$$$$  $$$$$$$$$$

                    How to program for windows 95 in asm32
                        Lesson 2 : Your First Window !
                      by _HaK_ and corrected by I_Magnus

    -----------------------------------------------------------------------
  ---------------------------------------------------------------------------


  1.Introduction :
  ----------------

      OK this time  I'll try to teach you how to do your first window.
      It won't be complicated (just a bit). The only thing we have to
      know is that a window is composed of multiple elements :

       * A title bar with, most of the time, :

           - Three buttons : quit, minimize and maximize.
           - A title.
           - An  icon  before the  title which  become a  System Menu by
             clicking on it.

       * A Menu Bar

       * Borders

       * And a client area (the main component of the windows sometimes
         called working area)



  2.Stop talking and let's begin :
  --------------------------------

    2.1.The window creation :
    -------------------------

      Each window belongs to a class type.  And so, before creating a window,
      we have to register a new class  defining some options of the window.
      To register a new class type we'll use :  RegisterClassA
      And to create the window we'll use : CreateWindowExA

      2.1.1.First The RegisterClassA :
      --------------------------------

        This  function  is used  to  register a new  class  for a window.
        A class is a sort of  advanced  definition options for a windows.
        It defines the  procedure to call each time the user  touches the
        window, the menu of the window,  the icon and the cursor  of the
        application,...  Multiple  windows can use  the same  class, and
        then the same window procedure.

        With this API we have to push only a  parameter : a long pointer
        to the "WndClass" structure.

        To define a structure put it before the data segment in the first
        part  of the .ASM  (in the  definition part). Once  defined, the
        structure has to be declared in the data segment  assigned to a
        name. Each  time a name is  assigned to a  structure, it gets the
        same defined composition, but its own data area.

        The WndClass structure is defined as follows :

          WNDCLASS struc
              clsStyle          dd   ?   ; class style
              clsLpfnWndProc    dd   ?   ; pointer to the window procedure
              clsCbClsExtra     dd   ?   ; sort of size of buffer (0)
              clsCbWndExtra     dd   ?   ; sort of size of buffer too (0)
              clsHInstance      dd   ?   ; application instance handle
              clsHIcon          dd   ?   ; icon handle
              clsHCursor        dd   ?   ; cursor handle
              clsHbrBackground  dd   ?   ; background brush handle
              clsLpszMenuName   dd   ?   ; menu handle
              clsLpszClassName  dd   ?   ; far ptr to class name string,
                                         ; "null terminated"
          WNDCLASS ends

        To declare this structure you have to add to your data :

          NameYouWant  WNDCLASS 

        After, if  you want to access  a special  offset of the structure,
        do the following (it's an example) :

          mov  [NameYouWant.clsHIcon],eax

        If a first structure contains another structure, for example
        a RECT or a POINT structure, you can access them by typing :

          mov  [FirstStructureName.SecondStructureName.DataName],eax

        But be  careful : don't begin  a data name in the structure with
        numbers : it will result in a fatal error while compiling !

        OK, now to the WNDCLASS structure :

          * The first data is the class style. The value is a combination
            of the following value :

              CS_VREDRAW          EQU       0001h ;
              CS_HREDRAW          EQU       0002h ;
              CS_DBLCLKS          EQU       0008h ;
              CS_OWNDC            EQU       0020h ;
              CS_CLASSDC          EQU       0040h ;
              CS_PARENTDC         EQU       0080h ;
              CS_NOCLOSE          EQU       0200h ; Disable the close
                                                  ; command of the window.
              CS_SAVEBITS         EQU       0800h ;
              CS_BYTEALIGNCLIENT  EQU       1000h ;
              CS_BYTEALIGNWINDOW  EQU       2000h ;
              CS_GLOBALCLASS      EQU       4000h ;
              CS_IME              EQU   00010000h ; ? no info about this.

          [It seems to have something to do with Java.  I found a webpage
           dealing with it, and a MS Knowlege Base article describing it.
           Something to do with Client Side Image Map Editor? -- Ed.     ]

          * The second data  is a long  pointer  to a window  procedure :
            each time  something  appends  to the  window, this procedure
            is called. (for more info see below)

          * The next two data are integers, but i  have no info about them
            and if you put in zeros, it works perfectly !

          * The  clsHInstance need  to have the application handle getted
            by the API : GetModuleHandleA (see lesson 1)

        Now we access to an interesting part of the WNDCLASS structure :

          * The clsHIcon parameter : Here we have to put the handle of an
            Icon.  This Icon will  become  the Default  Icon  of the next
            created window (the  icon is shown in the taskbar and in the
            title bar (can be chosen if you want...or not)).

          * The clsHCursor  parameter : Here we have to put the handle of
            a Cursor. The selected cursor is shown when the user has  the
            mouse cursor within the window.

            The icon and  the  cursor can be  defined in the .RC file. But
            the icon and the cursor have to be loaded with the LoadCursorA
            and  LoadIconA  APIs, to get the Icon and Cursor handle that
            has to be moved to the  structure. If  no Cursor (or Icon)
            are selected, the default Cursor (or Icon) will be the current
            mouse cursor (or win logo for Icon).
            There is some "predefined"  cursor and icon that can be loaded
            from the application with handle 0 (HWND=0, so push 0 for hwnd
            before calling the LoadCursorA and LoadIconA).

              Predefined Cursor :

                IDC_ARROW        EQU   32512 ; normal cursor
                IDC_IBEAM        EQU   32513
                IDC_WAIT         EQU   32514
                IDC_CROSS        EQU   32515
                IDC_UPARROW      EQU   32516
                IDC_SIZE         EQU   32640 ; OBSOLETE: use IDC_SIZEALL
                IDC_ICON         EQU   32641 ; OBSOLETE: use IDC_ARROW
                IDC_SIZENWSE     EQU   32642
                IDC_SIZENESW     EQU   32643
                IDC_SIZEWE       EQU   32644
                IDC_SIZENS       EQU   32645
                IDC_SIZEALL      EQU   32646
                IDC_NO           EQU   32648
                IDC_HAND         EQU   32649 ; only Win98 ?
                                             ; (for win version >=500)
                IDC_APPSTARTING  EQU   32650
                IDC_HELP         EQU   32651

              Predefined Icons :

                IDI_APPLICATION  EQU   32512
                IDI_HAND         EQU   32513
                IDI_QUESTION     EQU   32514
                IDI_EXCLAMATION  EQU   32515
                IDI_ASTERISK     EQU   32516
                IDI_WINLOGO      EQU   32517

          * The clsHbrBackground to define the brush with which the window
            client area will be filled.  This can be a standard value such as :

              COLOR_SCROLLBAR           EQU 0
              COLOR_BACKGROUND          EQU 1
              COLOR_ACTIVECAPTION       EQU 2
              COLOR_INACTIVECAPTION     EQU 3
              COLOR_MENU                EQU 4
              COLOR_WINDOW              EQU 5
              COLOR_WINDOWFRAME         EQU 6
              COLOR_MENUTEXT            EQU 7
              COLOR_WINDOWTEXT          EQU 8
              COLOR_CAPTIONTEXT         EQU 9
              COLOR_ACTIVEBORDER        EQU 10
              COLOR_INACTIVEBORDER      EQU 11
              COLOR_APPWORKSPACE        EQU 12
              COLOR_HIGHLIGHT           EQU 13
              COLOR_HIGHLIGHTTEXT       EQU 14
              COLOR_BTNFACE             EQU 15
              COLOR_BTNSHADOW           EQU 16
              COLOR_GRAYTEXT            EQU 17
              COLOR_BTNTEXT             EQU 18
              COLOR_INACTIVECAPTIONTEXT EQU 19
              COLOR_BTNHIGHLIGHT        EQU 20
              COLOR_3DDKSHADOW          EQU 21
              COLOR_3DLIGHT             EQU 22
              COLOR_INFOTEXT            EQU 23
              COLOR_INFOBK              EQU 24
              COLOR_HOTLIGHT                EQU  26 ; Only Win98 ?
                                                    ; (for win version >=500)
              COLOR_GRADIENTACTIVECAPTION   EQU  27 ; Only Win98 ?
                                                    ; (for win version >=500)
              COLOR_GRADIENTINACTIVECAPTION EQU  28 ; Only Win98 ?
                                                    ; (for win version >=500)

            If you  want your own  brush, move to this data the handle of
            the brush you get  after the Brush  Creation  APIs (Just like
            CreateSolidBrush,...)

          * The  clsLpszMenuName  has to get the  Handle of a menu.  This
            Handle  can be obtained  by the  LoadMenu  API if the menu is
            stored in the  resource file. To load it You have to push the
            application  handle and the Menu resource ID (or a pointer to
            a null terminated  string defining the name of the menu given
            in the .RC file). The pushed application handle defines, just
            like the LoadIconA  and LoadCursorA, the module from where it
            must be loaded.

          * The  clsLpszClassName  gets the  offset  of  a  string,  null
            terminated, which defines the new class name to which will be
            assigned all the given parameters.

        Once you have  filled all  data, push the  offset of  the filled
        structure and call the RegisterClassA API to register it.

        Now the class is registered, we use the CreateWindowExA to create
        the window using the new registered class.

      2.1.2.CreateWindowExA :
      ---------------------

        This  is the  real function  to create  a window  or  one of its
        components (see Lesson 3). All its  parameters have to be pushed
        on the Stack and always in the inverted order.

        OK Now the parameters :

          HWND CreateWindowExA(
            DWORD dwExStyle,
            LPCSTR lpClassName,
            LPCSTR lpWindowName,
            DWORD dwStyle,
            int X,
            int Y,
            int nWidth,
            int nHeight,
            HWND hWndParent ,
            HMENU hMenu,
            HINSTANCE hInstance,
            LPVOID lpParam);

          * The first parameters define the  extended style of the window
            This  is a  complement to the  dwStyle parameter and can be a
            combination of :

              WS_EX_DLGMODALFRAME  EQU   00000001h
              WS_EX_NOPARENTNOTIFY EQU   00000004h
              WS_EX_TOPMOST        EQU   00000008h ; Window is always on top
              WS_EX_ACCEPTFILES    EQU   00000010h
              WS_EX_TRANSPARENT    EQU   00000020h ; Window is transparent
                                                   ;  (can see through it)
              WS_EX_MDICHILD       EQU   00000040h
              WS_EX_TOOLWINDOW     EQU   00000080h ; create a small window :
                                                   ; smaller caption,...
              WS_EX_WINDOWEDGE     EQU   00000100h
              WS_EX_CLIENTEDGE     EQU   00000200h
              WS_EX_CONTEXTHELP    EQU   00000400h
              WS_EX_RIGHT          EQU   00001000h
              WS_EX_LEFT           EQU   00000000h
              WS_EX_RTLREADING     EQU   00002000h ; write text mode :
                                                   ; right to left (Arabic)
              WS_EX_LTRREADING     EQU   00000000h ; left to right
              WS_EX_LEFTSCROLLBAR  EQU   00004000h ; scroll bar if one
                                                   ; on left
              WS_EX_RIGHTSCROLLBAR EQU   00000000h ; on right
              WS_EX_CONTROLPARENT  EQU   00010000h
              WS_EX_STATICEDGE     EQU   00020000h
              WS_EX_APPWINDOW      EQU   00040000h

          * The lpClassName gets the offset of the null terminated string
            defining  the  Class  to  which the window belongs. There are
            special Classes which define Window Control such as Edit Box,
            Buttons, etc...

          * The  lpWindowName gets the offset of a null terminated string
            defining the title of the window.

          * The  dwStyle  defines  the windows  main style. It can get a
            combination of these Values:

              WS_OVERLAPPED    EQU   00000000h ; flat window (win3.1 style)
              WS_POPUP         EQU   80000000h ; new popup window (no parent)
              WS_CHILD         EQU   40000000h ; window has a parent and
                                               ; belong to him
              WS_MINIMIZE      EQU   20000000h ; window is showed minimized
              WS_VISIBLE       EQU   10000000h ; window is showed normal
              WS_DISABLED      EQU   08000000h ; window is disabled
                                               ; (for child)
              WS_CLIPSIBLINGS  EQU   04000000h ; window clip his siblings
              WS_CLIPCHILDREN  EQU   02000000h ; window clip his children
              WS_MAXIMIZE      EQU   01000000h ; window is showed maximized
              WS_BORDER        EQU   00800000h ; window has black drawn
                                               ; border (ugly , win3.1 style)
              WS_DLGFRAME      EQU   00400000h ; window is similar to a
                                               ; dialog : 3d style
              WS_VSCROLL       EQU   00200000h ; window have vertical
                                               ; scroll bar
              WS_HSCROLL       EQU   00100000h ; window have horizontal
                                               ; scroll bar
              WS_SYSMENU       EQU   00080000h ; title bar have his menu
                                               ; (the icon on the left)
              WS_THICKFRAME    EQU   00040000h ; window can be resized
                                               ; (cursor on border)
              WS_GROUP         EQU   00020000h ; window create a new group
                                               ; (for child)
              WS_TABSTOP       EQU   00010000h ; window can be selected with
                                               ; the tab key (for child)
              WS_MINIMIZEBOX   EQU   00020000h ; window have the mini button
                                               ; in title bar
              WS_MAXIMIZEBOX   EQU   00010000h ; window have the maxi button
                                               ; in title bar
              If you choose only one of the WS_MINIMIZEDBOX or WS_MAXIMIZED,
              the other button will be displayed also (but grayed).

          * The 4 next parameters defines :

            - X : the abscissa  of the left side of window when displayed
                  (from left border)

            - Y : the  ordinate  of the top side of window when displayed
                  (from top border)

            - nWidth : the width of the window

            - nHeight : the height of the window

            You can assign any value to these  parameters. But there is a
            default value for Windows :

              CW_USEDEFAULT    EQU   80000000h

            And then with this value give the default abscissa, ordinate,
            width and/or Height to the window.

          * The hWndParent can get two values :

            - 0 if it's a new window

            - or the handle of the parent  window which will  include the
              child window (for window control).

          * The hMenu can get the Handle of a menu loaded by the LoadMenu
            API. If you want none : simply push 0.

            This  can be  used better  than the  HMenu in  the  WndClass,
            because the Menu will be specific to the window and if a Menu
            is defined in the WndClass all  window having the same  Class
            would have the same Menu.

            If you are creating a child window this parameters will define
            the value in wparam of the WM_COMMAND  (see  below) message if
            the user  selects the  child window. This is also a sort of
            identifier for the child window.

          * The  hInstance  parameter  just  gets the  value given by the
            GetModuleHandleA API, the Application handle.

          * You can assign a value to  lpParam  that will be given to the
            window  procedure  at  the  WM_CREATE  as  the  lparam ( this
            correspond to  the address of a special structure). It can be
            used for MDI  windows but i don't know how and what it is  so
            I put zero in for the moment (I will try it in the future)

      Once  you  have  pushed  all  the  values you wanted in the correct
      order, simply call the CreateWindowExA API.

      Before displaying  the new window,  Windows will send three message
      to the Window procedure : WM_CREATE, WM_NCCALCSIZE, WM_NCCREATE.

      Once The creation finished,  Windows gives you the handle  and puts
      in eax.  This is the  created  window  handle that  can be used  as
      parent handle if  creating child  windows.  This window  handle can
      be used for interaction on the created window or child window.

    2.2.The Window procedure :
    --------------------------

      This procedure is called every time something happens to the window.
      When  entering the procedure, Windows has put some parameter on the
      stack. To Access them simply define your procedure as follows :

        YourProcName PROC uses ebx edi esi, HWnd:DWORD, WMsg:DWORD,
                                            WParam:DWORD, LParam:DWORD

      We have to save on the stack ebx,edi and esi because  windows  does
      not save them.

      Windows give us four parameters which are all dword :

        - hwnd : the handle of the window calling the procedure.

        - wmsg : the window message

        - wparam : a dependent the case parameter

        - lparam : a dependent  the case  parameter too (often pointing a
                   structure)

      TASM  provide you an easy access  by adjusting  the correct address
      with the BP register  (load at beginning the  SP register to BP and
      then do the famous [BP],[BP+4],... addressing for  us). If  we want
      to access them we simply type :

        mov  eax,[hwnd]    or    push  [wparam]  , ...

      This has a consequence : if modifying the BP register, then do it
      with some precautions (or u will get fatal error while running) !

      When  we want to give  back the hand to  Windows, simply put a ret.

      Once we finished the whole procedure it has to be terminated with :

        YourProcName ENDP

      Now I'll try to explain to you a bit about the parameters :

        * First the HWnd. It's a window handle, and the handle belongs to
          the  calling window.  For example  if two  window are using the
          same class, they use the same Window  procedure. So this handle
          describe the calling window. It can be used as a replacement of
          the application  handle, because  you often  want to modify the
          calling  window, and  not all of the  application. This  handle
          corresponds to the  handle given back after the CreateWindowExA
          (has to be verified, it's a supposition).

        * Then the  WParam and  LParam.  As said before  these parameters 
          depend on the current window message  in the WMsg. So there  is  
          nothing  to  say  but  that the WParam is often  a simple value 
          and that  the  LParam most  of the  time points  to  a  special
          structure.

        * And to finish the WMsg. This parameter contains the main value.
          This says to  the procedure  what happens. For easier access to
          the value, windows programmers give them names.

          All the message name begin with WM_...

          OK now the full list (some of them are explained below the list) :

            WM_NULL                         EQU  0000h
            WM_CREATE                       EQU  0001h
            WM_DESTROY                      EQU  0002h
            WM_MOVE                         EQU  0003h
            WM_SIZE                         EQU  0005h
            WM_ACTIVATE                     EQU  0006h
            WM_SETFOCUS                     EQU  0007h
            WM_KILLFOCUS                    EQU  0008h
            WM_ENABLE                       EQU  000Ah
            WM_SETREDRAW                    EQU  000Bh
            WM_SETTEXT                      EQU  000Ch
            WM_GETTEXT                      EQU  000Dh
            WM_GETTEXTLENGTH                EQU  000Eh
            WM_PAINT                        EQU  000Fh
            WM_CLOSE                        EQU  0010h
            WM_QUERYENDSESSION              EQU  0011h
            WM_QUIT                         EQU  0012h
            WM_QUERYOPEN                    EQU  0013h
            WM_ERASEBKGND                   EQU  0014h
            WM_SYSCOLORCHANGE               EQU  0015h
            WM_ENDSESSION                   EQU  0016h
            WM_SHOWWINDOW                   EQU  0018h
            WM_WININICHANGE                 EQU  001Ah
            WM_SETTINGCHANGE                EQU  001Ah
            WM_DEVMODECHANGE                EQU  001Bh
            WM_ACTIVATEAPP                  EQU  001Ch
            WM_FONTCHANGE                   EQU  001Dh
            WM_TIMECHANGE                   EQU  001Eh
            WM_CANCELMODE                   EQU  001Fh
            WM_SETCURSOR                    EQU  0020h
            WM_MOUSEACTIVATE                EQU  0021h
            WM_CHILDACTIVATE                EQU  0022h
            WM_QUEUESYNC                    EQU  0023h
            WM_GETMINMAXINFO                EQU  0024h
            WM_PAINTICON                    EQU  0026h
            WM_ICONERASEBKGND               EQU  0027h
            WM_NEXTDLGCTL                   EQU  0028h
            WM_SPOOLERSTATUS                EQU  002Ah
            WM_DRAWITEM                     EQU  002Bh
            WM_MEASUREITEM                  EQU  002Ch
            WM_DELETEITEM                   EQU  002Dh
            WM_VKEYTOITEM                   EQU  002Eh
            WM_CHARTOITEM                   EQU  002Fh
            WM_SETFONT                      EQU  0030h
            WM_GETFONT                      EQU  0031h
            WM_SETHOTKEY                    EQU  0032h
            WM_GETHOTKEY                    EQU  0033h
            WM_QUERYDRAGICON                EQU  0037h
            WM_COMPAREITEM                  EQU  0039h
            WM_GETOBJECT                    EQU  003Dh ; Only Win98 ?
                                                       ; Win version >= 500
            WM_COMPACTING                   EQU  0041h
            WM_COMMNOTIFY                   EQU  0044h ; no longer supported
            WM_WINDOWPOSCHANGING            EQU  0046h
            WM_WINDOWPOSCHANGED             EQU  0047h
            WM_POWER                        EQU  0048h
            WM_COPYDATA                     EQU  004Ah
            WM_CANCELJOURNAL                EQU  004Bh
            WM_NOTIFY                       EQU  004Eh
            WM_INPUTLANGCHANGEREQUEST       EQU  0050h
            WM_INPUTLANGCHANGE              EQU  0051h
            WM_TCARD                        EQU  0052h
            WM_HELP                         EQU  0053h
            WM_USERCHANGED                  EQU  0054h
            WM_NOTIFYFORMAT                 EQU  0055h
            WM_CONTEXTMENU                  EQU  007Bh
            WM_STYLECHANGING                EQU  007Ch
            WM_STYLECHANGED                 EQU  007Dh
            WM_DISPLAYCHANGE                EQU  007Eh
            WM_GETICON                      EQU  007Fh
            WM_SETICON                      EQU  0080h
            WM_NCCREATE                     EQU  0081h
            WM_NCDESTROY                    EQU  0082h
            WM_NCCALCSIZE                   EQU  0083h
            WM_NCHITTEST                    EQU  0084h
            WM_NCPAINT                      EQU  0085h
            WM_NCACTIVATE                   EQU  0086h
            WM_GETDLGCODE                   EQU  0087h
            WM_SYNCPAINT                    EQU  0088h
            WM_NCMOUSEMOVE                  EQU  00A0h
            WM_NCLBUTTONDOWN                EQU  00A1h
            WM_NCLBUTTONUP                  EQU  00A2h
            WM_NCLBUTTONDBLCLK              EQU  00A3h
            WM_NCRBUTTONDOWN                EQU  00A4h
            WM_NCRBUTTONUP                  EQU  00A5h
            WM_NCRBUTTONDBLCLK              EQU  00A6h
            WM_NCMBUTTONDOWN                EQU  00A7h
            WM_NCMBUTTONUP                  EQU  00A8h
            WM_NCMBUTTONDBLCLK              EQU  00A9h
            WM_KEYFIRST                     EQU  0100h
            WM_KEYDOWN                      EQU  0100h
            WM_KEYUP                        EQU  0101h
            WM_CHAR                         EQU  0102h
            WM_DEADCHAR                     EQU  0103h
            WM_SYSKEYDOWN                   EQU  0104h
            WM_SYSKEYUP                     EQU  0105h
            WM_SYSCHAR                      EQU  0106h
            WM_SYSDEADCHAR                  EQU  0107h
            WM_KEYLAST                      EQU  0108h
            WM_IME_STARTCOMPOSITION         EQU  010Dh
            WM_IME_ENDCOMPOSITION           EQU  010Eh
            WM_IME_COMPOSITION              EQU  010Fh
            WM_IME_KEYLAST                  EQU  010Fh
            WM_INITDIALOG                   EQU  0110h
            WM_COMMAND                      EQU  0111h
            WM_SYSCOMMAND                   EQU  0112h
            WM_TIMER                        EQU  0113h
            WM_HSCROLL                      EQU  0114h
            WM_VSCROLL                      EQU  0115h
            WM_INITMENU                     EQU  0116h
            WM_INITMENUPOPUP                EQU  0117h
            WM_MENUSELECT                   EQU  011Fh
            WM_MENUCHAR                     EQU  0120h
            WM_ENTERIDLE                    EQU  0121h
            WM_MENURBUTTONUP                EQU  0122h ; Only Win98 ?
                                                       ; Win version >= 500
            WM_MENUDRAG                     EQU  0123h ; Only Win98 ?
                                                       ; Win version >= 500
            WM_MENUGETOBJECT                EQU  0124h ; Only Win98 ?
                                                       ; Win version >= 500
            WM_UNINITMENUPOPUP              EQU  0125h ; Only Win98 ?
                                                       ; Win version >= 500
            WM_MENUCOMMAND                  EQU  0126h ; Only Win98 ?
                                                       ; Win version >= 500
            WM_CTLCOLORMSGBOX               EQU  0132h
            WM_CTLCOLOREDIT                 EQU  0133h
            WM_CTLCOLORLISTBOX              EQU  0134h
            WM_CTLCOLORBTN                  EQU  0135h
            WM_CTLCOLORDLG                  EQU  0136h
            WM_CTLCOLORSCROLLBAR            EQU  0137h
            WM_CTLCOLORSTATIC               EQU  0138h
            WM_MOUSEFIRST                   EQU  0200h
            WM_MOUSEMOVE                    EQU  0200h
            WM_LBUTTONDOWN                  EQU  0201h
            WM_LBUTTONUP                    EQU  0202h
            WM_LBUTTONDBLCLK                EQU  0203h
            WM_RBUTTONDOWN                  EQU  0204h
            WM_RBUTTONUP                    EQU  0205h
            WM_RBUTTONDBLCLK                EQU  0206h
            WM_MBUTTONDOWN                  EQU  0207h
            WM_MBUTTONUP                    EQU  0208h
            WM_MBUTTONDBLCLK                EQU  0209h
            WM_PARENTNOTIFY                 EQU  0210h
            WM_ENTERMENULOOP                EQU  0211h
            WM_EXITMENULOOP                 EQU  0212h
            WM_NEXTMENU                     EQU  0213h
            WM_SIZING                       EQU  0214h
            WM_CAPTURECHANGED               EQU  0215h
            WM_MOVING                       EQU  0216h
            WM_POWERBROADCAST               EQU  0218h
            WM_DEVICECHANGE                 EQU  0219h
            WM_MDICREATE                    EQU  0220h
            WM_MDIDESTROY                   EQU  0221h
            WM_MDIACTIVATE                  EQU  0222h
            WM_MDIRESTORE                   EQU  0223h
            WM_MDINEXT                      EQU  0224h
            WM_MDIMAXIMIZE                  EQU  0225h
            WM_MDITILE                      EQU  0226h
            WM_MDICASCADE                   EQU  0227h
            WM_MDIICONARRANGE               EQU  0228h
            WM_MDIGETACTIVE                 EQU  0229h
            WM_MDISETMENU                   EQU  0230h
            WM_ENTERSIZEMOVE                EQU  0231h
            WM_EXITSIZEMOVE                 EQU  0232h
            WM_DROPFILES                    EQU  0233h
            WM_MDIREFRESHMENU               EQU  0234h
            WM_IME_SETCONTEXT               EQU  0281h
            WM_IME_NOTIFY                   EQU  0282h
            WM_IME_CONTROL                  EQU  0283h
            WM_IME_COMPOSITIONFULL          EQU  0284h
            WM_IME_SELECT                   EQU  0285h
            WM_IME_CHAR                     EQU  0286h
            WM_IME_REQUEST                  EQU  0288h ; Only Win98 ?
                                                       ; Win version >= 500
            WM_IME_KEYDOWN                  EQU  0290h
            WM_IME_KEYUP                    EQU  0291h
            WM_CUT                          EQU  0300h
            WM_COPY                         EQU  0301h
            WM_PASTE                        EQU  0302h
            WM_CLEAR                        EQU  0303h
            WM_UNDO                         EQU  0304h
            WM_RENDERFORMAT                 EQU  0305h
            WM_RENDERALLFORMATS             EQU  0306h
            WM_DESTROYCLIPBOARD             EQU  0307h
            WM_DRAWCLIPBOARD                EQU  0308h
            WM_PAINTCLIPBOARD               EQU  0309h
            WM_VSCROLLCLIPBOARD             EQU  030Ah
            WM_SIZECLIPBOARD                EQU  030Bh
            WM_ASKCBFORMATNAME              EQU  030Ch
            WM_CHANGECBCHAIN                EQU  030Dh
            WM_HSCROLLCLIPBOARD             EQU  030Eh
            WM_QUERYNEWPALETTE              EQU  030Fh
            WM_PALETTEISCHANGING            EQU  0310h
            WM_PALETTECHANGED               EQU  0311h
            WM_HOTKEY                       EQU  0312h
            WM_PRINT                        EQU  0317h
            WM_PRINTCLIENT                  EQU  0318h
            WM_HANDHELDFIRST                EQU  0358h
            WM_HANDHELDLAST                 EQU  035Fh
            WM_AFXFIRST                     EQU  0360h
            WM_AFXLAST                      EQU  037Fh
            WM_PENWINFIRST                  EQU  0380h
            WM_PENWINLAST                   EQU  038Fh
            WM_APP                          EQU  8000h

          All window message after  0400h  are reserved so i have no docs
          on them. Ok, here  are all the message values.  But  you  don't
          need to  fully support all  these  windows  messages.  You will
          only  have  to  support  those  you  want to use. If  you don't 
          support  all  window message  (did  you ? :))  you can call the
          default message  processing of window : DefWindowProcA and this
          with all your parameters and it will support the  ones that are
          unsupported by your code.

          I gave all the name, but  I won't have time to explain them all
          and so refer to  the  famous Win32  programmer's reference Help
          file !

          Some explanations on some of them :

            * WM_CREATE : this message is the first message this procedure
               will get. It is sent by windows just  before  the window is 
               created. It can be  used to  initialize  some value, define
               multiple things... LParam  points to a structure containing
               the information on the created window.

            * WM_DESTROY : this message is  sent when  the user  close the
               window : keyboard  shortcut ( ALT-F4 ), the close button in
               the titlebar or the close option in the system menu.

            * WM_MOVE : The user has moved  the  window and  finishes  the
               move. LParam contains the new window position : in the  low
               word the abscissa, and in the high word the ordinate.

            * WM_MOVING : The user is moving the window  (window  position
               is  changing).  LParam  points  to  a rectangle (Left, Top,
               Right, Bottom) structure containing the window coordinates.

            * WM_SIZE : The user has finished resizing the window.

            * WM_SIZING : The user is resizing the window.

            * WM_PAINT : called when a window has to be repainted. If  you
               want to draw something  this  must contain  the  BeginPaint
               and EndPaint  APIs  for initializing all the data contained
               in the PAINT structure. (Wait for a next lesson...)

            * WM_COMMAND : The user  chose  an element : a menu, a button,
               a window  control,... The  chosen  element  identification
               code is in WParam. This not include the title bar elements !

            * WM_SYSCOMMAND : The  user  chose  an   element of the system
               menu. The element identification code is in WParam

    2.3.Communication between the application and the window procedure :
    --------------------------------------------------------------------

      Once  you  have  finished creating a  window,  there  is  a  way  to
      communicate  between the Window  procedure and the main  application.
      For example : The user clicked the close button  in  the  title  bar.
      The window  procedure will get  the  WM_DESTROY  message.  But on the
      other  hand  nothing  prevents  the  app  that  the  user closed  the
      application.  The " official"  way to  do  this is by  calling in the
      window procedure  the PostQuitMessageA.  On the other  side, the main
      application continues calling with no end the  GetMessageA API  and if
      the quit message was posted the value in eax is null and then you can
      jump to your  ending code.  But  if the value  in eax was not legal to
      zero,  you  have  to  call  the   TranslateMessage   and   then   the
      DispatchMessage.  An  other  way  to  send  a  message  is  using the
      PostThreadMessageA.

      This  section  is  really  poor  because  i  didn't test too much the
      communication between the window  procedure and the main application.
      But if you have some info on it, contact me (see at the end how to) !



  3.Others indications :
  ----------------------

    If  creating  a  window,  don't  forget one  of  the  following styles:
    WS_NORMAL, WS_MINIMIZED or  WS_MAXIMIZED. Because  your window won't be
    displayed. An other  way to select  the way you  display your window is
    using the API ShowWindow  with one of  the following  parameters in the
    show state :

      SW_HIDE             EQU 0
      HIDE_WINDOW         EQU 0
      SW_SHOWNORMAL       EQU 1
      SW_NORMAL           EQU 1
      SHOW_OPENWINDOW     EQU 1
      SW_SHOWMINIMIZED    EQU 2
      SHOW_ICONWINDOW     EQU 2
      SW_SHOWMAXIMIZED    EQU 3
      SW_MAXIMIZE         EQU 3
      SHOW_FULLSCREEN     EQU 3
      SW_SHOWNOACTIVATE   EQU 4
      SHOW_OPENNOACTIVATE EQU 4
      SW_SHOW             EQU 5
      SW_MINIMIZE         EQU 6
      SW_SHOWMINNOACTIVE  EQU 7
      SW_SHOWNA           EQU 8
      SW_RESTORE          EQU 9
      SW_SHOWDEFAULT      EQU 10
      SW_FORCEMINIMIZE    EQU 11
      SW_MAX              EQU 11



  4.The .ASM file :
  -----------------

    ;--- Start of TUT_02.ASM -->8

              .386
              locals
              jumps
              .model flat,STDCALL

      ; All called APIs defined as being an external procedure

              extrn CreateWindowExA:Proc
              extrn DefWindowProcA:Proc
              extrn DispatchMessageA:Proc
              extrn ExitProcess:Proc
              extrn GetMessageA:Proc
              extrn GetModuleHandleA:Proc
              extrn LoadCursorA:Proc
              extrn LoadIconA:Proc
              extrn MessageBoxA:Proc
              extrn PostQuitMessage:Proc
              extrn RegisterClassA:Proc
              extrn TranslateMessage:Proc

      ; All Special value used

      ; The Class Style

      CS_VREDRAW      EQU 0001h
      CS_HREDRAW      EQU 0002h
      CS_GLOBALCLASS  EQU 4000h

      ; The Background Brush Color

      COLOR_WINDOW    EQU 5

      ; The default size for the window

      CW_USEDEFAULT   EQU 8000h

      ; The Used Window Style

      WS_OVERLAPPED   EQU 000000000h
      WS_MAXIMIZEBOX  EQU 000010000h
      WS_MINIMIZEBOX  EQU 000020000h
      WS_THICKFRAME   EQU 000040000h
      WS_SYSMENU      EQU 000080000h
      WS_DLGFRAME     EQU 000400000h
      WS_BORDER       EQU 000800000h
      WS_CAPTION      EQU 000C00000h     ; WS_BORDER | WS_DLGFRAME
      WS_VISIBLE      EQU 010000000h
WS_OVERLAPPEDWINDOW EQU WS_OVERLAPPED OR WS_CAPTION OR WS_SYSMENU OR WS_THICKFRAME OR WS_MINIMIZEBOX OR WS_MAXIMIZEBOX OR WS_VISIBLE

      ; The support Window Message in the window procedure

      WM_LBUTTONDOWN  EQU 0201h ; Left Mouse Boutton down in the Client
                                ; Area of window
      WM_DESTROY      EQU 0002h ; the minimum needed i think (most important)

      ; We define all the used structures :

      ; the class structure

      WNDCLASS struc
        clsStyle          dd ?   ; class style
        clsLpfnWndProc    dd ?
        clsCbClsExtra     dd ?
        clsCbWndExtra     dd ?
        clsHInstance      dd ?   ; instance handle
        clsHIcon          dd ?   ; class icon handle
        clsHCursor        dd ?   ; class cursor handle
        clsHbrBackground  dd ?   ; class background brush
        clsLpszMenuName   dd ?   ; menu name
        clsLpszClassName  dd ?   ; far ptr to class name
      WNDCLASS ends

      ; the point structure used in the message structure

      POINT   struc
        ptX             dd ?
        ptY             dd ?
      POINT   ends

      ; the message structure (badly defined in the windows.inc of tasm)

      MSGSTRUCT struc
        msHWND          dd ?
        msMESSAGE       dd ?
        msWPARAM        dd ?
        msLPARAM        dd ?
        msTIME          dd ?
        msPT            POINT 
      MSGSTRUCT ends

      ; now the data

              .data

      ; declare a class structure

      wc      WNDCLASS 

      ; declare a message structure

      msg     MSGSTRUCT 

      ; The main application handle.

      AppHWnd         dd 0

      ; The created window handle.

      NewHWnd         dd 0

      ; the created class name

      WndClassName    db "ASMClass",0

      ; the created window title

      WindowCaption   db "Lesson 2",0

      ; the msg box title (got when clicking in the client area)

      MsgBoxCaption   db "Lesson 2",0

      ; the msg box content.

      MsgBoxContent   db "You clicked in the Client area of the window",0

      ; now the code
              .code

      Start:

      ; Get the application handle

              push    0h
              call    GetModuleHandleA ; get the application handle
              mov     [AppHWnd],eax    ; and store it

      ; we fill the class structure

              mov     [wc.clsStyle], CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS
                                                ; class style
              mov     [wc.clsLpfnWndProc], offset WndProc
                                                ; the window procedure
              mov     [wc.clsCbClsExtra], 0     ; ?
              mov     [wc.clsCbWndExtra], 0     ; ?
              mov     eax, [AppHWnd]
              mov     [wc.clsHInstance], eax    ; the application handle
              push    32516                     ; icon resource identifier
              push    0                         ; where from to load (system)
              call    LoadIconA                 ; load icon
              mov     [wc.clsHIcon], eax        ; store the geted handle
              push    32512                     ; cursor resource identifier
              push    0                         ; where from to load (system)
              call    LoadCursorA               ; Load cursor
              mov     [wc.clsHCursor], eax      ; store the geted handle
              mov     [wc.clsHbrBackground], COLOR_WINDOW + 1
                                                ; background color
              mov     dword ptr [wc.clsLpszMenuName], 0  ; no menu
              mov     dword ptr [wc.clsLpszClassName], offset WndClassName
                                                ; new created class name

      ; register the filled class

              push    offset wc                 ; offset of filled class
              call    RegisterClassA            ; register it !

      ; create the window

              push    0                      ; lpParam
              push    [AppHWnd]              ; hInstance
              push    0                      ; menu
              push    0                      ; parent hwnd
              push    CW_USEDEFAULT          ; height
              push    CW_USEDEFAULT          ; width
              push    CW_USEDEFAULT          ; y
              push    CW_USEDEFAULT          ; x
              push    WS_OVERLAPPEDWINDOW    ; Style
              push    offset WindowCaption   ; Title string
              push    offset WndClassName    ; Class name
              push    0                      ; extra style
              call    CreateWindowExA        ; create the window !
              mov     [NewHWnd], eax         ; save the window handle
                                             ; (for future)

      ; now the message loop : does nothing, only wait on the quit message
      ;                        of the window procedure

      msg_loop:

      ; get the message

              push    0
              push    0
              push    0
              push    offset msg
              call    GetMessageA

      ; if zero then quit message posted

              cmp     ax, 0
              je      end_loop

      ; else continue the loop

              push    offset msg
              call    TranslateMessage
              push    offset msg
              call    DispatchMessageA
              jmp     msg_loop

      ; OK now the message was posted

      end_loop:

      ; exit and close the application.

              push    0h
              call    ExitProcess

      ; here the window procedure.

WndProc PROC uses ebx edi esi, hwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD

              cmp     [wmsg], WM_DESTROY      ; user want to quit ?
              je      wmdestroy
              cmp     [wmsg], WM_LBUTTONDOWN  ; user clicked within the
                                              ; client area ?
              je      wmlbuttondown
              push    [lparam]
              push    [wparam]
              push    [wmsg]
              push    [hwnd]
              call    DefWindowProcA  ; no, then call the default processing
              xor     eax,eax
              ret                     ; and give the hand back

      wmdestroy:                      ; user want to quit !
              push    0               ; wanted exit code (stored in the msg
                                      ; structure)
              call    PostQuitMessage ; post quit message to main application
              xor     eax,eax
              ret                     ; give the hand back

      wmlbuttondown:                  ; user clicked in the client area
              push    20h
              push    offset MsgBoxCaption
              push    offset MsgBoxContent
              push    [NewHWnd]
              call    MessageBoxA      ; display the dialog box (see tut 1)
              xor     eax,eax
              ret                      ; give hand back

      WndProc          endp

      End Start

    ;8<- EOF TUT_01.ASM ---



  5.The .DEF file :
  -----------------

    ;--- Start of TUT_02.DEF -->8

      NAME           TUT_02
      DESCRIPTION    'ASM program'
      EXETYPE        WINDOWS
      CODE           PRELOAD MOVEABLE
      DATA           PRELOAD MOVEABLE MULTIPLE

    ;8<- EOF TUT_02.DEF ---



  6.The makefile file :
  ---------------------


    ;--- Start of MakeFile -->8

      # make -B            Will build .EXE
      # make -B -DDEBUG    Will build the debug version.

      NAME = TUT_02
      OBJS = $(NAME).obj
      DEF  = $(NAME).def

      !if $d(DEBUG)
      TASMDEBUG=/zi
      LINKDEBUG=/v
      !else
      TASMDEBUG=
      LINKDEBUG=
      !endif

      !if $d(MAKEDIR)
      IMPORT=$(MAKEDIR)\..\lib\import32
      !else
      IMPORT=import32
      !endif


      $(NAME).EXE: $(OBJS) $(DEF)
        tlink32 /Tpe /aa /c $(LINKDEBUG) $(OBJS),$(NAME),, $(IMPORT), $(DEF)

      .asm.obj:
         tasm32 $(TASMDEBUG) /ml /m2 $&.asm

    ;8<- EOF MakeFile ---

  7.The Greetz And Some Info :
  -----------------------------

    _Masta_ : Continues your tut they are useful !
    To all Win32asm men : See you soon ! :)
    Message to Nemrod : (Scoobidoo) where are you ?

    To contact myself :

      - try the Sunday afternoon on #Win32asm on EFNET.
         (around 16 hours (GMT+1))

      - or try my E-mail : kinher@infonie.fr

        Next lessons : 3. The Window components !
                       4. Dialog Boxes !

        All my lessons are released at first at :

             http://perso.infonie.fr/kinher

        As you can notice, my english is really bad, so i'm searching
  somebody to correct the tuts ! :) (and you get the tuts before anybody !)