An updated snippet on something I've probably made countless times. I've seen a few questions about scroll bars over the recent months and have had a personal request for it.
Load a text file into a scrollable window frame. You can use the mouse wheel to scroll or drag the scroll bar. Press 'b' to toggle a line number border (much like the one in the DBP editor).
This will not account for lines of text that go beyond the width of the window. That's a more advanced topic beyond the scope of this demo. If anyone needs an example of that I can post something for that as well.
type _Props
x as integer
y as integer
width as integer
height as integer
lineHeight as integer
thumbPos as integer
thumbWidth as integer
thumbHeight as integer
linePointer as integer
viewport as integer
scrollContent as integer
endtype
Global window as _Props
window.x = 100 : `X-position of window
window.y = 100 : `Y-position of window
window.width = 400 : `Window's width (includes trackbar)
window.height = 300 : `Window's height
window.lineHeight = text height("X") : `If value is less than the text height, the lines will overlap
window.thumbPos = 0 : `Thumb's relative position to the window
window.thumbWidth = 16 : `Thumb's width
window.thumbHeight = 20 : `Thumb's height
window.viewport = window.height / window.lineHeight - 1 : `Number of visible lines at a time
rem create an array to store the text
dim lines$() as string
rem open file and add text to array
readme$ = "test.txt"
if file exist(readme$) = 1
open to read 1, readme$
while file end(1) = 0
add to stack lines$()
read string 1, lines$()
endwhile
close file 1
endif
rem The amount of content beyond the visible viewport
window.scrollContent = array count(lines$()) - window.viewport
sync on
do
cls
_MC = mouseclick()
REM ========= User control stuff ===================
if _MC = 1
thumbX = window.x + window.width - window.thumbWidth
thumbY = window.y + window.thumbPos
rem if mouse is within the bounds of the thumb
if mouseOver(thumbX, thumbY, thumbX+window.thumbWidth, thumbY+window.thumbHeight) = 1 and mFlag = 0
mFlag = 1
dragThumb = 1
rem prevents a visual issue where the thumb could appear to "jump" to the cursor when clicked
tempOffsetY = thumbY - mousey()
endif
rem if mouse is dragging the thumb
if dragThumb = 1
rem update thumb's relative position to the window
window.thumbPos = mousey() + tempOffsetY - window.y
if window.thumbPos < 0 then window.thumbPos = 0
if window.thumbPos > window.height-window.thumbHeight then window.thumbPos = window.height-window.thumbHeight
rem Put thumb's relative position in terms of 0 to 1.
rem 0 being the top of the scrollbar. 1 is scrolled to the very bottom
t# = window.thumbPos / (window.height-window.thumbHeight+0.0)
rem The line offset. The point within the array where the thumb has been scrolled to
window.linePointer = window.scrollContent * t#
endif
mFlag = 1
else
if _MC = 0
mFlag = 0
dragThumb = 0
endif
endif
rem Scroll the text using the mouse wheel
mz = mousez()
if mz <> oldMz
if mz < oldMz then inc window.thumbPos, 15
if mz > oldMz then dec window.thumbPos, 15
oldMz = mz
if window.thumbPos < 0 then window.thumbPos = 0
if window.thumbPos > window.height-window.thumbHeight then window.thumbPos = window.height-window.thumbHeight
t# = window.thumbPos / (window.height-window.thumbHeight+0.0)
window.linePointer = window.scrollContent * t#
endif
rem toggle line number border
if inkey$() = "b" and vkFlag = 0 then showBorder = 1-showBorder : vkFlag = 1
if inkey$() = "" then vkFlag = 0
REM ========= Visual stuff ===================
drawWindow(showBorder)
sync
loop
function mouseOver(x1, y1, x2, y2)
if mousex() > x1 and mousex() < x2 and mousey() > y1 and mousey() < y2 then exitfunction 1
endfunction 0
function drawWindow(showLineNumbers as boolean)
rem draw the window
ink rgb(255,255,255),0
box window.x, window.y, window.x+window.width, window.y+window.height
rem draw the track bar and thumb
ink rgb(200,200,200),0
trackX = window.x+window.width-window.thumbWidth
box trackX, window.y, trackX+window.thumbWidth, window.y+window.height
ink rgb(96,96,96),0
thumbY = window.y + window.thumbPos
box trackX, thumbY, trackX+window.thumbWidth, thumbY+window.thumbHeight
rem If showing line numbers, draw the margin's dotted-line border
if showLineNumbers = 1
w = len(str$(array count(lines$())))
borderWidth = len(str$(array count(lines$()))) * text width("X") + 4
ink rgb(0,130,132),0
for i = 0 to window.height-1
x = window.x + borderWidth
y = window.y + i
if y mod 2 = 0 then dot x, y
next i
else
borderWidth = 0
endif
rem This makes sure we stay within the array bounds
maxLine = min(window.linePointer+window.viewport, array count(lines$()))
rem display the lines
ink rgb(255,0,0), 0
j = 0
for i = window.linePointer to maxLine
y = window.y+(j*window.lineHeight)
inc j
ink 0, 0
text window.x+2+borderWidth, y, lines$(i)
if showLineNumbers = 1
ink rgb(0,130,132),0
text window.x+2, y, padNum$(i+1, w)
endif
next i
endfunction
REM This will return the number 'X' as a string
REM right-justified and padding with spaces to
REM equal the overall specified length.
function padNum$(x, length)
s$ = str$(x)
s$ = space$(length - len(s$)) + s$
endfunction s$
"You're not going crazy. You're going sane in a crazy world!" ~Tick