WM_COMMAND = 273
INSTALL @lib$+"WINLIB5"
ON SYS : PROCa(@wparam%) : RETURN
a%=FN_button("on sys",300,50,100,30,100,0)
b%=FN_button("setproc",300,100,100,30,FN_setproc(PROCb),0)
c%=FN_button("setproc( )",300,150,100,30,FN_setproc(PROCc()),0)
REPEAT WAIT 0
UNTIL 0
DEF PROCa(w%): PRINT "on sys "; w%: ENDPROC
DEF PROCb: PRINT "setproc": ENDPROC
DEF PROCc(w%,l%): PRINT "setproc() ";w%,l%: ENDPROC
DEF FN_setproc(RETURN F%)
PRIVATE D%,T%,lp%
IF T% = 0 THEN
LOCAL L%, P%, W%, S%, U%, O%, wp%, code%, pass%, pr%
DIM code% NOTEND AND 2047, code% 2300, L% -1
SYS "GetWindowLong", @hwnd%, -4 TO O%
FOR pass% = 8 TO 10 STEP 2
P% = code%
[OPT pass%
.pr% DD 0
.wp% DD 0
.lp% DD 0
;REM proc addresses
]
P% = (P% + 2047) AND -2048
[OPT pass%
.U%
pop eax
push O%
push eax
jmp "CallWindowProc"
.S% ; subclass
mov eax,[esp+8] ; msg
cmp eax,WM_COMMAND
jnz U%
mov eax,[esp+12] ; wparam
and eax,&FFFFFF00
cmp eax,&0000FF00
jnz U%
mov eax,[esp+16] ; lparam
mov [lp%],eax
mov eax,[esp+12] ; wparam
mov [wp%],eax
not eax
and eax,&000000FF
jz U%
mov ebx,lp%
mov eax,[ebx+eax*4]
or eax,eax
jz U%
mov [pr%],eax
jnz T%
.W%
push 0
call "Sleep"
.T%
mov al,[@vdu%+205]
add al,8
cmp al,[@vdu%+206]
jz W%
call "csenter"
mov edx,[@vdu%-144]
mov dl,[@vdu%+205]
mov dword [edx+4],pr% ; to @msg%
mov dword [edx+260],!^PROC_@sys
add dl,8
mov [@vdu%+205],dl
call "csleave"
or byte [^@flags%+3],&20
ret 20
]
NEXT pass%
SYS "SetWindowLong", @hwnd%, -4, S%
ENDIF
D%+=1 : lp%!(D%*4)=F%
=NOTD%AND&FFFF
DEF PROC_@sys: IF ?!@msg%=&28 PROC(@msg%)(@msg%!4,@msg%!8) ELSE PROC(@msg%)
RETURN
SWP_NOMOVE = 2
SWP_NOZORDER = 4
WHITENESS = &FF0062
WM_SIZE = 5
WM_HSCROLL = &114
WM_VSCROLL = &115
WS_HSCROLL = &100000
WS_VSCROLL = &200000
CanvasX% = 800
CanvasY% = 800
WindowX% = 700
WindowY% = 700
IF WindowX%=0 THEN WindowX%=@vdu%!208
IF WindowY%=0 THEN WindowY%=@vdu%!212
IF CanvasX%=0 THEN CanvasX%=WindowX%
IF CanvasY%=0 THEN CanvasY%=WindowY%
SYS "SetWindowPos", @hwnd%, 0, 0, 0, WindowX%, WindowY%, SWP_NOMOVE + SWP_NOZORDER
DIM BITMAPINFOHEADER{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, \
\ Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, \
\ ClrUsed%, ClrImportant%}
DIM bmi{Header{} = BITMAPINFOHEADER{}}
bmi.Header.Size% = DIM(BITMAPINFOHEADER{})
bmi.Header.Width% = CanvasX%
bmi.Header.Height% = CanvasY%
bmi.Header.Planes.l& = 1
bmi.Header.BitCount.l& = 24
SYS "CreateDIBSection", @memhdc%, bmi{}, 0, ^Bits%, 0, 0 TO hbitmap%
IF hbitmap% = 0 ERROR 100, "Couldn't create DIBSection"
SYS "SelectObject", @memhdc%, hbitmap% TO oldhbm%
SYS "DeleteObject", oldhbm%
INSTALL @lib$+"EVENTLIB"
PROC_eventinit
PROC_eventregister(WM_SIZE, PROCmove())
PROC_eventregister(WM_HSCROLL, PROCmove())
PROC_eventregister(WM_VSCROLL, PROCmove())
REM SYS "GetWindowLong", @hwnd%, -16 TO ws%
REM SYS "SetWindowLong", @hwnd%, -16, ws% OR WS_HSCROLL OR WS_VSCROLL
VDU 23,22,WindowX%;WindowY%;8,16,16,128
ORIGIN 0,2*(@vdu%!212-CanvasY%)
VDU 24,0;0;CanvasX%*2-2;CanvasY%*2-2;
CLG
LINE 0,0,CanvasX%*2-2,CanvasY%*2-2
LINE 0,CanvasY%*2-2,CanvasX%*2-2,0
VDU 23,23,2;0;0;0;
OFF : VDU 5 : VDU 30
MOVE 0,CanvasY%*2-200
REPEAT
WAIT 10
cx% = RND(CanvasX%*2)
cy% = RND(CanvasY%*2)
cr% = RND(200)
GCOL RND(15)
CIRCLE FILL cx%, cy%, cr%
GCOL 0
CIRCLE cx%, cy%, cr%
GCOL 4,0
MOVE cx%-8*INTLOG(cr%)-8,cy%+16
IF cr% > 24 PRINT ;cr%;
PROC_eventpoll
PROCscroll(-1)
UNTIL FALSE
END
DEF PROCscroll(Y%)
PRIVATE S%
IF S% THEN ENDPROC
S%=TRUE
LOCAL rc{}
DIM rc{l%,t%,r%,b%}
SYS "GetRgnBox", @vdu.hr%, rc{}
SYS "ScrollDC", @memhdc%, 0, Y%, rc{}, 0, 0, 0
SYS "ScrollWindow", @hwnd%, 0, Y%, 0, 0
IF Y%<0 THEN
SYS "PatBlt", @memhdc%, 0, CanvasY%-ABS(Y%), CanvasX%, ABS(Y%), WHITENESS
ELSE
SYS "PatBlt", @memhdc%, 0, 0, CanvasX%, ABS(Y%), WHITENESS
ENDIF
REM PROCclr(Bits%,CanvasX%*ABS(Y%),255)
S%=FALSE
ENDPROC
DEF FNTAB(X%,Y%) : X% = X%*16 : Y% = 2*CanvasY%-Y%*24
= CHR$25+CHR$4+CHR$(X%)+CHR$(X%DIV256)+CHR$(Y%)+CHR$(Y%DIV256)
DEF PROCclr(B%,C%,A%) : REM b=start c=len a=value
PRIVATE E%
CASE bmi.Header.BitCount.l& OF
WHEN 24 : C%*=3
WHEN 32 : C%*=4
ENDCASE
IF E%=0 THEN
LOCAL F%,G%,H%,I%,L%
DIM E% 45 : L%=E%+45
FOR I%=8 TO 10 STEP 2
P%=E%
[OPT I%
mov edx,eax
shl edx,8
or eax,edx
mov edx,eax
shl edx,16
or eax,edx
mov edx,eax
.H%
mov al,cl
and al,3
jz G%
mov [ebx+ecx],dl
dec ecx
jmp short H%
.G%
mov eax,edx
mov edx,4
shr ecx,2
.F%
mov [ebx],eax
add ebx,edx
loop F%
ret
]
NEXT I%
ENDIF
CALL E%
ENDPROC
DEF PROCmove(msg%,wp%,lp%) : REM ENDPROC
REM PRINT msg%,wp%,lp%
PRIVATE sih{}, siv{}
LOCAL flag%
DIM sih{cbSize%, fMask%, nMin%, nMax%, nPage%, nPos%, nTrackPos%}
DIM siv{cbSize%, fMask%, nMin%, nMax%, nPage%, nPos%, nTrackPos%}
sih.cbSize% = DIM(sih{})
siv.cbSize% = DIM(siv{})
sih.fMask% = 7
siv.fMask% = 7
sih.nMax% = CanvasX%
siv.nMax% = CanvasY%
CASE msg% OF
WHEN WM_SIZE:
sih.nPage% = lp% AND &FFFF
siv.nPage% = lp% >>> 16
LOCAL rc{},xs%,ys%,xmax%,ymax%,flag%,sx%,sy%,hbar%,vbar%
DIM rc{l%,t%,r%,b%}
SYS "GetSystemMetrics", 0 TO xs% : xs%-=20 :REM screen
SYS "GetSystemMetrics", 1 TO ys% : ys%-=20
SYS "GetSystemMetrics", 2 TO sx% : REM scrollbar
SYS "GetSystemMetrics", 3 TO sy%
IF sih.nPage%<CanvasX% THEN hbar%=1 ELSE hbar%=0 : sih.nPage%=CanvasX%+1
IF siv.nPage%<CanvasY% THEN vbar%=1 ELSE vbar%=0 : siv.nPage%=CanvasY%+1
IF CanvasX%>xs% THEN xmax%=xs% ELSE xmax%=CanvasX%+vbar%*sx%
IF CanvasY%>ys% THEN ymax%=ys% ELSE ymax%=CanvasY%+hbar%*sy%
REM IF sih.nPage%=CanvasX% THEN ymax%=ymax%-sy% ELSE ymax%=ymax%+sy%
REM IF siv.nPage%=CanvasY% THEN xmax%=xmax%-sx% ELSE xmax%=xmax%+sx%
rc.r%=xmax% : rc.b%=ymax%
SYS "GetWindowLong", @hwnd%, -16 TO style%
SYS "AdjustWindowRect", rc{}, style%, 0 : REM menu or not ??? , taskbar ??????
xmax%=rc.r%-rc.l% : IF xmax%>xs% THEN xmax%=xs%
ymax%=rc.b%-rc.t% : IF ymax%>ys% THEN ymax%=ys%
SYS "GetWindowRect", @hwnd%, rc{}
rc.r%=rc.r%-rc.l%
rc.b%=rc.b%-rc.t%
IF rc.r% > xmax% THEN
WindowX%=xmax%+vbar%*sx%
flag%=1
ELSE
WindowX%=rc.r%+vbar%*sx%: REM no need to "setwindowpos" unless Y needs
ENDIF
IF rc.b% > ymax% THEN
WindowY%=ymax%+hbar%*sy%
flag%=1
ELSE
WindowY%=rc.b%+hbar%*sy%
ENDIF
IF INKEY(-1) THEN TRACE STEP ON
WHEN WM_HSCROLL:
CASE wp% AND &FFFF OF
WHEN 0: sih.nPos% -= 1
WHEN 1: sih.nPos% += 1
WHEN 2: sih.nPos% -= sih.nPage%
WHEN 3: sih.nPos% += sih.nPage%
WHEN 5: sih.nPos% = wp% >> 16
ENDCASE
WHEN WM_VSCROLL:
CASE wp% AND &FFFF OF
WHEN 0: siv.nPos% -= 1
WHEN 1: siv.nPos% += 1
WHEN 2: siv.nPos% -= siv.nPage%
WHEN 3: siv.nPos% += siv.nPage%
WHEN 5: siv.nPos% = wp% >> 16
ENDCASE
ENDCASE
IF sih.nPos% > sih.nMax%-sih.nPage% sih.nPos% = sih.nMax%-sih.nPage%
IF siv.nPos% > siv.nMax%-siv.nPage% siv.nPos% = siv.nMax%-siv.nPage%
IF sih.nPos% < sih.nMin% sih.nPos% = sih.nMin%
IF siv.nPos% < siv.nMin% siv.nPos% = siv.nMin%
SYS "SetScrollInfo", @hwnd%, 0, sih{}, 1
SYS "SetScrollInfo", @hwnd%, 1, siv{}, 1
@ox% = sih.nPos%
@oy% = siv.nPos%
SYS "InvalidateRect", @hwnd%, 0, 0
*REFRESH
IF flag% THEN SYS "SetWindowPos", @hwnd%, 0, 0, 0, WindowX%, WindowY%, SWP_NOMOVE + SWP_NOZORDER
ENDPROC