Консультация № 191459
11.10.2017, 07:06
0.00 руб.
0 3 1
Здравствуйте! У меня возникли сложности с таким вопросом:

Помогите пожалуйста мне исправить этот код. Нужно чтобы программа выполняла вот такие действия:

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

Удаляются кнопки - тоже по очереди, начиная с последней появившейся кнопки, щелчками правой клавиши мыши.
Начинать добавление и удаление кнопок можно в любой последовательности:
Например: добавил три кнопки, удалил одну, добавил еще четыре, удалил две и т.д.

Увеличить расстояние между кнопками по вертикали, чтобы между ними было по 10 ps.
Программа была написана с помощью компилятора TASM
Вот сам код:


Приложение:
;WIN_my2.asm
.386
locals
jumps
.model flat,STDCALL
include win32.inc
L equ <LARGE>
Extrn BeginPaint:PROC ;начало блока перерисовки окна
Extrn CreateWindowExA:PROC ;создать окно
Extrn DefWindowProcA:PROC ;процедура обработки сообщений ;по-умолчанию
Extrn DispatchMessageA:PROC ;процедура передачи сообщения оконному обработчику сооб-щений
Extrn EndPaint:PROC ;завершение блока перерисовки ок-на
Extrn ExitProcess:PROC ;завершение программы
extrn FindWindowA:PROC ;поиск окна в ОС
extrn GetMessageA:PROC ;принять сообщение из системной ;очереди
extrn GetModuleHandleA:PROC ;получить описатель модуля
extrn GetStockObject:PROC ;получить описатель основного пера,
;кисти или шрифта
extrn InvalidateRect:PROC ;объявление недостоверности области
;пользователя в окне
extrn LoadCursorA:PROC ;загузить иконку курсора
extrn LoadIconA:PROC ;загрузить пиктограмму
extrn MessageBeep:PROC ;издать звуковой сигнал
extrn MessageBoxA:PROC ;выдать системное окно с сообщением
extrn PostQuitMessage:PROC ;послать сообщение о выходе из
;программы
extrn RegisterClassA:PROC ;регистрация класса окна
extrn ShowWindow:PROC ;показать окно на экране
extrn SetWindowPos:PROC ;изменяет размер, положение и поря-док
окна
extrn TextOutA:PROC ;вывод текста в окно
extrn TranslateMessage:PROC ;обработка сообщений от клавиатуры
extrn UpdateWindow:PROC ;обновить окно
CreateWindowEx equ <CreateWindowExA>
DefWindowProc equ <DefWindowProcA>
DispatchMessage equ <DispatchMessageA>
FindWindow equ <FindWindowA>
GetMessage equ <GetMessageA>
GetModuleHandle equ <GetModuleHandleA>
LoadCursor equ <LoadCursorA>
LoadIcon equ <LoadIconA>
MessageBox equ <MessageBoxA>
RegisterClass equ <RegisterClassA>
TextOut equ <TextOutA>
.data
newhwnd dd 0 ;ячейку для хранения описателя (хэндела) нового окна.
lppaint PAINTSTRUCT <?> ;структура для перерисовки изображе-ния.
msg MSGSTRUCT <?> ;структура системного сообщения.
wc WNDCLASS <?> ;структура для регистрации окна.
mbx_count dd 0 ;ячейка - счетчик нажатий левой клавиши мыши.
hInst dd 0 ;ячейка для хранения системного указателя (хэндела)
;нашей программы.
szTitleName db 'Win32 Assembly Program' ;текст заголовка окна ;программы.
zero db 0 ;и его замыкающий ноль.
szAlternate db '(Secondary)',0 ;текст для изменения заголовка окна, ес-ли ;приложение запущено повторно.
szClassName db 'ASMCLASS32',0 ;придуманное нами имя класса окна,
;под которым будем регистрировать-ся.
szPaint db 'Left mouse button pressed:' ;текст сообщения
s_num db '00000000h --times',0 ;в окне программы
MSG_L EQU ($-offset szPaint)-1
;;;;;;;;;;;!!!!!!!!!! ЗАГОЛОВКИ ДЛЯ 10 КНОПОК
_button db 'button',0
_button_tit1 db 'Button 1',0
_button_tit2 db 'Button 2',0
_button_tit3 db 'Button 3',0
_button_tit4 db 'Button 4',0
_button_tit5 db 'Button 5',0
_button_tit6 db 'Button 6',0
_button_tit7 db 'Button 7',0
_button_tit8 db 'Button 8',0
_button_tit9 db 'Button 9',0
_button_tit10 db 'Button 10',0
bh1 dd 0 ; === хендлеры для 10 кнопок ===
bh2 dd 0
bh3 dd 0
bh4 dd 0
bh5 dd 0
bh6 dd 0
bh7 dd 0
bh8 dd 0
bh9 dd 0
bh10 dd 0
;
;
ost dw 10 ; счетчик номера удаляемой кнопки

