Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты в разделе

Коцюрбенко Алексей aka Жерар
Статус: Мастер-Эксперт
Рейтинг: 89
∙ повысить рейтинг »
Evgen aka Chuma
Статус: 5-й класс
Рейтинг: 0
∙ повысить рейтинг »
quirck
Статус: 1-й класс
Рейтинг: 0
∙ повысить рейтинг »

∙ Assembler

Номер выпуска:1660
Дата выхода:16.10.2017, 07:15
Администратор рассылки:Лысков Игорь Витальевич (Старший модератор)
Подписчиков / экспертов:45 / 16
Вопросов / ответов:1 / 1

Консультация # 191459: Здравствуйте! У меня возникли сложности с таким вопросом: Помогите пожалуйста мне исправить этот код. Нужно чтобы программа выполняла вот такие действия: Внесите в текст программы изменения, чтобы в начальный момент запуска программы на экране кнопок никаких не было, а они стали бы по-очереди появляться при щелчках левой клавишей мыши...

Консультация # 191459:

Здравствуйте! У меня возникли сложности с таким вопросом:

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

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

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

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

Дата отправки: 11.10.2017, 07:06
Вопрос задал: ter4nastya (Посетитель)
Всего ответов: 1
Страница онлайн-консультации »


Консультирует Лысков Игорь Витальевич (Старший модератор):

Здравствуйте, ter4nastya!
Держите код. Слегка оптимизировал... smile

Код (Assembler) :: выделить код
.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

Консультировал: Лысков Игорь Витальевич (Старший модератор)
Дата отправки: 11.10.2017, 11:28

5
Игорь Витальевич, большое вам спасибо за то, что помогли мне. Вы очень меня выручили!
-----
Дата оценки: 12.10.2017, 06:15

Рейтинг ответа:

НЕ одобряю +1 одобряю!


Оценить выпуск | Задать вопрос экспертам

главная страница  |  стать участником  |  получить консультацию
техническая поддержка

Дорогой читатель!
Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались. Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора - для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение. Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал, который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом. Заходите - у нас интересно!
МЫ РАБОТАЕМ ДЛЯ ВАС!


В избранное