; choose the following, if necessary: include vclib.inc ; Microsoft VC++ .lib link names include win32.inc ; constants, structures, and entry names
extrn InitApp:near,RegisterClassEx:near,CreateWindowEx:near public _start .code _start: call InitApp ; call custom app initialization push edi call RegisterClassEx sub esp,48 ; allocate argument list mov edi,esp ; set block move destination mov ecx,12 ; number of arguments rep movsd call CreateWindowEx ; ... message loop ... extrn ExitProcess:near,EndApp:near .code call EndApp ; call custom app cleanup push eax ; (error) return code call ExitProcessCREATEARGS holds the CreateWindowEx parameters. This allows us to use a block copy, avoiding a bunch of PUSH instructions.
public InitApp,EndApp extrn GetModuleHandle:near .code InitApp: mov edi,offset wc mov esi,offset cwargs push large 0 ; NULL string pointer means call GetModuleHandle ; get HINSTANCE/HMODULE of EXE file mov [edi].wcxInstance,eax mov [esi].cwargInstance,eax ; ...initialization code... ret EndApp: xor eax,eax ; assume no errors ret
wcxStyle = CS_VREDRAW + CS_HREDRAW + CS_DBLCLICKS:
The field holds a combination of style codes. With
the appropriate styles, we make our default window request repaints when
it resized, and we allow it to detect double-clicks.
wcxWndProc = WndProc:
We set this to point to our main window procedure.
It's the same as the WndProc in our minimal
GUI program.
wcxClsExtra = 0, wcxWndExtra = 0:
We don't need to add any auxiliary information,
so we request no extra bytes.
wcxInstance = GetModuleHandle(0):
This field determines which module owns the window
class. We set this to the handle of the EXE module.
wcxIcon = LoadIcon(NULL, IDI_WINLOGO):
Although Win95 displays this by default, we put
this in so we can choose another default.
wcxCursor = LoadCursor(NULL, IDC_ARROW):
Without this, the cursor display doesn't always
show properly when transiting our default window.
wcxBkgndBrush = COLOR_WINDOW + 1:
Without this, the client area will
start with a portion of the screen display. COLOR_WINDOW is a system color,
and it will be affected by the Screen Display properties (right-click on
the desktop, then choose Properties, then Appearance.)
Because NULL means no color and there exists a system
color with the ID value of 0, the value of a system color must be incremented
by one before placing it in this field.
wcxMenuName = NULL:
We still do without a menu.
wcxClassName = wndclsname:
Address of the class name string in NUL-terminated
format.
wcxSmallIcon = LoadIcon(NULL, IDI_WINLOGO):
Use the same set of icons as wcxIcon.
extrn LoadIcon:near,LoadCursor:near DEFAULT_CS_STYLE equ CS_VREDRAW + CS_HREDRAW + CS_DBLCLKS .data wc WNDCLASSEX <size WNDCLASSEX,DEFAULT_CS_STYLE,WndProc,0,0, 0, \ 0,0,COLOR_WINDOW+1, 0,wndclsname, 0> wndclsname db 'winmain',0 .code push large IDI_WINLOGO push large 0 ; hInstance, 0 = stock icon call LoadIcon mov [edi].wcxIcon,eax mov [edi].wcxSmallIcon,eax push large IDC_ARROW push large 0 ; hInstance, 0 = stock cursor call LoadCursor mov [edi].wcxCursor,eax
DEFAULT_STYLE equ WS_VISIBLE + WS_OVERLAPPED + WS_CAPTION + WS_SYSMENU \ + WS_THICKFRAME + WS_MINIMIZEBOX + WS_MAXIMIZEBOX DEFAULT_EXSTYLE equ WS_EX_WINDOWEDGE + WS_EX_CLIENTEDGE DEFAULT_X equ 100 DEFAULT_Y equ 100 DEFAULT_WIDTH equ 200 DEFAULT_HEIGHT equ 200 .data align 4 cwargs CREATEARGS <DEFAULT_EXSTYLE,wndclsname,def_title,DEFAULT_STYLE, \ DEFAULT_X,DEFAULT_Y, DEFAULT_WIDTH,DEFAULT_HEIGHT, 0,0, 0, 0> def_title db 'Application',0