| ||
The last example in this chapter demonstrates the operation of a program with a drop-down list. When creating a list, it is filled with the names of different colors. If you double-click a specific color , the message box displaying the name of this color will appear.
The steps that occur after you double-click a specific list element are as follows : the event related to the list is detected first, then the most significant word of WPARAM is used, to determine which event took place. This task is carried out by the [ EBP+10H ] parameter, namely, by its most significant part[ EBP+12H ].
Although I have no opportunity to cover the properties of various controls in detail, I'll outline the basic idea of a control such as a list. Each element of the list has a set of attributes that can be used to locate it within the list: an ordinal number, a unique number, and an element name. The unique number is especially important because it allows the element to be identified uniquely.
; The lst.inc file ; Constants WM_SETFOCUS equ 7h ; The message that arrives when the window is closed WM_DESTROY equ 2 ; The message that arrives when the window is created WM_CREATE equ 1 ; The message that arrives when something happens ; to the window controls WM_COMMAND equ 111h ; The message that allows you to send the string to the control WM_SETTEXT equ 0Ch ; The message that allows you to receive the string WM_GETTEXT equ 0Dh ; The command message for adding strings LB_ADDSTRING equ 180h LB_GETTEXT equ 189h LB_GETCURSEL equ 188h LBN_DBLCLK equ 2 ; Window properties CS_VREDRAW equ 1h CS_HREDRAW equ 2h CS_GLOBALCLASS equ 4000h WS_TABSTOP equ 10000h WS_SYSMENU equ 80000h WS_THICKFRAME equ 40000h WS_OVERLAPPEDWINDOW equ WS_TABSTOP+WS_SYSMENU STYLE equ CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS CS_HREDRAW equ 2h BS_DEFPUSHBUTTON equ 1h WS_VISIBLE equ 10000000h WS_CHILD equ 40000000h WS_BORDER equ 800000h WS_VSCROLL equ 200000h LBS_NOTIFY equ 1h STYLBTN equ WS_CHILD + BS_DEFPUSHBUTTON + WS_VISIBLE + WS_TABSTOP STYLLST equ WS_THICKFRAME + WS_CHILD + WS_VISIBLE + WS_BORDER + WS_TABSTOP + WS_VSCROLL + LBS_NOTIFY ; Standard icon identifier IDI_APPLICATION equ 32512 ; Cursor identifier IDC_ARROW equ 32512 ; Normal window display mode SW_SHOWNORMAL equ 1 ; Prototypes of external procedures EXTERN SetFocus@4:NEAR EXTERN SendMessageA@16:NEAR 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 ; Structures ; 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 list.asm file .586P ; Flat memory model .MODEL FLAT, stdcall include list.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 of the LISTBOX window', 0 CLASSNAME DB 'CLASS32', 0 CPBUT DB 'Exit', 0 ; Exit CPLST DB ' ', 0 CLSBUTN DB 'BUTTON', 0 CLSLIST DB 'LISTBOX', 0 HWNDBTN DWORD 0 HWNDLST DWORD 0 CAP DB 'Message', 0 CAP1 DB 'Chosen', 0 MES DB 'Program termination', 0 ; Array of strings STR1 DB 'Red', 0 STR2 DB 'Green', 0 STR3 DB 'Blue', 0 STR4 DB 'Yellow', 0 STR5 DB 'Black', 0 STR6 DB 'White', 0 ; Pointers to strings PS DWORD OFFSET STR1 DWORD OFFSET STR2 DWORD OFFSET STR3 DWORD OFFSET STR4 DWORD OFFSET STR5 DWORD OFFSET STR6 BUF DB 30 dup(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 200 ; DY - Window height PUSH 250 ; DX - Window width PUSH 100 ; Y - Coordinate of the top left corner PUSH 100 ; X - Coordinate of the top left corner PUSH WS_OVERLAPPEDWINDOW PUSH OFFSET TITLENAME ; Window title 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 ; Display the newly created window ;------------------------------------------ PUSH [NEWHWND] CALL UpdateWindow@4 ; Command to redraw the visible part ; of the window, the WM_PAINT message ; Message-handling 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_LCOP ; 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 ; Button? ; Exit? JE WMDESTROY MOV EAX, HWNDLST CMP DWORD PTR [EBP+14H], EAX ; List? JNE NOLIST ; Working with the list CMP WORD PTR [EBP+12H], LBN_DBLCLK JNE NOLIST ; There was a double-click ; Now determine the chosen line ; First index PUSH 0 PUSH 0 PUSH LB_GETCURSEL PUSH HWNDLST CALL SendMessageA@16 ; Now text PUSH OFFSET BUF PUSH EAX PUSH LB_GETTEXT PUSH HWNDLST CALL SendMessageA@16 ; Specify, what has been chosen PUSH 0 PUSH OFFSET CAP1 PUSH OFFSET BUF PUSH DWORD PTR [EBP+08H] CALL MessageBoxA@16 NOLIST: 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 ; Class name PUSH 0 CALL CreateWindowExA@48 MOV HWNDBTN, EAX ; Save the button descriptor ;------------------------------------------ ; Create the LISTBOX window PUSH 0 PUSH [HINST] PUSH 0 PUSH DWORD PTR [EBP+08H] PUSH 90 ; DY PUSH 150 ; DX PUSH 50 ; Y PUSH 10 ; X PUSH STYLLST PUSH OFFSET CPLST ; Window name PUSH OFFSET CLSLIST ; Class name PUSH 0 CALL CreateWindowExA@48 MOV HWNDLST, EAX ; Fill the list PUSH PS PUSH 0 PUSH LB_ADDSTRING PUSH HWNDLST CALL SendMessageA@16 PUSH PS+4 PUSH 0 PUSH LB_ADDSTRING PUSH HWNDLST CALL SendMessageA@16 PUSH PS+8 PUSH 0 PUSH LB_ADDSTRING PUSH HWNDLST CALL SendMessageA@16 PUSH PS+12 PUSH 0 PUSH LB_ADDSTRING PUSH HWNDLST CALL SendMessageA@16 PUSH PS+16 PUSH 0 PUSH LB_ADDSTRING PUSH HWNDLST CALL SendMessageA@16 PUSH PS+20 PUSH 0 PUSH LB_ADDSTRING PUSH HWNDLST CALL SendMessageA@16 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 MessageBoxAG16 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'd like to mention one important topic. In the course of program execution, various interesting and unusual events may occur to the window. For example, the user may drag the window over the screen, resize it as desired, and finally open other windows that overlap the current one.
In such situations, the system sends the WM_PAINT message to the window. The same message is sent to the window when executing some functions related to redrawing the window, such as the UpdateWindow function. If the WM_PAINT message is not processed by the window procedure but is returned to the system by the DefWindowProc function, the system redraws the window (under any conditions) and redraws the window contents. However, only child windows are related to window contents, such as buttons , lists, and other controls. In the next chapters, I will describe various methods of putting text and graphical information into the window. To ensure that the information is preserved in the window, you must process the WM_PAINT message.
To conclude, note that the examples provided in this chapter are written to be compiled using MASM32. To use them with TASM32, as mentioned previously, it is sufficient to remove the @N suffix from all names of API functions and to use the IMPORT32.LIB library instead of USER32.LIB and KERNEL32.LIB.
| ||