
- •«Техника работы с окнами»
- •Содержание
- •Описание используемых api-функций
- •InvalidateRect Добавляет прямоугольник к области модификации указанного окна. Обновление региона представляет собой часть клиентской области окна, которые должны быть перерисованы.
- •CreateWindowEx Создает перекрывающее, всплывающее или дочернее окно с расширенным стилем окна.
- •DispatchMessage
- •Исходный текст отлаженной программы
- •Результаты работы программы:
- •Список литературы:
Исходный текст отлаженной программы
/*okna.inc*/
WM_DESTROY equ 2
WM_CREATE equ 1
WM_LBUTTONDOWN equ 201h
WM_RBUTTONDOWN equ 204h
VK_R equ 52h
VK_G equ 47h
VK_B equ 42h
WM_KEYDOWN equ 100h
WM_PAINT equ 0FH
CS_VREDRAW equ 1h
CS_HREDRAW equ 2h
CS_GLOBALCLASS equ 4000h
WS_OVERLAPPEDWINDOW equ 000CF0000H
IDI_WINLOGO equ 32517
IDC_HAND equ 32649
stylcl equ CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS
WS_VSCROLL equ 00200000H
WS_HSCROLL equ 00100000H
stylcl2 equ WS_OVERLAPPEDWINDOW
BS_DEFPUSHBUTTON equ 1h
WS_VISIBLE equ 10000000h
WS_CHILD equ 40000000h
WS_BORDER equ 800000h
WS_TABSTOP equ 10000h
STYLBTN equ WS_CHILD + BS_DEFPUSHBUTTON + WS_VISIBLE + WS_TABSTOP
STYLEDT equ WS_CHILD + WS_VISIBLE + WS_BORDER + WS_TABSTOP
SW_SHOWNORMAL equ 1
WM_COMMAND equ 111h
WS_CHILD equ 40000000h
BS_DEFPUSHBUTTON equ 1h
WS_VISIBLE equ 10000000h
EXTERN InvalidateRect@12:NEAR
SetFocus PROTO :DWORD
DefWindowProcA PROTO :DWORD, :DWORD, :DWORD, :DWORD
CreateWindowExA PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
DispatchMessageA PROTO :DWORD
ExitProcess PROTO :DWORD
GetMessageA PROTO :DWORD, :DWORD, :DWORD, :DWORD
GetModuleHandleA PROTO :DWORD
LoadCursorA PROTO :DWORD, :DWORD
LoadIconA PROTO :DWORD, :DWORD
PostQuitMessage PROTO :DWORD
RegisterClassA PROTO :DWORD
ShowWindow PROTO :DWORD, :DWORD
TranslateMessage PROTO :DWORD
UpdateWindow PROTO :DWORD
BeginPaint PROTO :DWORD, :DWORD
EndPaint PROTO :DWORD, :DWORD
CreateSolidBrush PROTO :DWORD
GetSystemMetrics PROTO :DWORD
GetDC PROTO :DWORD
CreateCompatibleDC PROTO :DWORD
SelectObject PROTO :DWORD, :DWORD
PatBlt PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
BitBlt PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
ReleaseDC PROTO :DWORD, :DWORD
DeleteDC PROTO :DWORD
Ellipse PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
SendMessageA PROTO :DWORD, :DWORD, :DWORD, :DWORD
MessageBoxA PROTO :DWORD, :DWORD, :DWORD, :DWORD
MSGSTRUCT STRUC
MSHWND DD ?
MSMESSAGE DD ?
MSWPARAM DD ?
MSLPARAM DD ?
MSTIME DD ?
MSPT DD ?
MSGSTRUCT ENDS
WNDCLASS STRUC
CLSSTYLE DD ?
CLSLPFNWNDPROC DD ?
CLSCBCLSEXTRA DD ?
CLSCBWNDEXTRA DD ?
CLSHINSTANCE DD ?
CLSHICON DD ?
CLSHCURSOR DD ?
CLSHBRBACKGROUND DD ?
MENNAME DD ?
CLSNAME DD ?
WNDCLASS ENDS
PAINTSTR STRUC
hdc DD 0
fErase DD 0
left DD 0
top DD 0
right DD 0
bottom DD 0
fRes DD 0
fIncUp DD 0
Reserv DB 32 dup(0)
PAINTSTR ENDS
RECT STRUC
L DD ?
T DD ?
R DD ?
B DD ?
RECT ENDS
/*okna.asm*/
.386P
; плоская модель
.MODEL FLAT, stdcall
include ./okna.inc
; подключение библиотек
includelib D://masm32/lib/user32.lib
includelib D://masm32/lib/kernel32.lib
includelib D://masm32/lib/gdi32.lib
;===============================================================
; сегмент данных
;===============================================================
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
NEWHWND DWORD 0
MSG MSGSTRUCT <?>
WC WNDCLASS <?>
PNT PAINTSTR <?>
HINST DWORD 0
TITLENAME BYTE 'Работа с окнами',0
NAM BYTE 'CLASS32',0
XM DWORD ?
YM DWORD ?
HDC DWORD ?
MEMDC DWORD ?
HBRUSHRED DWORD ?
RED DWORD 0FFH
HBRUSHGREEN DWORD ?
GREEN DWORD 000FF00H
HBRUSHBLUE DWORD ?
BLUE DWORD 0FF0000H
HBRUSHGRAY DWORD ?
GRAY DWORD 0F0F0F0H
pR BYTE 0 ; признак нажатия клавиши R
pG BYTE 0 ; признак нажатия клавиши G
pB BYTE 0 ; признак нажатия клавиши B
CPBUT BYTE 'Выход',0
CLSBUTN BYTE 'BUTTON',0
HWNDBTN DWORD 0 ; дескриптор кнопки "Выход"
CAP BYTE 'Сообщение',0
MESBTN BYTE 'Вы действительно хотите выйти?',0
CPAUTHOR BYTE 'Об авторе',0 ;
HWNDAUTHOR DWORD 0 ; дескриптор кнопки "Автор"
CAPAUTHOR BYTE 'Об авторе',0
MESAUTHOR BYTE 'Калач С.А. 8-78-3. 2014',0
CPRED BYTE 'Красный',0 ;
HWNDRED DWORD 0 ; дескриптор кнопки "Красный"
MESRED BYTE 'Вы выбрали красный цвет квадратаа',0
MESRED2 BYTE 'Квадрат уже красный. Выберите другой цвет',0
pRED BYTE 0 ; признак нажатия кнопки "Красный"
CPBLUE BYTE 'Синий',0 ;
HWNDBLUE DWORD 0 ; дескриптор кнопки "Синий"
MESBLUE BYTE 'Вы выбрали синий цвет квадрата',0
MESBLUE2 BYTE 'Квадрат уже синий. Выберите другой цвет',0
pBLUE BYTE 0 ; признак нажатия кнопки "Синий"
CPGREEN BYTE 'Зелёный',0 ;
HWNDGREEN DWORD 0 ; дескриптор кнопки "Зелёный"
MESGREEN BYTE 'Вы выбрали зелёный цвет квадрата',0
MESGREEN2 BYTE 'Квадрат уже зелёный. Выберите другой цвет',0
pGREEN BYTE 0 ; признак нажатия кнопки "Зелёный"
CPCLEAR BYTE 'Очистить',0 ;
HWNDCLEAR DWORD 0 ; дескриптор кнопки "Очистить"
pCLEAR BYTE 0 ; признак нажатия кнопки "Очистить"
TEXTCLEAR BYTE 0 ; текст для очисти строки редактирования
HWNDEDT DWORD 0 ; дескриптор строки редактирования
CPEDT BYTE 'Нажми клавиши R,G,B',0
CLSEDIT BYTE 'EDIT',0
_DATA ENDS
;===============================================================
; сегмент кода
;===============================================================
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'
START:
; получить дескриптор приложения
INVOKE GetModuleHandleA,0
MOV [HINST], EAX
REG_CLASS:
; заполнить структуру окна
MOV [WC.CLSSTYLE],stylcl ; стиль
MOV [WC.CLSLPFNWNDPROC], OFFSET WNDPROC ; процедура обработки сообщений
MOV [WC.CLSCBCLSEXTRA],0
MOV [WC.CLSCBWNDEXTRA], 0
MOV EAX, [HINST]
MOV [WC.CLSHINSTANCE], EAX
INVOKE LoadIconA,0,IDI_WINLOGO ; иконка окна
MOV [WC.CLSHICON], EAX
INVOKE LoadCursorA,0,IDC_HAND ; курсор окна
MOV [WC.CLSHCURSOR], EAX
INVOKE CreateSolidBrush,0FFFFFFh ; создать кисть белым цветом
MOV [WC.CLSHBRBACKGROUND], EAX
MOV DWORD PTR [WC.MENNAME],0
MOV DWORD PTR [WC.CLSNAME], OFFSET NAM
INVOKE RegisterClassA, OFFSET WC
; создать окно зарегистрированного класса
INVOKE CreateWindowExA,0,OFFSET NAM, OFFSET TITLENAME, stylcl2,330,180,360,225,0,0,[HINST],0
; проверка на ошибку
CMP EAX, 0
JZ _ERR
MOV [NEWHWND], EAX ; дескриптор окна
INVOKE ShowWindow,[NEWHWND],SW_SHOWNORMAL ; показать созданное окно
INVOKE UpdateWindow,[NEWHWND] ; перерисовать видимую часть окна
; петля обработки сообщений
MSG_LOOP:
INVOKE GetMessageA, OFFSET MSG,0,0,0
CMP AX, 0
JE END_LOOP
INVOKE TranslateMessage,OFFSET MSG
INVOKE DispatchMessageA,OFFSET MSG
JMP MSG_LOOP
END_LOOP:
; выход из программы (закрыть процесс)
INVOKE ExitProcess,[MSG.MSWPARAM]
_ERR:
JMP END_LOOP
;===============================================================
; процедура окна
; расположение параметров в стеке
; [EBP+014Н] ; LPARAM
; [EBP+10H] ; WPARAM
; [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_PAINT ; сообщение WM_PAINT - при рисовании окна
JE WMPAINT
CMP DWORD PTR [EBP+0CH],WM_DESTROY ; сообщение WM_DESTROY - при закры-тии окна
JE WMDESTROY
CMP DWORD PTR [EBP+0CH],WM_CREATE ; сообщение WM CREATE - при создании окна
JE WMCREATE
CMP DWORD PTR [EBP+0CH],WM_KEYDOWN ; сообщение WM_KEYDOWN - при нажатии клавиш
JE KEY_DOWN
CMP DWORD PTR [EBP+0CH],WM_COMMAND ; сообщение WM COMMAND - при событи-ях с элементами на окне
JE WMCOMMAND
CMP DWORD PTR [EBP+0CH],WM_LBUTTONDOWN
JE LBUTTONDOWN
JMP DEFWNDPROC
LBUTTONDOWN:
INVOKE SetFocus,NEWHWND
;================================
WMCOMMAND:
MOV EAX, HWNDBTN
CMP DWORD PTR [EBP+14H], EAX ; не нажата ли кнопка "Выход"?
JNE DOWN
INVOKE MessageBoxA,DWORD PTR [EBP+08H],OFFSET MESBTN,OFFSET CAP,1 ; 40h - MB_ICONINFORMATION
CMP EAX,1
JNE DOWN
JMP WMDESTROY
DOWN:
;----------
MOV EAX, HWNDAUTHOR
CMP DWORD PTR [EBP+14H], EAX ; не нажата ли кнопка "Об авторе"?
JNE next1
INVOKE MessageBoxA,DWORD PTR [EBP+08H],OFFSET MESAUTHOR,OFFSET CAPAUTHOR,40h ; 40h - MB_ICONINFORMATION
next1:
;----------
MOV EAX, HWNDRED
CMP DWORD PTR [EBP+14H], EAX ; не нажата ли кнопка "Красный"?
JNE next2
CMP pRED,1 ; квадрат уже красный?
JNE next5
INVOKE MessageBoxA,DWORD PTR [EBP+08H],OFFSET MESRED2,OFFSET CAP,30h ; 30h - MB_ICONWARNING
JMP next2
next5:
MOV pRED,1
MOV pBLUE,0
MOV pGREEN,0
INVOKE MessageBoxA,DWORD PTR [EBP+08H],OFFSET MESRED,OFFSET CAP,30h
next2:
;----------
MOV EAX, HWNDGREEN
CMP DWORD PTR [EBP+14H], EAX ; не нажата ли кнопка "Зелёный"?
JNE next7
CMP pGREEN,1 ; квадрат уже зелёный?
JNE next8
INVOKE MessageBoxA,DWORD PTR [EBP+08H],OFFSET MESGREEN2,OFFSET CAP,30h
JMP next7
next8:
MOV pGREEN,1
MOV pRED,0
MOV pBLUE,0
INVOKE MessageBoxA,DWORD PTR [EBP+08H],OFFSET MESGREEN,OFFSET CAP,30h
next7:
;----------
MOV EAX, HWNDBLUE
CMP DWORD PTR [EBP+14H], EAX ; не нажата ли кнопка "Синий"?
JNE next3
CMP pBLUE,1 ; квадрат уже синий?
JNE next6
INVOKE MessageBoxA,DWORD PTR [EBP+08H],OFFSET MESBLUE2,OFFSET CAP,30h
JMP next3
next6:
MOV pBLUE,1
MOV pRED,0
MOV pGREEN,0
INVOKE MessageBoxA,DWORD PTR [EBP+08H],OFFSET MESBLUE,OFFSET CAP,30h
next3:
;----------
MOV EAX, HWNDCLEAR
CMP DWORD PTR [EBP+14H], EAX ; не нажата ли кнопка "Очистить"?
JNE next12
; поместить строку в окно редактирования
INVOKE SendMessageA,HWNDEDT,000CH,0,OFFSET TEXTCLEAR ; 000CH - WM_SETTEXT
INVOKE SetFocus,NEWHWND
next12:
;----------
; дать команду перерисовать окно
PUSH 0
PUSH OFFSET RECT
PUSH DWORD PTR [EBP+08H]
CALL InvalidateRect@12
MOV EAX, 0
JMP FINISH
;================================
KEY_DOWN:
CMP DWORD PTR [EBP+10H],VK_R
JNE R_NODOWN
CMP pRED,1 ; квадрат уже красный?
JNE next9
INVOKE MessageBoxA,DWORD PTR [EBP+08H],OFFSET MESRED2,OFFSET CAP,30h
JMP R_NODOWN
next9:
MOV pRED,1
MOV pGREEN,0
MOV pBLUE,0
R_NODOWN:
;----------
CMP DWORD PTR [EBP+10H],VK_G
JNE G_NODOWN
CMP pGREEN,1 ; квадрат уже зелёный?
JNE next10
INVOKE MessageBoxA,DWORD PTR [EBP+08H],OFFSET MESGREEN2,OFFSET CAP,30h
JMP G_NODOWN
next10:
MOV pGREEN,1
MOV pRED,0
MOV pBLUE,0
G_NODOWN:
;----------
CMP DWORD PTR [EBP+10H],VK_B
JNE B_NODOWN
CMP pBLUE,1 ; квадрат уже синий?
JNE next11
INVOKE MessageBoxA,DWORD PTR [EBP+08H],OFFSET MESBLUE2,OFFSET CAP,30h
JMP B_NODOWN
next11:
MOV pBLUE,1
MOV pGREEN,0
MOV pRED,0
B_NODOWN:
;----------
; дать команду перерисовать окно
PUSH 0
PUSH OFFSET RECT
PUSH DWORD PTR [EBP+08H]
CALL InvalidateRect@12
MOV EAX, 0
JMP FINISH
;================================
WMPAINT:
INVOKE BeginPaint, DWORD PTR [EBP+08H],OFFSET PNT
MOV HDC,EAX ; сохранить контекст (дескриптор)
INVOKE CreateSolidBrush, 0FF9933h; серый 08B8B83h ; фон
INVOKE SelectObject,MEMDC,EAX
; заполнить данную прямоугольную область
; 0F00021H РАТСОРУ=заполнить данным цветом
INVOKE PatBlt,MEMDC,0,0,XM,YM,0F00021H
;----------
CMP pRED,1
JNE RED_NO
INVOKE SelectObject,MEMDC,HBRUSHRED
INVOKE Rectangle,MEMDC,170,70,250,150
JMP CONT
RED_NO:
;----------
CMP pGREEN,1
JNE GREEN_NO
INVOKE SelectObject,MEMDC,HBRUSHGREEN
INVOKE Rectangle,MEMDC,170,70,250,150
JMP CONT
GREEN_NO:
;----------
CMP pBLUE,1
JNE BLUE_NO
INVOKE SelectObject,MEMDC,HBRUSHBLUE
INVOKE Rectangle,MEMDC,170,70,250,150
JMP CONT
BLUE_NO :
INVOKE SelectObject,MEMDC,HBRUSHGRAY
INVOKE Rectangle,MEMDC,170,70,250,150
CONT:
;----------
; скопировать виртуальное окно на реальное
INVOKE BitBlt,HDC,0,0,XM,YM,MEMDC,0,0,0CC0020h ; SRCCOPY=изображение как есть
; закрыть контекст окна
INVOKE EndPaint, DWORD PTR [EBP+08H],OFFSET PNT
MOV EAX, 0
JMP FINISH
;================================
WMCREATE:
; размеры экрана
INVOKE GetSystemMetrics,0
MOV XM, EAX
INVOKE GetSystemMetrics,1
MOV YM, EAX
; открыть контекст окна
INVOKE GetDC,DWORD PTR [EBP+08H]
MOV HDC,EAX
; создать совместимый с данным окном контекст
INVOKE CreateCompatibleDC,EAX
MOV MEMDC, EAX
; создать в памяти растровое изображение, совместимое с hdc
INVOKE CreateCompatibleBitmap,HDC,XM,YM
; выбрать растровое изображение в данном контексте
INVOKE SelectObject,MEMDC,EAX
INVOKE CreateSolidBrush,RED ; создать кисть цветом RED
MOV HBRUSHRED,EAX
INVOKE CreateSolidBrush,GREEN ; создать кисть цветом GREEN
MOV HBRUSHGREEN,EAX
INVOKE CreateSolidBrush,BLUE ; создать кисть цветом BLUE
MOV HBRUSHBLUE,EAX
INVOKE CreateSolidBrush,GRAY ; создать кисть цветом GRAY
MOV HBRUSHGRAY,EAX
; удалить контекст
INVOKE ReleaseDC,DWORD PTR [EBP+08H],HDC
; кнопка "Выход"
INVOKE CreateWindowExA,0,OFFSET CLSBUTN,OFFSET CPBUT,STYLBTN,10,10,80,20,DWORD PTR [EBP+08H],0,[HINST],0
MOV HWNDBTN, EAX ; запомнить дескриптор кнопки "Выход"
; кнопка "Об авторе"
INVOKE CreateWindowExA,0,OFFSET CLSBUTN,OFFSET CPAUTHOR,STYLBTN,10,40,80,20,DWORD PTR [EBP+08H],0,[HINST],0
MOV HWNDAUTHOR, EAX ; запомнить дескриптор кнопки "Об авторе"
; кнопка "Красный"
INVOKE CreateWindowExA,0,OFFSET CLSBUTN,OFFSET CPRED,STYLBTN,10,70,80,20,DWORD PTR [EBP+08H],0,[HINST],0
MOV HWNDRED, EAX ; запомнить дескриптор кнопки "Красный"
; кнопка "Зелёный"
INVOKE CreateWindowExA,0,OFFSET CLSBUTN,OFFSET CPGREEN,STYLBTN,10,100,80,20,DWORD PTR [EBP+08H],0,[HINST],0
MOV HWNDGREEN, EAX ; запомнить дескриптор кнопки "Зелёный"
; кнопка "Синий"
INVOKE CreateWindowExA,0,OFFSET CLSBUTN,OFFSET CPBLUE,STYLBTN,10,130,80,20,DWORD PTR [EBP+08H],0,[HINST],0
MOV HWNDBLUE, EAX ; запомнить дескриптор кнопки "Синий"
; кнопка "Очистить"
INVOKE CreateWindowExA,0,OFFSET CLSBUTN,OFFSET CPCLEAR,STYLBTN,260,160,80,20,DWORD PTR [EBP+08H],0,[HINST],0
MOV HWNDCLEAR, EAX ; запомнить дескриптор кнопки "Очистить"
; строка редактирования
INVOKE CreateWindowExA,0,OFFSET CLSEDIT,OFFSET CPEDT,STYLEDT,10,160,240,20,DWORD PTR [EBP+08H],0,[HINST],0
MOV HWNDEDT,EAX
; установить фокус на окне редактирования
; INVOKE SetFocus,HWNDEDT
MOV EAX, 0
JMP FINISH
;================================
DEFWNDPROC:
INVOKE DefWindowProcA,DWORD PTR [EBP+08H],DWORD PTR [EBP+0CH],DWORD PTR [EBP+10H],DWORD PTR [EBP+14H]
JMP FINISH
;================================
WMDESTROY:
INVOKE DeleteDC,HBRUSHRED ; удалить кисти
INVOKE DeleteDC,HBRUSHGREEN
INVOKE DeleteDC,HBRUSHBLUE
INVOKE DeleteDC,HBRUSHGRAY
INVOKE DeleteDC,MEMDC ; удалить виртуальное окно
INVOKE PostQuitMessage,0 ; выход WM_QUIT
MOV EAX, 0
;================================
FINISH:
POP EDI
POP ESI
POP EBX
POP EBP
RET 16
WNDPROC ENDP
_TEXT ENDS
END START