
Файл hint.Asm
; файл HINT.ASM
.386P
; плоская модель
.MODEL FLAT, stdcall
include hint.inc
; директивы компоновщику для подключения библиотек
; для компоновщика LINK.EXE
includelib d:\masm32\lib\user32.lib
includelib d:\masm32\lib\kernel32.lib
includelib d:\masm32\lib\gdi32.lib
; сегмент данных
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
MSG MSGSTRUCT <?>
HINST DD 0 ; дескриптор приложения
PA DB "DIAL1",0
HIN DB "HINTW",0
XX DD ?
YY DD ?
;-------------------------------
R1 RECT <?> ; поле редактирования
R2 RECT <?> ; кнопка
R3 RECT <?> ; флажок
S SIZ <?>
PS PAINTSTR <?>
PT POINT <?>
; дескрипторы окон-подсказок, для первого и второго элемента
H1 DD 0 ; поле редактирования
H2 DD 0 ; кнопка
H3 DD 0 ; флажок
; строка-подсказка
HINTS DB 60 DUP (?)
; перечень подсказок
HINT1 DB "Подсказка – Редактирование строки",0
HINT2 DB "Подсказка – Кнопка выхода",0
HINT3 DB "Подсказка - флаг",0
; для временного хранения контекста устройства
DC DD ?
; счетчик
P1 DD ?
_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+10Н] ; 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
; здесь реакция на закрытие окна
; удалить таймер
L4:
PUSH 2 ; идентификатор таймера
PUSH DWORD PTR [EBP+08H]
CALL KillTimer@8
; закрыть диалог
PUSH 0
PUSH DWORD PTR [EBP+08H]
CALL EndDialog@8
JMP FINISH
L1:
CMP DWORD PTR [EBP+0CH], WM_INITDIALOG
JNE L2
; здесь начальная инициализация
; установить таймер
PUSH OFFSET TIMPROC
PUSH 500 ; интервал 0.5 с.
PUSH 2 ; идентификатор таймера
PUSH DWORD PTR [EBP+08H]
CALL SetTimer@16
JMP FINISH
L2:
CMP DWORD PTR [EBP+0CH],WM_COMMAND
JNE L3
; кнопка выхода?
CMP WORD PTR [EBP+10H],2
JNE L3
JMP L4
L3:
FINISH:
POP EDI
POP ESI
POP EBX
POP EBP
MOV EAX,0
RET 16
WNDPROC ENDP
;---------------------------------------------
; процедура таймера
; расположение параметров в стеке
; [EBP+014Н] ; LPARAM - промежуток запуска Windows
; [EBP+10Н] ; WAPARAM - идентификатор таймера
; [EBP+0CH] ; WM_TIMER
; [EBP+8] ; HWND
TIMPROC PROC
PUSH EBP
MOV EBP,ESP
; получить положение курсора
PUSH OFFSET PT
CALL GetCursorPos@4
; запомнить координаты
MOV EAX,PT.X
MOV XX,EAX
MOV EAX,PT.Y
MOV YY,EAX
; получить положение элементов
; окно редактирования
PUSH 1
PUSH DWORD PTR [EBP+08H]
CALL GetDlgItem@8
PUSH OFFSET R1
PUSH EAX
CALL GetWindowRect@8
; кнопка выхода
PUSH 2
PUSH DWORD PTR [EBP+08H]
CALL GetDlgItem@8
PUSH OFFSET R2
PUSH EAX
CALL GetWindowRect@8
; кнопка флажка
PUSH 3
PUSH DWORD PTR [EBP+08H]
CALL GetDlgItem@8
PUSH OFFSET R3
PUSH EAX
CALL GetWindowRect@8
; увеличить счетчик
INC P1
MOV ECX,XX
MOV EDX,YY
; проверка условий
; поле редактирования:
.IF H1==0 && P1>5
.IF EDX<=R1.B && EDX>=R1.T && ECX>=R1.L && ECX<=R1.R
; подготовить строку
PUSH OFFSET HINT1
PUSH OFFSET HINTS
CALL lstrcpyA@8
; создать диалоговое окно - подсказку
PUSH 0
PUSH OFFSET HINT
PUSH DWORD PTR [EBP+08H]
PUSH OFFSET HIN
PUSH [HINST]
CALL CreateDialogParamA@20
MOV H1,EAX
; установить фокус
PUSH DWORD PTR [EBP+08H]
CALL SetFocus@4
; обнулить счетчик
MOV P1,0
JMP _END
.ENDIF
.ENDIF
.IF H1!=0
.IF (EDX>R1.B || EDX<R1.T) || (ECX<R1.L || ECX>R1.R)
; удаление подсказки в связи с перемещением курсора
PUSH H1
CALL DestroyWindow@4
MOV H1,0
JMP _END
.ENDIF
.ENDIF
; кнопка:
.IF H2==0 && P1>5
.IF EDX<=R2.B && EDX>=R2.T && ECX>=R2.L && ECX<=R2.R
; подготовить строку
PUSH OFFSET HINT2
PUSH OFFSET HINTS
CALL lstrcpyA@8
; создать диалоговое окно - подсказку
PUSH 0
PUSH OFFSET HINT
PUSH DWORD PTR [EBP+08H]
PUSH OFFSET HIN
PUSH [HINST]
CALL CreateDialogParamA@20
MOV H2,EAX
; установить фокус
PUSH DWORD PTR [EBP+08H]
CALL SetFocus@4
; обнулить счетчик
MOV P1,0
JMP _END
.ENDIF
.ENDIF
.IF H2!=0
.IF (EDX>R2.B || EDX<R2.T) || (ECX<R2.L || ECX>R2.R)
;удаление подсказки в связи с перемещением курсора
PUSH H2
CALL DestroyWindow@4
MOV H2,0
JMP _END
.ENDIF
.ENDIF
; флажок:
.IF H3==0 && P1>5
.IF EDX<=R3.B && EDX>=R3.T && ECX>=R3.L && ECX<=R3.R
; подготовить строку
PUSH OFFSET HINT3
PUSH OFFSET HINTS
CALL lstrcpyA@8
; создать диалоговое окно - подсказку
PUSH 0
PUSH OFFSET HINT
PUSH DWORD PTR [EBP+08H]
PUSH OFFSET HIN
PUSH [HINST]
CALL CreateDialogParamA@20
MOV H3,EAX
; установить фокус
PUSH DWORD PTR [EBP+08H]
CALL SetFocus@4
; обнулить счетчик
MOV P1,0
JMP _END
.ENDIF
.ENDIF
.IF H3!=0
.IF (EDX>R3.B || EDX<R3.T) || (ECX<R3.L || ECX>R3.R)
;удаление подсказки в связи с перемещением курсора
PUSH H3
CALL DestroyWindow@4
MOV H3,0
JMP _END
.ENDIF
.ENDIF
; восстановить стек
_END:
POP EBP
RET 16
TIMPROC ENDP
; процедура окна всплывающей подсказки
HINT PROC
PUSH EBP
MOV EBP,ESP
CMP DWORD PTR [EBP+0CH],WM_INITDIALOG
JNE NO_INIT
; инициализация
; получить контекст
PUSH DWORD PTR [EBP+08H]
CALL GetDC@4
MOV DC,EAX
; получить длину строки
PUSH OFFSET HINTS
CALL lstrlenA@4
; получить длину и ширину строки
PUSH OFFSET S
PUSH EAX
PUSH OFFSET HINTS
PUSH DC
CALL GetTextExtentPoint32A@16
; установить положение и размер окна-подсказки
PUSH 0
PUSH S.Y
ADD S.X,2
PUSH S.X
SUB YY,20
PUSH YY
ADD XX,10
PUSH XX
PUSH DWORD PTR [EBP+08H]
CALL MoveWindow@24
; закрыть контекст
PUSH DC
PUSH DWORD PTR [EBP+08H]
CALL ReleaseDC@8
; установить таймер
PUSH 0
PUSH 6000 ; интервал 6 с.
PUSH 3 ; идентификатор таймера
PUSH DWORD PTR [EBP+08H]
CALL SetTimer@16
JMP FIN
NO_INIT:
CMP DWORD PTR [EBP+0CH],WM_PAINT
JNE NO_PAINT
; перерисовка окна
; получить контекст
PUSH OFFSET PS
PUSH DWORD PTR [EBP+08H]
CALL BeginPaint@8
MOV DC,EAX
; установить цвета фона и текста подсказки
PUSH RGBB
PUSH EAX
CALL SetBkColor@8
PUSH RGBT
PUSH DC
CALL SetTextColor@8
; вывести текст
PUSH OFFSET HINTS
CALL lstrlenA@4
PUSH EAX
PUSH OFFSET HINTS
PUSH 0
PUSH 0
PUSH DC
CALL TextOutA@20
; закрыть контекст
PUSH OFFSET PS
PUSH DWORD PTR [EBP+08H]
CALL EndPaint@8
JMP FIN
NO_PAINT:
CMP DWORD PTR [EBP+0CH],WM_TIMER
JNE FIN
; обработка события таймера
; удалить таймер и удалить диалоговое окно
; подсказка удаляется в связи с истечением срока 6 с.
PUSH 3
PUSH DWORD PTR [EBP+08H]
CALL KillTimer@8
PUSH DWORD PTR [EBP+08H]
CALL DestroyWindow@4
FIN:
POP EBP
RET 16
HINT ENDP
_TEXT ENDS
END START