---------------------------------------------------------------------------
-----------------------------------------------------------------------
- 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 >
Transfer interrupted!
M_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 !)