;;Przykład 6.3. Aplikacja z wykorzystaniem informacji o zdarzeniach (program w języku asemblera MASM32)
.586P
.MODEL flat, STDCALL
;--- z pliku windows.inc ---
STD_INPUT_HANDLE                     equ -10
STD_OUTPUT_HANDLE                    equ -11

KEY_EVENT	EQU 1h ; zdarzenie klawiatury
MOUSE_EVENT	EQU 2h ; zdarzenie myszy
MENU_EVENT  EQU 8h
FOCUS_EVENT EQU 10h

RIGHT_ALT_PRESSED	EQU	1h ; Alt prawy
LEFT_ALT_PRESSED	EQU	2h ; Alt lewy
RIGHT_CTRL_PRESSED	EQU	4h ; Ctrl prawy
LEFT_CTRL_PRESSED	EQU	8h ; Ctrl lewy
SHIFT_PRESSED		EQU	10h ; Shift naciśnięty 
NUMLOCK_ON			EQU	20h ; Num Lock włączony 
SCROLLLOCK_ON		EQU	40h ; Scroll Lock włączony 
CAPSLOCK_ON		EQU	80h ; Caps Lock włączony 
ENHANCED_KEY		EQU	100h ; klawisz jest zwolniony 
FROM_LEFT_1ST_BUTTON_PRESSED	EQU	1h ; przycisk lewy
RIGHTMOST_BUTTON_PRESSED	EQU	2h ; przycisk prawy
FROM_LEFT_2ND_BUTTON_PRESSED EQU 4h ; przycisk środkowy
FROM_LEFT_3ND_BUTTON_PRESSED EQU 8h ; przycisk trzeci z lewa
FROM_LEFT_4ND_BUTTON_PRESSED EQU 10h ;przycisk 4-ty z lewa 
MOUSE_MOVED	EQU	1h ; mysz przesuwa się 
DOUBLE_CLICK	EQU	2h ; podwójne klikniecie 
MOUSE_WHEELED	EQU	4h ; poruszenie kółkiem myszy  
;--- struktury z pliku windows.inc ----------
COORD	STRUCT
	X	DW	?
	Y	DW	?
COORD	ENDS
MOUSE_EVENT_RECORD STRUCT
  dwMousePosition   COORD <> ; współrzędne X, Y kursora myszy
  dwButtonState     DWORD ? ; znaczniki naciśnięcia przycisków myszy
  dwControlKeyState DWORD ? ; znaczniki naciśnięcia klawiszy sterujących
  dwEventFlags  DWORD ? ; znaczniki przesuwania i podwójnego kliknięcia myszą
MOUSE_EVENT_RECORD ENDS
KEY_EVENT_RECORD STRUCT
  bKeyDown      DWORD ? ;znacznik naciśnięcia któregokolwiek klawisza
  wRepeatCount  WORD ?  ; ilość powtórzeń kodu przy długim na-ciśnięciu
  wVirtualKeyCode   WORD ?	; wirtualny kod klawisza
  wVirtualScanCode  WORD ?	; scan-kod klawisza
  UNION
    UnicodeChar     WORD ?	; UNICODE kod klawisza
    AsciiChar       BYTE ?	; ASCII kod klawisza
  ENDS
  dwControlKeyState DWORD ? ;znaczniki klawiszy sterujących
KEY_EVENT_RECORD ENDS
WINDOW_BUFFER_SIZE_RECORD STRUCT
  dwSize  COORD <>
WINDOW_BUFFER_SIZE_RECORD ENDS
MENU_EVENT_RECORD STRUCT
  dwCommandId  DWORD      ?
MENU_EVENT_RECORD ENDS
FOCUS_EVENT_RECORD STRUCT
  bSetFocus  DWORD      ?
FOCUS_EVENT_RECORD ENDS
INPUT_RECORD STRUCT	;struktura z informacją o zdarzeniu
  EventType             WORD ? ; typ zdarzenia
  two_byte_alignment    WORD ? ; wyrównanie do granicy/4
  UNION
    KeyEvent                KEY_EVENT_RECORD            <>
    MouseEvent              MOUSE_EVENT_RECORD          <>
    WindowBufferSizeEvent   WINDOW_BUFFER_SIZE_RECORD   <>
    MenuEvent               MENU_EVENT_RECORD           <>
    FocusEvent              FOCUS_EVENT_RECORD          <>
  ENDS 
INPUT_RECORD ENDS 
;--- funkcje API Win32 z biblioteki  user32.lib ---
CharToOemA PROTO :DWORD,:DWORD
;--- funkcje API Win32 z biblioteki kernel32.lib -----------
GetStdHandle PROTO :DWORD
WriteConsoleA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
AllocConsole PROTO
FreeConsole PROTO
SetConsoleTitleA PROTO :DWORD
SetConsoleTextAttribute PROTO :DWORD, :DWORD
GetLargestConsoleWindowSize PROTO :DWORD
FillConsoleOutputAttribute PROTO :DWORD, :DWORD, :DWORD, \
                                 :COORD, :DWORD
SetConsoleCursorPosition PROTO :DWORD, :COORD
ReadConsoleInputA PROTO :DWORD,:DWORD,:DWORD,:DWORD
FlushConsoleInputBuffer PROTO :DWORD
WriteConsoleOutputCharacterA PROTO :DWORD, :DWORD, :DWORD, \
           :COORD, :DWORD