;;;;;;;;;;;!!!!!!!!!!
.code
start:
push L 0 ;подготовим стэк к запуску процедуры
call GetModuleHandle ;выполним процедуру (результат в EAX)
mov [hInst], eax ;поместим полученный хэндел на ;подготовленное для него место
push L 0
push offset szClassName
call FindWindow
or eax,eax
jz reg_class
mov [zero], ' '

reg_class:
mov [wc.clsStyle], CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS
mov [wc.clsLpfnWndProc], offset WndProc
mov [wc.clsCbClsExtra], 0
mov [wc.clsCbWndExtra], 0
mov eax, [hInst]
mov [wc.clsHInstance], eax
push L IDI_APPLICATION
push L 0
call LoadIcon
mov [wc.clsHIcon], eax
push L IDC_ARROW
push L 0
call LoadCursor
mov [wc.clsHCursor], eax
mov [wc.clsHbrBackground], COLOR_WINDOW + 1
mov dword ptr [wc.clsLpszMenuName], 0
mov dword ptr [wc.clsLpszClassName], offset szClassName
push offset wc
call RegisterClass
push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push L 0 ; описатель родительского окна
push L CW_USEDEFAULT ; высота окна
push L CW_USEDEFAULT ; ширина окна
push L CW_USEDEFAULT ; координата y окна
push L CW_USEDEFAULT ; координата x окна
push L WS_OVERLAPPEDWINDOW ; стиль окна
push offset szTitleName ; строка заголовка окна
push offset szClassName ; имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx
mov [newhwnd], eax
push L SW_SHOWNORMAL ;режим показа окна на экране –
;нормальный.
;;;;;;;;;;;;;;;;;;;;;;;;
; создание 10 кнопок
;;;;;;;;;;;;;;;;;;;; кнопка1
push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push [newhwnd] ; описатель родительского окна
push 20 ;L CW_USEDEFAULT высота окна
push 100 ;L CW_USEDEFAULT ширина окна
push 60 ;L CW_USEDEFAULT координата y окна
push 580 ;L CW_USEDEFAULT координата x окна
push L WS_VISIBLE+WS_CHILDWINDOW;+BS_DEFPUSHBUTTON стиль окна
push offset _button_tit1;szTitleName строка заголовка окна
push offset _button ; szClassName имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx
mov [bh1], eax
;
;;;;;;;;;;;;;;;;;;;; кнопка2
push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push [newhwnd] ; описатель родительского окна
push 20 ;L CW_USEDEFAULT высота окна
push 100 ;L CW_USEDEFAULT ширина окна
push 80 ;L CW_USEDEFAULT координата y окна
push 580 ;L CW_USEDEFAULT координата x окна
push L WS_VISIBLE+WS_CHILDWINDOW;+BS_DEFPUSHBUTTON стиль окна
push offset _button_tit2;szTitleName строка заголовка окна
push offset _button ; szClassName имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx
mov [bh2], eax
;
;;;;;;;;;;;;;;;;;;;; кнопка3
push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push [newhwnd] ; описатель родительского окна
push 20 ;L CW_USEDEFAULT высота окна
push 100 ;L CW_USEDEFAULT ширина окна
push 100 ;L CW_USEDEFAULT координата y окна
push 580 ;L CW_USEDEFAULT координата x окна
push L WS_VISIBLE+WS_CHILDWINDOW;+BS_DEFPUSHBUTTON стиль окна
push offset _button_tit3;szTitleName строка заголовка окна
push offset _button ; szClassName имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx
mov [bh3], eax
;;;;;;;;;;;;;;;;;;;; кнопка4
push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push [newhwnd] ; описатель родительского окна
push 20 ;L CW_USEDEFAULT высота окна
push 100 ;L CW_USEDEFAULT ширина окна
push 120 ;L CW_USEDEFAULT координата y окна
push 580 ;L CW_USEDEFAULT координата x окна
push L WS_VISIBLE+WS_CHILDWINDOW;+BS_DEFPUSHBUTTON стиль окна
push offset _button_tit4;szTitleName строка заголовка окна
push offset _button ; szClassName имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx
mov [bh4], eax
;;;;;;;;;;;;;;;;;;;; кнопка5
push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push [newhwnd] ; описатель родительского окна
push 20 ;L CW_USEDEFAULT высота окна
push 100 ;L CW_USEDEFAULT ширина окна
push 140 ;L CW_USEDEFAULT координата y окна
push 580 ;L CW_USEDEFAULT координата x окна
push L WS_VISIBLE+WS_CHILDWINDOW;+BS_DEFPUSHBUTTON стиль окна
push offset _button_tit5;szTitleName строка заголовка окна
push offset _button ; szClassName имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx
mov [bh5], eax
;;;;;;;;;;;;;;;;;;;; кнопка6
push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push [newhwnd] ; описатель родительского окна
push 20 ;L CW_USEDEFAULT высота окна
push 100 ;L CW_USEDEFAULT ширина окна
push 160 ;L CW_USEDEFAULT координата y окна
push 580 ;L CW_USEDEFAULT координата x окна
push L WS_VISIBLE+WS_CHILDWINDOW;+BS_DEFPUSHBUTTON стиль окна
push offset _button_tit6;szTitleName строка заголовка окна
push offset _button ; szClassName имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx
mov [bh6], eax
;;;;;;;;;;;;;;;;;;;; кнопка7
push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push [newhwnd] ; описатель родительского окна
push 20 ;L CW_USEDEFAULT высота окна
push 100 ;L CW_USEDEFAULT ширина окна
push 180 ;L CW_USEDEFAULT координата y окна
push 580 ;L CW_USEDEFAULT координата x окна
push L WS_VISIBLE+WS_CHILDWINDOW;+BS_DEFPUSHBUTTON стиль окна
push offset _button_tit7;szTitleName строка заголовка окна
push offset _button ; szClassName имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx
mov [bh7], eax
;;;;;;;;;;;;;;;;;;;; кнопка8
push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push [newhwnd] ; описатель родительского окна
push 20 ;L CW_USEDEFAULT высота окна
push 100 ;L CW_USEDEFAULT ширина окна
push 200 ;L CW_USEDEFAULT координата y окна
push 580 ;L CW_USEDEFAULT координата x окна
push L WS_VISIBLE+WS_CHILDWINDOW;+BS_DEFPUSHBUTTON стиль окна
push offset _button_tit8;szTitleName строка заголовка окна
push offset _button ; szClassName имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx
mov [bh8], eax
;;;;;;;;;;;;;;;;;;;; кнопка9
push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push [newhwnd] ; описатель родительского окна
push 20 ;L CW_USEDEFAULT высота окна
push 100 ;L CW_USEDEFAULT ширина окна
push 220 ;L CW_USEDEFAULT координата y окна
push 580 ;L CW_USEDEFAULT координата x окна
push L WS_VISIBLE+WS_CHILDWINDOW;+BS_DEFPUSHBUTTON стиль окна
push offset _button_tit9;szTitleName строка заголовка окна
push offset _button ; szClassName имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx
mov [bh9], eax
;;;;;;;;;;;;;;;;;;;; кнопка10
push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push [newhwnd] ; описатель родительского окна
push 20 ;L CW_USEDEFAULT высота окна
push 100 ;L CW_USEDEFAULT ширина окна
push 240 ;L CW_USEDEFAULT координата y окна
push 580 ;L CW_USEDEFAULT координата x окна
push L WS_VISIBLE+WS_CHILDWINDOW;+BS_DEFPUSHBUTTON стиль окна
push offset _button_tit10;szTitleName строка заголовка окна
push offset _button ; szClassName имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx
mov [bh10], eax
;
push [newhwnd] ;описатель окна, подлежащего показу на экране
call ShowWindow
push [newhwnd]
call UpdateWindow
msg_loop:
push L 0
push L 0
push L 0
push offset msg
call GetMessage
cmp ax, 0
je end_loop
push offset msg
call TranslateMessage
push offset msg
call DispatchMessage
jmp msg_loop
end_loop:
push [msg.msWPARAM]
call ExitProcess
WndProc proc uses ebx edi esi, hwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
LOCAL theDC:DWORD
cmp [wmsg], WM_DESTROY ;если - уничтожить окно?
je wmdestroy ;то перейти на уничтожение
cmp [wmsg], WM_RBUTTONDOWN ;нажата правая клавиша мы-ши?
je wmrbuttondown ;то перейти на обработку этого нажатия
cmp [wmsg], WM_SIZE ;изменен размер окна?
je wmsize
cmp [wmsg], WM_CREATE ;команда создать окно?
je wmcreate
cmp [wmsg], WM_LBUTTONDOWN ;нажата левая клавиша мыши?
je wmlbuttondown
cmp [wmsg], WM_PAINT ;это команда на перерисовку окна?
je wmpaint
cmp [wmsg], WM_GETMINMAXINFO ;минимизировать/
;максимизировать окно?
je wmgetminmaxinfo
jmp defwndproc ;иначе перейти на обработчик сообщений
;по-умолчанию
wmpaint:
push offset lppaint
push [hwnd]
call BeginPaint
mov [theDC], eax
mov eax, [mbx_count]
mov edi, offset s_num
call HexWrite32
push L MSG_L ;длина строки
push offset szPaint ;адрес строки для вывода
push L 5 ;координата Y где выводится строка
push L 5 ;координата X где выводится строка
push [theDC] ;контекст устройства, через которое идет вывод
call TextOut
push offset lppaint
push [hwnd]
call EndPaint

