Ассемблер для Windows

Данный раздел посвящен диалоговому окну с двумя списками



III

Данный раздел посвящен диалоговому окну с двумя списками. Двойным щелчком по элементу левого списка заполняется правый список. При этом мы учитываем возможность повторного щелчка по одному и тому же элементу. В принципе, в программе нет ничего сложного. Ниже будет дан комментарий к ней. Но мне хотелось бы немного поговорить о таком элементе, как список, остановившись на некоторых важных моментах.

Средства управления списком можно разделить на сообщения и свойства32. Свойства задаются в файле ресурсов. Например, свойство LBS_SORT приводит к тому, что содержимое списка будет автоматически сортироваться при добавлении туда элемента. Очень важным является свойство LBS_WANTKEYBOARDINPUT. При наличии такого свойства приложение получает сообщение WM_VKEYTOITEM, которое посылается приложению, когда нажимается какая-либо клавиша при наличии фокуса на данном списке. Вы можете выбрать самостоятельную обработку - клавиша PgUp, или оставить стандартную обработку. В том случае, если стандартная обработка не нужна, следует возвратить из функции диалогового окна отрицательное значение.

32

Впрочем, это можно сказать о любых элементах на диалоговом окне. Не правда ли, это весьма похоже на методы и свойства в объектном программировании. Но мы то с Вами знаем, что если углубиться еще дальше, то мы обнаружим, что значительная часть свойств опять сведется к обработке сообщений (см. комментарий к программе на Рисунок 2.4.3).

// файл diallst.rc

// определение констант #define WS_SYSMENU 0x00080000L #define WS_MINIMIZEBOX 0x00020000L #define WS_MAXIMIZEBOX 0x00010000L #define WS_VISIBLE 0x10000000L #define WS_TABSTOP 0x00010000L #define WS_VSCROLL 0x00200000L #define WS_THICKFRAME 0x00040000L #define LBS_NOTIFY 0x0001L #define LBS_SORT 0x0002L #define LBS_WANTKEYBOARDINPUT 0x0400L

// идентификаторы #define LIST1 101 #define LIST2 102 #define IDI_ICON1 3

// определили иконку IDI_ICON1 ICON "ico1.ico"

// определение диалогового окна DIAL1 DIALOG 0, 0, 210, 110 STYLE WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX CAPTION "Пример диалогового окна" FONT 8, "Arial" { CONTROL "ListBox1",LIST1, "listbox", WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | WS_THICKFRAME | LBS_NOTIFY | LBS_WANTKEYBOARDINPUT, 16, 16, 70, 75 CONTROL "ListBox2", LIST2, "listbox", WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | WS_THICKFRAME | LBS_NOTIFY | LBS_SORT, 116, 16, 70, 75 }




; файл diallst.inc ; константы ; сообщение приходит при закрытии окна WM_CLOSE equ 10h WM_INITDIALOG equ 110h WM_SETICON equ 80h WM_COMMAND equ 111h WM_VKEYTOITEM equ 2Eh LB_ADDSTRING equ 180h LBN_DBLCLK equ 2 LB_GETCURSEL equ 188h LB_GETTEXT equ 189h LB_FINDSTRING equ 18Fh VK_INSERT equ 2Dh

; прототипы внешних процедур EXTERN ExitProcess@4:NEAR EXTERN GetModuleHandleA@4:NEAR EXTERN DialogBoxParamA@20:NEAR EXTERN EndDialog@8:NEAR EXTERN LoadIconA@8:NEAR EXTERN SendMessageA@16:NEAR EXTERN SendDlgItemMessageA@20:NEAR EXTERN MessageBoxA@16:NEAR

; структуры ; структура сообщения MSGSTRUCT STRUC MSHWND DD ? MSMESSAGE DD ? MSWPARAM DD ? MSLPARAM DD ? MSTIME DD ? MSPT DD ? MSGSTRUCT ENDS