ExitProcess PROTO :DWORD
;--- biblioteki ---------
includelib .\lib\user32.lib
includelib .\lib\kernel32.lib
includelib .\lib\masm32.lib
;--- Kolory ----
kolor1 = 11111100b	; Kolory: BG_I,R,G,B,FG__I,R,G,B
kolor2 = 11111001b	; Kolory: BG_I,R,G,B,FG__I,R,G,B 
;--- sekcja danych ------
_DATA SEGMENT
 tytul	DB	"Przykład aplikacji konsolową",0
 ALIGN 4
 rtytul	DD	$ - tytul	;ilość znaków tablicy tytuł
 wiersz DB	"Zakończyć można klawiszem Esc lub "
        DB      "podwójnym naciśnięciem myszy",0Dh,0Ah,0
 ALIGN 4
 rwiersz	DD	$ - wiersz	;ilość znaków tablicy wiersz
 hout	DD	?	; deskryptor buforu wyjściowego
 hinp	DD	?	; deskryptor buforu wejściowego
 atryb	DD	kolor2
 YX	    COORD	<>
 nzdarz	DD	?	; ilość zdarzeń
 rout		DD	0 ;faktyczna ilość wyprowadzonych znaków
 rkom		DD	?	; ilość komórek konsoli
 rfakt	DD	?	; faktyczna ilość komórek konsoli
 zapis INPUT_RECORD <>
 symb DB 'A'
_DATA ENDS
;--- sekcja kodu ---------
_TEXT SEGMENT
start:
;--- tworzenie konsoli ---
 INVOKE	FreeConsole
 INVOKE	AllocConsole
;--- nagłówek okna ---
 INVOKE CharToOemA,OFFSET tytul,OFFSET tytul	\
       ; konwersja polskich znaków
 INVOKE SetConsoleTitleA,OFFSET tytul
;--- deskryptory buforów --- 
 INVOKE GetStdHandle, STD_OUTPUT_HANDLE
 mov	hout, EAX
 INVOKE GetStdHandle, STD_INPUT_HANDLE
 mov	hinp, EAX
;--- obliczenie rozmiaru buforu ekranu
 INVOKE GetLargestConsoleWindowSize,hout
 mov	YX, EAX
 movzx EAX, YX.X
 movzx EBX, YX.Y
 mul	EBX
 mov	rkom, EAX
;--- napełnienie komórek jednakowym atrybutem ---
 mov	YX.X, 0	
 mov	YX.Y, 0
 INVOKE FillConsoleOutputAttribute,hout,atryb,rkom, \
    COORD PTR [YX],OFFSET rfakt
;--- wyprowadzenie komunikatu informacyjnego ---
 INVOKE SetConsoleTextAttribute,hout,atryb	 
 INVOKE CharToOemA,OFFSET wiersz,OFFSET wiersz	\
      ; konwersja polskich znaków
 INVOKE WriteConsoleA,hout,OFFSET wiersz, rwiersz, \
         OFFSET rout,0	
;--- ustawienie kursora
 mov	YX.X, 0	
 mov	YX.Y, 1
 INVOKE SetConsoleCursorPosition,hout,COORD PTR [YX] \
      ;ustawienie pozycji kursora
;--- pętla
powt:
;--- odczyt komunikatu zdarzenia
 INVOKE FlushConsoleInputBuffer,hinp \
       ;czyszczenie kolejki komunikatów
 INVOKE ReadConsoleInputA,hinp,OFFSET zapis,1,OFFSET nzdarz \
       ; odczyt komunikatu zdarzenia
;--- sprawdzanie typu zdarzenia
 cmp	WORD PTR [zapis.EventType], MOUSE_EVENT
 je	mysz
 cmp	WORD PTR [zapis.EventType], KEY_EVENT
 je	klaw
 jmp	powt
;--- komunikat od myszy
mysz:
 cmp	(MOUSE_EVENT_RECORD \
      PTR [zapis.MouseEvent]).dwEventFlags, DOUBLE_CLICK
 je	kon		; na koniec programu
 cmp	(MOUSE_EVENT_RECORD \
   PTR [zapis.MouseEvent]).dwButtonState, \
                    FROM_LEFT_1ST_BUTTON_PRESSED
 jne	powt
;--- jest naciśnięty lewy klawisz myszy
 mov	EAX, (MOUSE_EVENT_RECORD \
   PTR [zapis.MouseEvent]).dwMousePosition \
                 ; współrzędne X,Y	
 mov	COORD PTR [YX], EAX	; współrzędne X,Y	
 INVOKE SetConsoleCursorPosition,hout,COORD PTR [YX] \
           ; ustawienie pozycji kursora
 jmp	powt
;--- komunikat od klawiatury ---
klaw:
 mov AL,(KEY_EVENT_RECORD PTR [zapis.KeyEvent]).ASCIIChar
 mov symb,AL
 cmp	AL, 01Bh	; porównanie z kodem Esc
 je	kon
 cmp	(KEY_EVENT_RECORD PTR [zapis.KeyEvent]).bKeyDown, 0	; po-równanie z zerem
 je	powt	;jeśli nie ma naciśnięcia
 INVOKE WriteConsoleOutputCharacterA,hout,OFFSET symb,1,COORD PTR [YX],rout ; wypisywanie znaku
 jmp	powt
;--- zamknięcie konsoli
kon:	
 INVOKE	FreeConsole
;----- wywołanie funkcji ExitProcess ---------
 INVOKE	ExitProcess,0
_TEXT	ENDS
END start