wmcreate:
mov eax, 0
jmp finish

defwndproc:
push [lparam]
push [wparam]
push [wmsg]
push [hwnd]
call DefWindowProc
jmp finish

wmdestroy:
push L 0
call PostQuitMessage
mov eax, 0
jmp finish

wmlbuttondown:
inc [mbx_count]
push L 0
push L 0
push [hwnd]
call InvalidateRect
mov eax, 0
jmp finish

wmrbuttondown: ;;;;;;;;;;;!!!!!!!!! обработка события нажатия правой мыши
;push L 0
; call MessageBeep
cmp ost,10 ; если счетчик = 10
jz delb10 ; то удаляем кнопку №10
cmp ost,9 ; если счетчик = 9
jz delb9 ; то удаляем кнопку №9
cmp ost,8 ; (далее аналогично)
jz delb8
cmp ost,7
jz delb7
cmp ost,6
jz delb6
cmp ost,5
jz delb5
cmp ost,4
jz delb4
cmp ost,3
jz delb3
cmp ost,2
jz delb2
cmp ost,1
jz delb1
jmp finish
delb10: push L SW_HIDE ; параметр = скрыть окно
push [bh10] ; хендлер кнопки в стек
jmp kud
delb9: push L SW_HIDE
push [bh9]
jmp kud
delb8: push L SW_HIDE
push [bh8]
jmp kud
delb7: push L SW_HIDE
push [bh7]
jmp kud
delb6: push L SW_HIDE
push [bh6]
jmp kud
delb5: push L SW_HIDE
push [bh5]
jmp kud
delb4: push L SW_HIDE
push [bh4]
jmp kud
delb3: push L SW_HIDE
push [bh3]
jmp kud
delb2: push L SW_HIDE
push [bh2]
jmp kud
delb1: push L SW_HIDE
push [bh1]
;
kud: call ShowWindow ; показать окно ( на самом деле = скрыть окно)
dec ost ; и декремировать счетчик ost
jmp finish
;
wmsize:
mov eax, 0
jmp finish

