; _______________________________________________________________________________________
;| |
;| ..::FreshLib::.. Free, open source. Licensed under "Fresh artistic license." |
;|_______________________________________________________________________________________|
;
; Description: TScrollWindow object class
;
; Target OS: Any
;
; Dependencies:
;
; Notes: TScrollWindow is window that may have scrollers to scroll the client area.
;_________________________________________________________________________________________
module "TScrollWindow library"
ObjectClass ScrollWindow, \
Window, \
TScrollWindow.Create, \
0, \
TScrollWindow.Get, \
TScrollWindow.Set, \
TScrollWindow.ExecCmd, \
TScrollWindow.SysEventHandler
struct TScrollbar
.Max dd ?
.Page dd ?
.Pos dd ?
._Drag dd ?
ends
object TScrollWindow, TWindow
._HScroller TScrollbar
._VScroller TScrollbar
method .HScrollSet, .Pos, .Max, .Page ; only params >=0 are set. If<0 ignored.
method .VScrollSet, .Pos, .Max, .Page
endobj
ScrollBarWidth = 12
MinScrollBarWidth = 12
;_________________________________________________________________________________________
proc TScrollWindow.Create, .pobj
begin
; push eax
; mov eax, [.pobj]
;
; mov [eax+TScrollWindow._HScroller.Max], 255
; mov [eax+TScrollWindow._HScroller.Page], 1
; mov [eax+TScrollWindow._HScroller.Pos], 10
;
; mov [eax+TScrollWindow._VScroller.Max], 1000
; mov [eax+TScrollWindow._VScroller.Page], 1
; mov [eax+TScrollWindow._VScroller.Pos], 450
;
; pop eax
return
endp
;_________________________________________________________________________________________
proc TScrollWindow.Get, .pobj, .paramID
begin
stc
return
endp
;_________________________________________________________________________________________
proc TScrollWindow.Set, .pobj, .paramID, .value
begin
stc
return
endp
;_________________________________________________________________________________________
proc TScrollWindow.SysEventHandler, .pobj, .pEvent
.event TScrollEvent
begin
push eax ebx edx esi edi
mov esi, [.pobj]
mov ecx, [.pEvent]
cmp [ecx+TSysEvent.event], sePaint
je .paint
cmp [ecx+TSysEvent.event], seMouseBtnPress
je .btnpress
cmp [ecx+TSysEvent.event], seMouseBtnRelease
je .btnrelease
cmp [ecx+TSysEvent.event], seMouseMove
je .mousemove
.continue:
stc
.finish:
pop edi esi edx ebx eax
return
;.........................................................................................
.paint:
locals
.recth TBounds
.rectv TBounds
.rectx TBounds
endl
stdcall Get, esi, TScrollWindow.FreeArea
mov ebx, eax
mov eax, [ebx+TBounds.x]
mov edx, [ebx+TBounds.y]
mov [.recth.x], eax
mov [.rectv.y], edx
add eax, [ebx+TBounds.width]
add edx, [ebx+TBounds.height]
mov [.rectv.x], eax
mov [.recth.y], edx
inc edx
inc eax
mov [.rectx.y], edx
mov [.rectx.x], eax
mov [.recth.height], ScrollBarWidth
mov [.rectv.width], ScrollBarWidth
mov [.rectx.width], ScrollBarWidth-1
mov [.rectx.height], ScrollBarWidth-1
mov eax, [ebx+TBounds.width]
mov edx, [ebx+TBounds.height]
inc eax
inc edx
mov [.recth.width], eax
mov [.rectv.height], edx
lea eax, [.rectx]
stdcall [DrawBox], [ecx+TPaintEvent.context], eax, [clDialogBk], bxNone
lea eax, [.recth]
stdcall [DrawBox], [ecx+TPaintEvent.context], eax, [clScrollBk], bxSunken or bxNoFill
lea eax, [.rectv]
stdcall [DrawBox], [ecx+TPaintEvent.context], eax, [clScrollBk], bxSunken or bxNoFill
lea eax, [esi+TScrollWindow._HScroller]
stdcall _SliderPixels, eax, [.recth.width]
push esi
stdcall DrawFillRect, [ecx+TPaintEvent.context], [.recth.x], [.recth.y], eax, [.recth.height], [clScrollBk]
mov esi, [.recth.width]
sub esi, eax
sub esi, edx
add eax, [.recth.x]
lea edi, [eax+edx]
stdcall DrawFillRect, [ecx+TPaintEvent.context], edi, [.recth.y], esi, [.recth.height], [clScrollBk]
pop esi
mov [.rectx.x], eax
mov [.rectx.width], edx
push [.recth.y] [.recth.height]
pop [.rectx.height] [.rectx.y]
lea eax, [.rectx]
stdcall [DrawSlider], [ecx+TPaintEvent.context], eax, [clScrollSlider], sliderHorizontal
lea eax, [esi+TScrollWindow._VScroller]
stdcall _SliderPixels, eax, [.rectv.height]
push esi
stdcall DrawFillRect, [ecx+TPaintEvent.context], [.rectv.x], [.rectv.y], [.rectv.width], eax, [clScrollBk]
mov esi, [.rectv.height]
sub esi, eax
sub esi, edx
add eax, [.rectv.y]
lea edi, [eax+edx]
stdcall DrawFillRect, [ecx+TPaintEvent.context], [.rectv.x], edi, [.rectv.width], esi, [clScrollBk]
pop esi
mov [.rectx.y], eax
mov [.rectx.height], edx
push [.rectv.x] [.rectv.width]
pop [.rectx.width] [.rectx.x]
lea eax, [.rectx]
stdcall [DrawSlider], [ecx+TPaintEvent.context], eax, [clScrollSlider], sliderVertical
clc
jmp .finish
;.........................................................................................
.btnpress:
stdcall __ScrollSetCursor, esi, [ecx+TMouseButtonEvent.x], [ecx+TMouseButtonEvent.y]
cmp [ecx+TMouseButtonEvent.Button], mbLeft
jne .continue
stdcall _WhatScrollbar, esi, [ecx+TMouseButtonEvent.x], [ecx+TMouseButtonEvent.y]
jc .continue ; not found
; here ecx=height of the scrollbar
; edi= ptr to TScrollbar structure
; ebx= coordinate of the mouse in the scrollbar
stdcall _SliderPixels, edi, ecx
sub ebx, eax
jl .before
cmp ebx, edx
jg .after
; inside the slider - capture the mouse.
mov [edi+TScrollbar._Drag], ebx
stdcall MouseCapture, [esi+TWindow.handle]
jmp .continue
.before:
.after:
jmp .continue
;.........................................................................................
.btnrelease:
stdcall __ScrollSetCursor, esi, [ecx+TMouseButtonEvent.x], [ecx+TMouseButtonEvent.y]
xor eax, eax
mov [esi+TScrollWindow._HScroller._Drag], eax
mov [esi+TScrollWindow._VScroller._Drag], eax
stdcall MouseCapture, eax
jmp .continue
;.........................................................................................
.mousemove:
mov ecx, [.pEvent]
stdcall __ScrollSetCursor, esi, [ecx+TMouseMoveEvent.x], [ecx+TMouseMoveEvent.y]
mov ecx, [.pEvent]
lea edi, [esi+TScrollWindow._HScroller]
mov eax, [ecx+TMouseMoveEvent.x]
mov ecx, [esi+TScrollWindow._width]
mov [.event.ScrollBar], scrollX
cmp [edi+TScrollbar._Drag], 0
jne .found
mov ecx, [.pEvent]
lea edi, [esi+TScrollWindow._VScroller]
mov eax, [ecx+TMouseMoveEvent.y]
mov ecx, [esi+TScrollWindow._height]
mov [.event.ScrollBar], scrollY
cmp [edi+TScrollbar._Drag], 0
je .continue
.found:
mov [.event.event], seScroll
mov [.event.ScrollCmd], scTrack
sub ecx, ScrollBarWidth
sub eax, 2
sub eax, [edi+TScrollbar._Drag]
stdcall _SetSliderPos, edi, eax, ecx
jc .endmove
mov eax, [edi+TScrollbar.Pos]
mov [.event.Value], eax
lea eax, [.event]
stdcall ExecEvent, esi, eax
jnc .finish
; ?????? Do we need this?
; execute esi, TScrollWindow.Refresh
.endmove:
clc
jmp .finish
endp
;_________________________________________________________________________________________
proc TScrollWindow.ExecCmd, .self, .method
begin
cmp [.method], TScrollWindow._ComputeFreeArea
je .computefreearea
stc
return
.computefreearea:
mov ecx, [.self]
sub [ecx+TScrollWindow._FreeArea.width], ScrollBarWidth
jns @f
mov [ecx+TScrollWindow._FreeArea.width], 0
@@:
sub [ecx+TScrollWindow._FreeArea.height], ScrollBarWidth
jns @f
mov [ecx+TScrollWindow._FreeArea.height], 0
@@:
stc
return
endp
;_________________________________________________________________________________________
proc _SetSliderPos, .pScrollbar, .x, .lengthpx
begin
push eax ecx edx
mov ecx, [.pScrollbar]
stdcall _SliderPixels, [.pScrollbar], [.lengthpx]
sub [.lengthpx], edx
jz .zero
mov eax, [ecx+TScrollbar.Max]
imul [.x]
idiv [.lengthpx]
cmp eax, 0
jge .ok
mov eax, 0
.ok:
cmp eax, [ecx+TScrollbar.Max]
jle .ok2
mov eax, [ecx+TScrollbar.Max]
.ok2:
cmp [ecx+TScrollbar.Pos], eax
stc
je @f
clc
@@:
mov [ecx+TScrollbar.Pos], eax
pop edx ecx eax
return
.zero:
xor eax, eax
jmp .ok2
endp
; returns:
; eax - position in pixels
; edx - size in pixels
proc _SliderPixels, .pScrollbar, .length
begin
push ecx esi
mov ecx, [.pScrollbar]
; page size in pixels.
mov esi, [ecx+TScrollbar.Max]
mov eax, [.length]
add esi, [ecx+TScrollbar.Page]
test esi, esi
jz .lengthok
imul [ecx+TScrollbar.Page]
idiv esi
.lengthok:
cmp eax, MinScrollBarWidth
jge @f
mov eax, MinScrollBarWidth
@@:
cmp eax, [.length]
jle @f
mov eax, [.length]
@@:
push eax
; position in pixels
sub eax, [.length]
mov esi, [ecx+TScrollbar.Max]
test esi, esi
jnz @f
inc esi
@@:
neg eax
mul [ecx+TScrollbar.Pos]
div esi
pop edx ; width
pop esi ecx
return
endp
proc __ScrollSetCursor, .window, .x, .y
begin
pushad
mov esi, [.window]
mov eax, [esi+TWindow._cursor]
stdcall _WhatScrollbar, esi, [.x], [.y]
jc @f
mov eax, mcArrow
@@:
test eax, $ffffff00
jnz @f
stdcall GetStockCursor, eax
@@:
stdcall SetMouseCursor, eax
popad
return
endp
; returns:
; ecx = height of the scrollbar
; edi = ptr to TScrollbar structure
; ebx = coordinate of the mouse in the scrollbar
;
; CF=1 if the cursor is not in scrollbar
proc _WhatScrollbar, .window, .x, .y
begin
push eax edx esi
mov esi, [.window]
mov eax, [.x]
mov edx, [.y]
mov eax, [esi+TWindow._width]
mov edx, [esi+TWindow._height]
sub eax, ScrollBarWidth
sub edx, ScrollBarWidth
cmp [.x], eax
jl .checkh
cmp [.y], edx
jg .notfound ; we are in the dead square.
; mouse in vscrollbar
mov ebx, [.y]
mov ecx, edx
lea edi, [esi+TScrollWindow._VScroller]
jmp .found
.checkh:
cmp [.y], edx
jl .notfound ; in the client area
; mouse in hscrollbar
mov ebx, [.x]
mov ecx, eax
lea edi, [esi+TScrollWindow._HScroller]
.found:
clc
pop esi edx eax
return
.notfound:
stc
pop esi edx eax
return
endp
endmodule