; файл diallst.asm .386P ; плоская модель .MODEL FLAT, stdcall include dial.inc ; директивы компоновщику для подключения библиотек includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib ;------------------------------------------------- ; сегмент данных _DATA SEGMENT DWORD PUBLIC USE32 'DATA' MSG MSGSTRUCT <?> HINST DD 0 ; дескриптор приложения PA DB "DIAL1",0 BUFER DB 100 DUP (0) STR1 DB "Первый",0 STR2 DB "Второй",0 STR3 DB "Третий",0 STR4 DB "Четвертый",0 STR5 DB "Пятый ",0 STR6 DB "Шестой",0 STR7 DB "Седьмой",0 STR8 DB "Восьмой",0 STR9 DB "Девятый",0 STR10 DB "Десятый",0 STR11 DB "Одиннадцатый",0 STR12 DB "Двенадцатый",0 STR13 DB "Тринадцатый",0 STR14 DB "Четырнадцатый",0 STR15 DB "Пятнадцатый",0 INDEX DD OFFSET STR1 DD OFFSET STR2 DD OFFSET STR3 DD OFFSET STR4 DD OFFSET STR5 DD OFFSET STR6 DD OFFSET STR7 DD OFFSET STR8 DD OFFSET STR9 DD OFFSET STR10 DD OFFSET STR11 DD OFFSET STR12 DD OFFSET STR13 DD OFFSET STR14 DD OFFSET STR15 _DATA ENDS

; сегмент кода _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: ; получить дескриптор приложения PUSH 0 CALL GetModuleHandleA@4 MOV [HINST], EAX ;---------------------------------------- PUSH 0 PUSH OFFSET WNDPROC PUSH 0 PUSH OFFSET PA PUSH [HINST] CALL DialogBoxParamA@20 CMP EAX,-1 JNE KOL ; сообщение об ошибке KOL: ;---------------------------------------- PUSH 0 CALL ExitProcess@4 ;---------------------------------------- ; процедура окна ; расположение параметров в стеке ; [EBP+014Н] ; 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_CLOSE JNE L1 PUSH 0 PUSH DWORD PTR [EBP+08H] CALL EndDialog@8 JMP FINISH L1: CMP DWORD PTR [EBP+0CH], WM_INITDIALOG JNE L2 ; загрузить иконку PUSH 3 ; идентификатор иконки PUSH [HINST] ; идентификатор процесса CALL LoadIconA@8 ; установить иконку PUSH EAX PUSH 0 ; тип иконки (маленькая) PUSH WM_SETICON PUSH DWORD PTR [EBP+08H] CALL SendMessageA@16 ; заполнить левый список MOV ECX, 15 MOV ESI, 0 L01: PUSH ECX ; сохранить параметр цикла PUSH INDEX[ESI] PUSH 0 PUSH LB_ADDSTRING PUSH 101 PUSH DWORD PTR [EBP+08H] CALL SendDlgItemMessageA@20 ADD ESI, 4 POP ECX LOOP L01 JMP FINISH L2: CMP DWORD PTR [EBP+0CH],WM_COMMAND JNE L3 ; не сообщение ли от левого списка? CMP WORD PTR [EBP+10Н],101 JNE FINISH ; не было ли двойного щелчка? CMP WORD PTR [EBP+12H], LBN_DBLCLK JNE FINISH ; был двойной щелчок, теперь определим элемент ; получить индекс выбранного элемента L4: PUSH 0 PUSH 0 PUSH LB_GETCURSEL PUSH 101 PUSH DWORD PTR [EBP+08H] CALL SendDlgItemMessageA@20 ; скопировать элемент списка в буфер PUSH OFFSET BUFER PUSH EAX ; индекс записи PUSH LB_GETTEXT PUSH 101 PUSH DWORD PTR [EBP+08H] CALL SendDlgItemMessageA@20 ; определить, нет ли элемента в правом списке PUSH OFFSET BUFER PUSH -1 ; искать во всем списке PUSH LB_FINDSTRING PUSH 102 PUSH DWORD PTR [EBP+08H] CALL SendDlgItemMessageA@20 CMP EAX,-1 JNE FINISH ; элемент нашли ; не нашли, можно добавлять PUSH OFFSET BUFER PUSH 0 PUSH LB_ADDSTRING PUSH 102 PUSH DWORD PTR [EBP+08H] CALL SendDlgItemMessageA@20 MOV EAX,-1 JMP FIN L3: ; здесь проверка, не нажата ли клавиша CMP DWORD PTR [EBP+0CH],WM_VKEYTOITEM JNE FINISH CMP WORD PTR [EBP+10H],VK_INSERT JE L4 MOV EAX,-1 JMP FIN FINISH: MOV EAX, 0 FIN: POP EDI POP ESI POP EBX POP EBP RET 16 WNDPROC ENDP _TEXT ENDS END START


Содержание раздела