wmgetminmaxinfo:
mov ebx, [lparam] ; указатель на структуру minmaxinfo
mov [(MINMAXINFO ptr ebx).mintrackposition_x] , 350
mov [(MINMAXINFO ptr ebx).mintrackposition_y] , 60
mov eax, 0

finish:
ret
WndProc endp
HexWrite8 proc
mov ah, al ;это число дублируется в ah
and al, 0fh ;затем в al оставляют младшую тетраду числа
shr ah, 4 ;а в ah - старшую
or ax, 3030h ;кадый нибл дополняется единицами (преобразуется в
;символ)
xchg al, ah ;байты меняются местами (так отображается на экране)
cmp ah, 39h ;идет сравнение старшего байта с символом ‘9’
ja @@4 ;переход, если символ оказался выше 9
@@1:
cmp al, 39h ;идет сравнение младшего байта с символом ‘9’
ja @@3 ;переход, если символ оказался выше 9
@@2:
stosw ;слово из AX заносится по адресу ES:EDI
ret
@@3:
sub al, 30h ;у числа убираются биты, переводящие его в символ
add al, 'A' - 10 ;затем снова добавляются, переводя число в букву
jmp @@2
@@4:
sub ah, 30h ;у числа убираются биты, переводящие его в символ
add ah, 'A'-10 ;затем снова добавляются, переводя число в букву
jmp @@1
HexWrite8 endp
HexWrite16 proc
push ax
xchg al,ah
call HexWrite8
pop ax
call HexWrite8
ret
HexWrite16 endp
HexWrite32 proc
push eax
shr eax, 16
call HexWrite16
pop eax
call HexWrite16
ret
HexWrite32 endp
public WndProc
ends
end start

