The Assembly Programming Master Book

Consider the first example. When you start this program, a window with an Exit button will appear. As you clearly understand, pressing this button terminates the program.

The most important thing here is how the program is informed that the button has been clicked. Everything is simple: First, it is necessary to check the WM_COMMAND message; then, you must check LPARAM containing the window descriptor (the unique number, called handle). The button is created in the form of the window. In this case, for the button, it is sufficient to define an event. [i]

Pay special attention to the button that you are creating. This combination of properties is the most typical but is not the only possible one. For example, if you want a button to contain an icon, you'll have to specify the BS_ICON (or BS_BITMAP ) property for it.

Listing 3.1: A window with an Exit button

; The button.inc file ; Constants ; The message that arrives when the window is closed WM_DESTROY equ 2 ; The message that arrives when the window is opened WM_CREATE equ 1 ; The message that arrives when the user ; clicks the left mouse button in the window area WM_LBUTTONDOWN equ 201h WM_COMMAND equ 111h ; Window properties CS_VREDRAW equ 1h CS_HREDRAW equ 2h CS_GLOBALCLASS equ 4000h WS_OVERLAPPEDWINDOW equ 000CF0000H STYLE equ CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS BS_DEFPUSHBUTTON equ 1h WS_VISIBLE equ 10000000h WS_CHILD equ 40000000h STYLBTN equ WS_CHILD+BS_DEFPUSHBUTTON+WS_VISIBLE ; Standard icon identifier IDI_APPLICATION equ 32512 ; Cursor identifier IDC_ARROW equ 32512 ; Normal mode of displaying the window SWJ_SHOWNORMAL equ 1 ; Prototypes of external procedures EXTERN MessageBoxA@16:NEAR EXTERN CreateWindowExA@ 48:NEAR EXTERN DefWindowProcA@16:NEAR EXTERN DispatchMessageA@4:NEAR EXTERN ExitProcess@4:NEAR EXTERN GetMessageA@16:NEAR EXTERN GetModuleHandleA@4:NEAR EXTERN LoadCursorA@8:NEAR EXTERN LoadIconA@8:NEAR EXTERN PostQuitMessage@4:NEAR EXTERN RegisterClassA@4:NEAR EXTERN ShowWindow@8:NEAR EXTERN TranslateMessage@4:NEAR EXTERN UpdateWindow@4:NEAR ; Structure ; Message structure MSGSTRUCT STRUC MSHWND DD ? MSMESSAGE DD ? MSWPARAM DD ? MSLPARAM DD ? MSTIME DD ? MSPT DD ? MSGSTRUCT ENDS ;---- Window class structure WNDCLASS STRUC CLSSTYLE DD ? CLWNDPROC DD ? CLSCBCLSEX DD ? CLSCBWNDEX DD ? CLSHINST DD ? CLSHICON DD ? CLSHCURSOR DD ? CLBKGROUND DD ? CLMENNAME DD ? CLNAME DD ? WNDCLASS ENDS ; The button.asm file .586P ; Flat memory model .MODEL FLAT, stdcall include button.inc ; Directives for the linker to link libraries includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib ;------------------------------------------ ; Data segment _DATA SEGMENT DWORD PUBLIC USE32 'DATA' NEWHWND DD 0 MSG MSGSTRUCT <?> WC WNDCLASS <?> HINST DD 0 ; Application descriptor TITLENAME DB 'The example - Exit button', 0 CLASSNAME DB 'CLASS32', 0 CPBUT DB 'Exit', 0 ; Exit CLSBUTN DB 'BUTTON', 0 HWNDBTN DWORD 0 CAP DB 'Message', 0 MES DB 'Program termination', 0 _DATA ENDS ; Code segment _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: ; Get the application descriptor PUSH 0 CALL GetModuleHandleA@4 MOV [HINST], EAX ; REG_CLASS: Fill the window structure ; Style MOV [WC.CLSSTYLE], STYLE ; Message handling procedure MOV [WC.CLWNDPROC], OFFSET WNDPROC MOV [WC.CLSCBCLSEX], 0 MOV [WC.CLSCBWNDEX], 0 MOV EAX, [HINST] MOV [WC.CLSHINST], EAX ;----------Window icon PUSH IDI_APPLICATION PUSH 0 CALL LoadIconA@8 MOV [WC.CLSHICON], EAX ;----------Window cursor PUSH IDC_ARROW PUSH 0 CALL LoadCursorA@8 MOV [WC.CLSHCURSOR], EAX ;---------- MOV [WC.CLBKGROUND], 17 ; Window color MOV DWORD PTR [WC.CLMENNAME], 0 MOV DWORD PTR [WC.CLNAME], OFFSET CLASSNAME PUSH OFFSET WC CALL RegisterClassA@4 ; Create a window of the registered class PUSH 0 PUSH [HINST] PUSH 0 PUSH 0 PUSH 400 ; DY - Window height PUSH 400 ; DX - Window width PUSH 100 ; Y - Coordinate of the top left corner PUSH 100 ; X --- Coordinate of the top right corner PUSH WS_OVERLAPPEDWINDOW PUSH OFFSET TITLENAME ; Window name PUSH OFFSET CLASSNAME ; Class name PUSH 0 CALL CreateWindowExA@48 ; Check for error CMP EAX, 0 JZ _ERR MOV [NEWHWND], EAX ; Window descriptor ;------------------------------------------ PUSH SW_SHOWNORMAL PUSH [NEWHWND] CALL ShowWindow@8 ; Show newly-created window ;------------------------------------------ PUSH [NEWHWND] CALL UpdateWindow@4 ; The command for redrawing the visible ; part of the window, the WM_PAINT message ; Message-processing loop MSG_/LOOP: PUSH 0 PUSH 0 PUSH 0 PUSH OFFSET MSG CALL GetMessageA@16 CMP EAX, 0 JE END_LOOP PUSH OFFSET MSG CALL TranslateMessage@4 PUSH OFFSET MSG CALL DispatchMessageA@4 JMP MSG_LOOP END_LOOP: ; Exit the program (close the process) PUSH [MSG.MSWPARAM] CALL ExitProcess@4 _ERR: JMP END_LOOP ;------------------------------------------------------Window procedure ; Position of parameters in the stack ; [EBP+014H] ; LPARAM ; [EBP+10H] ; WAPARAM ; [EBP+0CH] ; MES ; [EBP+8] ; HWND WNDPROC PROC PUSH EBP MOV EBP, ESP PUSH EBX PUSH ESI PUSH EDI CMP DWORD PTR [EBP+0CH], WM_DESTROY JE WMDESTROY CMP DWORD PTR [EBP+0CH], WM_CREATE JE WMCREATE CMP DWORD PTR [EBP+0CH], WM_COMMAND JE WMCOMMND JMP DEFWNDPROC WMCOMMND: MOV EAX, HWNDBTN CMP DWORD PTR [EBP+14H], EAX ; Hasn't the user clicked the button? JE WMDESTROY MOV EAX, 0 JMP FINISH WMCREATE: ; Create the button window PUSH 0 PUSH [HINST] PUSH 0 PUSH DWORD PTR [EBP+08H] PUSH 20 ; DY PUSH 60 ; DX PUSH 10 ; Y PUSH 10 ; X PUSH STYLBTN PUSH OFFSET CPBUT ; Window name PUSH OFFSET CLSBUTN ; Window class PUSH 0 CALL CreateWindowExA@48 MOV HWNDBTN, EAX ; Save the button descriptor MOV EAX, 0 JMP FINISH DEFWNDPROC: PUSH DWORD PTR [EBP+14H] PUSH DWORD PTR [EBP+10H] PUSH DWORD PTR [EBP+0CH] PUSH DWORD PTR [EBP+08H] CALL DefWindowProcA@16 JMP FINISH WMDESTROY: PUSH 0 ; MB_OK PUSH OFFSET CAP PUSH OFFSET MES PUSH DWORD PTR [EBP+08H] ; Window descriptor CALL MessageBoxA@16 PUSH 0 CALL PostQuitMessage@4 ; WM_QUIT message MOV EAX, 0 FINISH: POP EDI POP ESI POP EBX POP EBP RET 16 WNDPROC ENDP _TEXT ENDS END START

 

[i] Honestly, I am not proceeding properly here. After making sure that the button generated an event, you ought to determine what kind of event it was by checking the most significant word of WPARAM (the BN_CLICKED = 0 event). However, without going into particulars, I'd like to note that in most examples you consider here it is not necessary to do this for a button.

Категории