wtorek, lipca 27, 2010

Plan lekcji - wersja hard ;-)

Swego czasu pisanie programów do wyświetlania planu lekcji czy zajęć to był mój odpowiednik hello world ;-) [to i całkowanie numeryczne ;-)].

Pamiętam, że używałem do tego paru języków, ale największym hardcorem była wersja w assemblerze skompilowana przy pomocy TASMa, dla Win16 i Win32 ;-)

Najważniejsza część programu zaczyna się od labelki obsluga101_107 [tak, wtedy pisałem jeszcze w kodzie po polsku, przestałem dopiero gdy zacząłem pracować w Motoroli ;-)].
Najpierw ustawiany jest nowy tytuł okienka, który odpowiada wybranemu dniowi tygodnia, a następnie otwierany jest plik nazwa_tygodnia.txt [który musi się chyba znajdować na dysku C:, ale głowy tu nie dam ;-)], którego zawartość jest wkładana do okienka prezentującego plan ;-)
Ciekawe może też być to co zaczyna się od labelki wmcreate, tam jest obsługa komunikatu WM_CREATE, który dostaje funkcja okna w momencie gdy system pragnie by okienko się stworzyło. Mamy tam najpierw 8 wywołań makra BUTTON, z parametrami takimi jak nazwa, koordynaty X i Y, wymiary (długość i wysokość) oraz numerem komunikatu podpiętego do guziczka :-) [dokładniej tego co chyba w wParam leci w momencie gdy obsługiwany jest komunikat WM_COMMAND].

locals
jumps
.model large, WINDOWS PASCAL
include windows.inc
include winmak.mak
.586p


extrn BEGINPAINT:PROC
extrn CREATEWINDOW:PROC
extrn DEFWINDOWPROC:PROC
extrn DISPATCHMESSAGE:PROC
extrn ENDPAINT:PROC
extrn GETMESSAGE:PROC
extrn GETSTOCKOBJECT:PROC
extrn INITAPP:PROC
extrn INITTASK:PROC
extrn INVALIDATERECT:PROC
extrn LOADCURSOR:PROC
extrn MESSAGEBEEP:PROC
extrn MESSAGEBOX:PROC
extrn POSTQUITMESSAGE:PROC
extrn REGISTERCLASS:PROC
extrn SHOWWINDOW:PROC
extrn TEXTOUT:PROC
extrn TRANSLATEMESSAGE:PROC
extrn UPDATEWINDOW:PROC
extrn WAITEVENT:PROC
extrn SETWINDOWTEXT:PROC
extrn GETWINDOWTEXT:PROC
extrn SENDMESSAGE:PROC
extrn GETDLGITEM:PROC
.data

db 16 dup (0)
psp dw ?
pszCmdline dw ?
hPrev dw ?
hInstance dw ?
cmdShow dw ?

newhwnd dw 0
lppaint PAINTSTRUCT <0>
msg MSGSTRUCT <0>
wc WNDCLASS <0>
mbx_count dw 0

szClassName db 'PLC',0
INCLUDE winconst.inc
szMon db 'Poniedziałek',0
szTue db 'Wtorek',0
szWed db 'Środa',0
szThu db 'Czwartek',0
szFri db 'Piątek',0
szSat db 'Sobota',0
szSun db 'Niedziela',0
szKoniec db 'Koniec',0
szBrakLekcji db 'Nie ma lekcji!!!',0
szPathName db 'd:\plan\'
szFileName db ' .txt',0
szTitleName db 'Plan lekcji - '
szDzien db 14 dup(0)
acDNI db '12345',0
hwndSTATIC dw 0
.code
.286
;-----------------------------------------------------------------------------
start:

mov ax, @data
mov ds, ax ; set up data segment

;Windows initialization. Sets up registers and stack.

;INITTASK returns:
; Failure:
; AX = zero if it failed
; Success:
; AX = 1
; CX = stack limit
; DX = cmdShow parameter to CreateWindow
; ES:BX = -> DOS format command line (ES = PSP address)
; SI = hPrevinstance
; DI = hinstance

call INITTASK
or ax,ax
jnz @@OK
jmp @@Fail
@@OK: mov [psp],es
mov word ptr [pszCmdline],bx
mov [hPrev],si
mov [hInstance],di
mov [cmdShow],dx

;Initialize the Windows App

xor ax,ax
push ax
call WAITEVENT
push [hInstance]
call INITAPP
or ax,ax
jnz @@InitOK

@@Fail:
mov ax, 4CFFh
int 21h ; terminate program


@@InitOK:
;-----------------------------------------------------------------------------
; This is generally where WinMain is called. We won't use a WinMain, since
; this app is 100% assembly.

cmp [hPrev], 0
jne already_running

; initialize the WndClass structure
mov [wc.clsStyle], CS_HREDRAW + CS_VREDRAW
mov word ptr [wc.clsLpfnWndProc], offset WndProc
mov word ptr [wc.clsLpfnWndProc+2], seg WndProc
mov [wc.clsCbClsExtra], 0
mov [wc.clsCbWndExtra], 0
mov ax, [hInstance]
mov [wc.clsHInstance], ax
mov [wc.clsHIcon], 0

push 0
push IDC_ARROW
call LOADCURSOR
mov [wc.clsHCursor], ax

push WHITE_BRUSH
call GETSTOCKOBJECT
mov [wc.clsHbrBackground], ax