Обсуждение

давно
Посетитель
7438
7205
11.10.2017, 11:28
общий
это ответ
Здравствуйте, ter4nastya!
Держите код. Слегка оптимизировал...
[code lang=asm h=200].386
locals
jumps
.model flat,STDCALL
include win32.inc
L equ <LARGE>
Extrn BeginPaint:PROC ;начало блока перерисовки окна
Extrn CreateWindowExA:PROC ;создать окно
Extrn DefWindowProcA:PROC ;процедура обработки сообщений ;по-умолчанию
Extrn DispatchMessageA:PROC ;процедура передачи сообщения оконному обработчику сооб-щений
Extrn EndPaint:PROC ;завершение блока перерисовки ок-на
Extrn ExitProcess:PROC ;завершение программы
extrn FindWindowA:PROC ;поиск окна в ОС
extrn GetMessageA:PROC ;принять сообщение из системной ;очереди
extrn GetModuleHandleA:PROC ;получить описатель модуля
extrn GetStockObject:PROC ;получить описатель основного пера,
;кисти или шрифта
extrn InvalidateRect:PROC ;объявление недостоверности области
;пользователя в окне
extrn LoadCursorA:PROC ;загузить иконку курсора
extrn LoadIconA:PROC ;загрузить пиктограмму
extrn MessageBeep:PROC ;издать звуковой сигнал
extrn MessageBoxA:PROC ;выдать системное окно с сообщением
extrn PostQuitMessage:PROC ;послать сообщение о выходе из
;программы
extrn RegisterClassA:PROC ;регистрация класса окна
extrn ShowWindow:PROC ;показать окно на экране
extrn SetWindowPos:PROC ;изменяет размер, положение и поря-док окна
extrn TextOutA:PROC ;вывод текста в окно
extrn TranslateMessage:PROC ;обработка сообщений от клавиатуры
extrn UpdateWindow:PROC ;обновить окно
CreateWindowEx equ <CreateWindowExA>
DefWindowProc equ <DefWindowProcA>
DispatchMessage equ <DispatchMessageA>
FindWindow equ <FindWindowA>
GetMessage equ <GetMessageA>
GetModuleHandle equ <GetModuleHandleA>
LoadCursor equ <LoadCursorA>
LoadIcon equ <LoadIconA>
MessageBox equ <MessageBoxA>
RegisterClass equ <RegisterClassA>
TextOut equ <TextOutA>
.data
newhwnd dd 0 ;ячейку для хранения описателя (хэндела) нового окна.
mbx_count dd 0 ;ячейка - счетчик нажатий левой клавиши мыши.
hInst dd 0 ;ячейка для хранения системного указателя (хэндела)
;нашей программы.
szTitleName db 'Win32 Assembly Program' ;текст заголовка окна ;программы.
zero db 0 ;и его замыкающий ноль.
szAlternate db '(Secondary)',0 ;текст для изменения заголовка окна, ес-ли ;приложение запущено повторно.
szClassName db 'ASMCLASS32',0 ;придуманное нами имя класса окна,
;под которым будем регистрировать-ся.
szPaint db 'Left mouse button pressed:' ;текст сообщения
s_num db '00000000h --times',0 ;в окне программы
MSG_L EQU ($-offset szPaint)-1
;;;;;;;;;;;!!!!!!!!!! ЗАГОЛОВКИ ДЛЯ 10 КНОПОК
_button db 'button',0
_button_tit dd _button_tit1, _button_tit2, _button_tit3, _button_tit4, _button_tit5
dd _button_tit6, _button_tit7, _button_tit8, _button_tit9, _button_tit10
_button_tit1 db 'Button 1',0
_button_tit2 db 'Button 2',0
_button_tit3 db 'Button 3',0
_button_tit4 db 'Button 4',0
_button_tit5 db 'Button 5',0
_button_tit6 db 'Button 6',0
_button_tit7 db 'Button 7',0
_button_tit8 db 'Button 8',0
_button_tit9 db 'Button 9',0
_button_tit10 db 'Button 10',0
bhandle dd 10 dup (0) ; === хендлеры для 10 кнопок ===
;
.data?
lppaint PAINTSTRUCT <?> ;структура для перерисовки изображе-ния.
msg MSGSTRUCT <?> ;структура системного сообщения.
wc WNDCLASS <?> ;структура для регистрации окна.

