Title: Win32 Programming with Masm Author: Evil Homer Dated: March 20, 2004 Welcome to Chapter Four of my illustrious tutorial. Today we are going to cover the WndProc procedure of our win32 application. WndProc's job is to receive and handle "WM's" (Windows Messages). Let's take a look at a minimal WndProc... We can see that the procedure takes four parameters. Remember that we don't call this procedure, Windows OS calls it for us. The meaning of the wParam and lParam parameters varies with the type of WM being handled, but we can rely on hWin = the handle of the window (or control) which generated the message, and uMsg = the type of WM. WndProc PROC hWin:DWORD, uMsg:DWORD, wParam :DWORD, lParam :DWORD ;(some code in here) invoke DefWindowProc,hWin,uMsg,wParam,lParam ret WndProc endp The Window Procedure (WndProc) is an example of a CALLBACK function. These are functions that we don't ever need to call ourselves, they are event handlers of some description, and are called automatically in response to events that occur. Never mind all that, the code we place inside WndProc can be anything, but normally the code is handling the GUI of the application - all the controls that the user can play with generate WindowsMessages (WM's) which are tossed on the MsgQueue... our MessagePump throws them at our main window, and WndProc receives and handles them. Every time the user clicks a button or types a character in an edit control, we get sent a WM. We get sent WM's even when the user does nothing, for example WM_PAINT being a request to redraw the application window. We'll just add the following code so we can at least quit the application, since we have no controls yet. WndProc PROC hWin:DWORD, uMsg:DWORD, wParam :DWORD, lParam :DWORD mov eax,uMsg .if uMsg==WM_DESTROY invoke PostQuitMessage,NULL .endif invoke DefWindowProc,hWin,uMsg,wParam,lParam ret WndProc endp Ok, with that, and a couple of data variables I forgot to define, let's put it all together :) The following is a complete win32 application which does very little. It creates a window and displays it, and allows us to close it. We'll build on it more, but we could consider this a complete win32 "skeleton source" which could be used as the basis for any number of win32 applications. .486 ;<- opcode set = lowest cpu the program will run on .model flat,stdcall ;<- flat memory model, with standard calling convention option casemap:none ;<- compiler is case-sensitive to sourcecode (capitals matter) include \masm32\include\windows.inc ;<- this contains a bunch of Windows equates and structs include \masm32\include\user32.inc ;<- now we add includes and libs which support functions we want to call include \masm32\include\kernel32.inc ;<- most of your Win32 apps will contain at least these two "api includes" includelib \masm32\lib\user32.lib ;<- for every "api include" there should be a matching "LIB" includelib \masm32\lib\kernel32.lib .DATA szClassName db "MyApplication",0 szDisplayName db "JUST TESTING",0 hWnd dd 0 hInst dd 0 hIcon dd 0 .CODE WndProc PROC hWin:DWORD, uMsg:DWORD, wParam :DWORD, lParam :DWORD mov eax,uMsg .if uMsg==WM_DESTROY invoke PostQuitMessage,NULL .endif invoke DefWindowProc,hWin,uMsg,wParam,lParam ret WndProc endp Main proc local wc:WNDCLASSEX local msg:MSG mov wc.cbSize, sizeof WNDCLASSEX mov wc.style, CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW mov wc.lpfnWndProc, offset WndProc mov wc.cbClsExtra, NULL mov wc.cbWndExtra, NULL push hInst pop wc.hInstance mov wc.hbrBackground, COLOR_BTNFACE+1 mov wc.lpszMenuName, NULL mov wc.lpszClassName, offset szClassName push hIcon pop wc.hIcon invoke LoadCursor,NULL,IDC_ARROW mov wc.hCursor,eax push hIcon pop wc.hIconSm invoke RegisterClassEx, ADDR wc invoke CreateWindowEx,WS_EX_LEFT, ADDR szClassName, ADDR szDisplayName, WS_OVERLAPPED or WS_SYSMENU, 0,0,500,250, NULL,NULL, hInst,NULL mov hWnd,eax invoke ShowWindow,hWnd,SW_SHOWNORMAL invoke UpdateWindow,hWnd StartLoop: invoke GetMessage,ADDR msg,NULL,0,0 cmp eax, 0 je ExitLoop invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg jmp StartLoop ExitLoop: ret Main ENDP start: call Main push 0 call ExitProcess end start Go ahead, build your (first?) win32 executable and run it :) Are we having fun yet? Remember kids, if it's not fun, don't do it !! Next time we'll add some simple controls to the application.