@pixelsearch
Found some time to make a simple example to wrap my head around the example you gave me
I managed to boil it down to the code below for testing. Gonna skip resizing the tumb and double clicks for this test, do you see any flaws in the test scrollbar I made?
The thing I did diffirently is how to handle the WM_COMMAND message to prevent it setting the tumb location twice while dragging the tumb:
if $Scrolling then Return $GUI_RUNDEFMSG
#include <GUIConstantsEx.au3>
#include <GuiRichEdit.au3>
#include <Misc.au3>
#include <SendMessage.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Local $s
For $i = 1 To 100
$s &= 'Line ' & $i & @crlf
Next
AutoItSetOption('MouseCoordMode', 2) ; 2 = relative coords to the client area of the active window
$Form = GUICreate('Form', 294, 432, 2034, 330)
$Text = GUICtrlCreateLabel(0, 0, 0, 200, 17)
$Edit = _GUICtrlRichEdit_Create($Form, $s, 120, 70, 100, 270, BitOR($es_multiline, $es_autovscroll, $es_nohidesel), 0)
_GUICtrlRichEdit_SetScrollPos($Edit, 0, 0)
$Bar = GUICtrlCreateLabel('', 70, 70, 40, 270, $SS_BLACKRECT)
$Tumb = GUICtrlCreateLabel('', 70, 70, 40, 80, $SS_GRAYRECT)
GUISetState(@SW_SHOW)
;-----------------------------------------------
$BarX = 70
$BarY = 70
$BarWidth = 40
$BarHeight = 270
$TumbX = 70
$TumbY = 70
$TumbHeight = 80
$TumbMax = $BarY + $BarHeight - $TumbHeight
$TumbPercent = 0
$EditHeight = 270
$LineFirst = 0
$LineLast = 0
$LineCount = 0
$LineVisible = 0
$LineTop = 0
$EditPercent = 0
$MouseY = 0
$Scrolling = False
;-----------------------------------------------
func MouseOnTumb()
local $MouseXY = MouseGetPos()
Return $MouseXY[0] >= $BarX and $MouseXY[0] <= $BarX + $BarWidth and $MouseXY[1] >= $BarY and $MouseXY[1] <= $BarY + $BarHeight
EndFunc
GUIRegisterMsg($WM_COMMAND, WM_COMMAND)
Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
if $Scrolling then Return $GUI_RUNDEFMSG
If $lParam = $Edit Then
If BitShift($wParam, 16) = $EN_UPDATE Then UpdateTumbPosition()
EndIf
Return $GUI_RUNDEFMSG
EndFunc
Func UpdateTumbPosition()
$LineFirst = _GUICtrlRichEdit_GetNumberOfFirstVisibleLine($Edit)
$LineLast = _GUICtrlRichEdit_GetLineNumberFromCharPos($Edit, _GUICtrlRichEdit_GetCharPosFromXY($Edit, 1, $EditHeight))
$LineCount = _GUICtrlRichEdit_GetLineCount($Edit)
$LinesVisible = $LineLast - $LineFirst + 1 ; count last visible line too (+1)
$MaxScroll = $LineCount - $LinesVisible
If $MaxScroll <= 0 Then
$EditPercent = 0
Else
$EditPercent = ($LineFirst - 1) / $MaxScroll
EndIf
GUICtrlSetData($text, $EditPercent)
$TumbY = $BarY + $EditPercent * ($BarHeight - $TumbHeight)
GUICtrlSetPos($Tumb, $TumbX, $TumbY)
EndFunc
Func UpdateEditPosition()
$MouseY = MouseGetPos(1)
$TumbY = $MouseY - $TumbHeight / 2
If $TumbY < $BarY Then $TumbY = $BarY
If $TumbY > $TumbMax Then $TumbY = $TumbMax
GUICtrlSetPos($Tumb, $TumbX, $TumbY)
$TumbPercent = ($TumbY - $BarY) / ($TumbMax - $BarY)
GUICtrlSetData($Text, $TumbPercent)
$LineFirst = _GUICtrlRichEdit_GetNumberOfFirstVisibleLine($Edit)
$LineLast = _GUICtrlRichEdit_GetLineNumberFromCharPos($Edit, _GUICtrlRichEdit_GetCharPosFromXY($Edit, 1, $EditHeight))
$LineCount = _GUICtrlRichEdit_GetLineCount($Edit)
$LinesVisible = $LineLast - $LineFirst
$LineTop = $TumbPercent * ($LineCount - $LinesVisible) + 1
_GUICtrlRichEdit_ScrollLines($Edit, $LineTop - $LineFirst)
EndFunc
;-----------------------------------------------
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
_GUICtrlRichEdit_Destroy($Edit)
GUIDelete($Form)
Exit
Case $gui_event_primarydown
if MouseOnTumb() then $Scrolling = True
Case $gui_event_mousemove
if $Scrolling then UpdateEditPosition()
Case $gui_event_primaryup
$Scrolling = False
EndSwitch
WEnd