;;;;;;;;;;;!!!!!!!!!!
.code
start:
push L 0 ;подготовим стэк к запуску процедуры
call GetModuleHandle ;выполним процедуру (результат в EAX)
mov [hInst], eax ;поместим полученный хэндел на ;подготовленное для него место
push L 0
push offset szClassName
call FindWindow
or eax,eax
jz reg_class
mov [zero], ' '

reg_class:
mov [wc.clsStyle], CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS
mov [wc.clsLpfnWndProc], offset WndProc
mov [wc.clsCbClsExtra], 0
mov [wc.clsCbWndExtra], 0
mov eax, [hInst]
mov [wc.clsHInstance], eax
push L IDI_APPLICATION
push L 0
call LoadIcon
mov [wc.clsHIcon], eax
push L IDC_ARROW
push L 0
call LoadCursor
mov [wc.clsHCursor], eax
mov [wc.clsHbrBackground], COLOR_WINDOW + 1
mov dword ptr [wc.clsLpszMenuName], 0
mov dword ptr [wc.clsLpszClassName], offset szClassName
push offset wc
call RegisterClass
push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push L 0 ; описатель родительского окна
push L CW_USEDEFAULT ; высота окна
push L CW_USEDEFAULT ; ширина окна
push L CW_USEDEFAULT ; координата y окна
push L CW_USEDEFAULT ; координата x окна
push L WS_OVERLAPPEDWINDOW ; стиль окна
push offset szTitleName ; строка заголовка окна
push offset szClassName ; имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx
mov [newhwnd], eax