mov word ptr [wc.clsLpszMenuName], 0
mov word ptr [wc.clsLpszMenuName+2], 0

mov word ptr [wc.clsLpszClassName], offset szClassName
mov word ptr [wc.clsLpszClassName+2], ds


push ds
push offset wc
call REGISTERCLASS

already_running:

push ds
push offset szClassName ; Class name
push ds
push offset szTitleName ; Title string
push WS_OVERLAPPEDWINDOW+WS_VISIBLE and WS_SYSMENU; high word of Style
push 0 ; low word of Style
push CW_USEDEFAULT ; x
push CW_USEDEFAULT ; y
push 400
push 220
push 0 ; parent hwnd
push 0 ; menu
push [hInstance] ; hInstance
push 0 ; lpParam
push 0 ; lpParam

call CREATEWINDOW

mov [newhwnd], ax

push [newhwnd]
push [cmdShow]
call SHOWWINDOW

push [newhwnd]
call UPDATEWINDOW

msg_loop:
push ds
push offset msg
push 0
push 0
push 0
call GETMESSAGE

cmp ax, 0
je end_loop

push ds
push offset msg
call TRANSLATEMESSAGE

push ds
push offset msg
call DISPATCHMESSAGE

jmp msg_loop

end_loop:
mov ax, [msg.msWPARAM]
mov ah, 4Ch
int 21h

;-----------------------------------------------------------------------------
WndProc proc hwnd:WORD, wmsg:WORD, wparam:WORD, lparam:DWORD

cmp [wmsg], WM_DESTROY
je wmdestroy
cmp [wmsg], WM_CREATE
je wmcreate
cmp [wmsg], WM_COMMAND
je wmcommand
; cmp [wmsg], WM_PAINT
; je wmpaint

jmp defwndproc


wmcreate:

BUTTON szMon,0,0,100,25,101
BUTTON szTue,0,25,100,25,102
BUTTON szWed,0,50,100,25,103
BUTTON szThu,0,75,100,25,104
BUTTON szFri,0,100,100,25,105
BUTTON szSat,0,125,100,25,106
BUTTON szSun,0,150,100,25,107
BUTTON szKoniec,0,175,100,25,108

STATIC '',0,112,12,200,200-12,-1
mov hwndSTATIC,ax

mov ah,2ah
int 21h
mov ah,0
cmp ax,0
jne dalej
mov ax,7
dalej: add ax,100
push [hwnd]
push WM_COMMAND
push ax
push 0
push 0

call SENDMESSAGE

mov ax, 0
jmp finish

wmcommand: cmp [wparam],108
je koniecprogramu
cmp [wparam],101
jge test107


jmp koncz

test107: cmp [wparam],107
jle obsluga101_107

koncz: mov ax,0
jmp finish


koniecprogramu:
push [hwnd]
push WM_CLOSE
push 0
push 0
push 0

CALL SENDMESSAGE

jmp koncz


obsluga101_107:
push [hwnd]
push [wparam]

call GETDLGITEM

push ax
push ds
push offset szDzien
push 13

call GETWINDOWTEXT

push [hwnd]
push ds
push offset szTitleName

call SETWINDOWTEXT

cmp [wparam],106
je niemalekcji
cmp [wparam],107
je niemalekcji


push es
push ds
pop es
mov di,offset szText
cld
mov cx,50
mov ax,0
rep stosw

pop es

mov bx,[wparam]
sub bx,101
mov ah,acDNI[bx]
mov bx,offset szFileName
mov BYTE PTR [bx],ah
mov ah,3dh
mov al,0
mov dx,offset szPathName
int 21h
mov bx,ax
mov ah,3fh
mov cx,1023
mov dx,offset szText
int 21h
mov ah,3eh
int 21h
push hwndSTATIC
push ds
push offset szText

CALL SETWINDOWTEXT

jmp koncz

niemalekcji:
push hwndSTATIC
push ds
push offset szBrakLekcji

CALL SETWINDOWTEXT

jmp koncz


defwndproc:
push hwnd
push wmsg
push wparam
push lparam
call DEFWINDOWPROC
jmp finish

wmdestroy:
push 0
call POSTQUITMESSAGE
mov ax, 0
jmp finish


finish:
mov dx, 0
ret
WndProc endp
;-----------------------------------------------------------------------------
szText db 100 dup(?)
public WndProc
ends
end start


No i czyż nie jest to wersja hard? ;-)

Niestety nigdzie na dysku nie mogę zlokalizować skompilowanej wersji tego programu. W ogóle wszystkie moje programy w assemblerze mam tylko w postaci źródeł :-( widać kiedyś starałem się zaoszczędzić trochę miejsca i pokasowałem EXEki :-(
Jakby ktoś chciał spróbować kompilacji to trzeba próbować z TASMem :-)

Obiecuję, że jeżeli dostanę konto do Google AppInventora for Android to postaram się zrobić i plan lekcji dla Androida ;p


Podobne postybeta
.asm - to było fajne rozszerzenie plików z programami ;-)
Manipulowanie statystyką
Celeron M353 900MHz vs. Intel Atom 1.6GHz, czyli o tym czemu jest remis? ;-)
Umiejętność programowania pomaga :-)
Go dla Java'owca ;-) odcinek 2 "kontenery dwa ;-)"