;;;;;;;;;;;;;;;;;;;;;;;;
; создание 10 кнопок
mov ecx, 0
create_loop:
push ecx

push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push [newhwnd] ; описатель родительского окна
push 20 ;L CW_USEDEFAULT высота окна
push 100 ;L CW_USEDEFAULT ширина окна
mov eax, 30
mul ecx
add eax, 60
push eax ;координата y окна
push 580 ;L CW_USEDEFAULT координата x окна
push L WS_CHILDWINDOW;+BS_DEFPUSHBUTTON стиль окна
push _button_tit[ecx*4] ;строка заголовка окна
push offset _button ; szClassName имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx

pop ecx
mov bhandle[ecx*4], eax
inc ecx
cmp ecx, 10
jl create_loop
;
push L SW_SHOWNORMAL ;режим показа окна на экране – нормальный.
push [newhwnd] ;описатель окна, подлежащего показу на экране
call ShowWindow
push [newhwnd]
call UpdateWindow
msg_loop:
push L 0
push L 0
push L 0
push offset msg
call GetMessage
cmp ax, 0
je end_loop
push offset msg
call TranslateMessage
push offset msg
call DispatchMessage
jmp msg_loop
end_loop:
push [msg.msWPARAM]
call ExitProcess

WndProc proc uses ebx edi esi, hwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
LOCAL theDC:DWORD
cmp [wmsg], WM_DESTROY ;если - уничтожить окно?
je wmdestroy ;то перейти на уничтожение
cmp [wmsg], WM_RBUTTONDOWN ;нажата правая клавиша мы-ши?
je wmrbuttondown ;то перейти на обработку этого нажатия
cmp [wmsg], WM_SIZE ;изменен размер окна?
je wmsize
cmp [wmsg], WM_CREATE ;команда создать окно?
je wmcreate
cmp [wmsg], WM_LBUTTONDOWN ;нажата левая клавиша мыши?
je wmlbuttondown
cmp [wmsg], WM_PAINT ;это команда на перерисовку окна?
je wmpaint
cmp [wmsg], WM_GETMINMAXINFO ;минимизировать/максимизировать окно?
je wmgetminmaxinfo
jmp defwndproc ;иначе перейти на обработчик сообщений по-умолчанию

wmpaint:
push offset lppaint
push [hwnd]
call BeginPaint
mov [theDC], eax
mov eax, [mbx_count]
mov edi, offset s_num
call HexWrite32
push L MSG_L ;длина строки
push offset szPaint ;адрес строки для вывода
push L 5 ;координата Y где выводится строка
push L 5 ;координата X где выводится строка
push [theDC] ;контекст устройства, через которое идет вывод
call TextOut
push offset lppaint
push [hwnd]
call EndPaint

wmcreate:
mov eax, 0
jmp finish

defwndproc:
push [lparam]
push [wparam]
push [wmsg]
push [hwnd]
call DefWindowProc
jmp finish

wmdestroy:
push L 0
call PostQuitMessage
mov eax, 0
jmp finish

wmlbuttondown:
mov eax, [mbx_count]
cmp eax, 10
je wmlbuttondown_ret
push L SW_SHOW
push [bhandle + eax*4]
call ShowWindow

inc [mbx_count]
push L 0
push L 0
push [hwnd]
call InvalidateRect

wmlbuttondown_ret:
mov eax, 0
jmp finish

wmrbuttondown: ;;;;;;;;;;;!!!!!!!!! обработка события нажатия правой мыши
mov eax, [mbx_count]
cmp eax, 0
je wmlbuttondown_ret

dec eax
mov [mbx_count], eax
push L SW_HIDE
push [bhandle + eax*4]
call ShowWindow

push L 0
push L 0
push [hwnd]
call InvalidateRect

wmrbuttondown_ret:
mov eax, 0
jmp finish
;
wmsize:
mov eax, 0
jmp finish

wmgetminmaxinfo:
mov ebx, [lparam] ; указатель на структуру minmaxinfo
mov [(MINMAXINFO ptr ebx).mintrackposition_x] , 350
mov [(MINMAXINFO ptr ebx).mintrackposition_y] , 60
mov eax, 0

finish:
ret
WndProc endp

HexWrite8 proc
mov ah, al ;это число дублируется в ah
and al, 0fh ;затем в al оставляют младшую тетраду числа
shr ah, 4 ;а в ah - старшую
or ax, 3030h ;кадый нибл дополняется единицами (преобразуется в
;символ)
xchg al, ah ;байты меняются местами (так отображается на экране)
cmp ah, 39h ;идет сравнение старшего байта с символом ‘9’
ja @@4 ;переход, если символ оказался выше 9
@@1:
cmp al, 39h ;идет сравнение младшего байта с символом ‘9’
ja @@3 ;переход, если символ оказался выше 9
@@2:
stosw ;слово из AX заносится по адресу ES:EDI
ret
@@3:
sub al, 30h ;у числа убираются биты, переводящие его в символ
add al, 'A' - 10 ;затем снова добавляются, переводя число в букву
jmp @@2
@@4:
sub ah, 30h ;у числа убираются биты, переводящие его в символ
add ah, 'A'-10 ;затем снова добавляются, переводя число в букву
jmp @@1
HexWrite8 endp
HexWrite16 proc
push ax
xchg al,ah
call HexWrite8
pop ax
call HexWrite8
ret
HexWrite16 endp
HexWrite32 proc
push eax
shr eax, 16
call HexWrite16
pop eax
call HexWrite16
ret
HexWrite32 endp
public WndProc
ends
end start
[/code]
5
Игорь Витальевич, большое вам спасибо за то, что помогли мне. Вы очень меня выручили!
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401367
6
11.10.2017, 11:44
общий
11.10.2017, 11:44
Адресаты:
Игорь Витальевич, объясните пожалуйста, где в вашем коде находится расстояние между кнопками?
давно
Посетитель
7438
7205
11.10.2017, 11:56
общий
Адресаты:
Вот в этом цикле:
[code lang=asm] mov ecx, 0
create_loop:
push ecx

push L 0 ; параметры создания окна
push [hInst] ; описатель (хэндел) нашего приложения
push L 0 ; описатель оконного меню
push [newhwnd] ; описатель родительского окна
push 20 ;L CW_USEDEFAULT высота окна
push 100 ;L CW_USEDEFAULT ширина окна

mov eax, 30 ; шаг между кнопками = 20 (высота одной) + 10 (расстояние между кнопками)
mul ecx ;индекс кнопки 0-9
add eax, 60 :координата Y первой кнопки

push eax ;координата y окна
push 580 ;L CW_USEDEFAULT координата x окна
push L WS_CHILDWINDOW;+BS_DEFPUSHBUTTON стиль окна
push _button_tit[ecx*4] ;строка заголовка окна
push offset _button ; szClassName имя класса окна
push L 0 ; расширенный стиль окна
call CreateWindowEx

pop ecx
mov bhandle[ecx*4], eax
inc ecx
cmp ecx, 10
jl create_loop
[/code]
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа