Jump to content

Richedit horizontal scroll right arrow problem


Go to solution Solved by pixelsearch,

Recommended Posts

Thanks Mike for the info, it makes it clearer now.

Scrollbar-4.png

xyThumbTop reflects the left position of the thumb (for a horizontal scrollbar) at a certain moment, so it changes, depending on the position of the thumb. For example, in the pic above, here are the results I got at the moment the thumb is no more on the left side and _GUIScrollBars_GetScrollBarInfoEx() is called at this very moment :

dxyLineButton: 17
xyThumbTop...: 109
xyThumbBottom: 125

We see in the pic that 109 is correct (the thin black cross is placed exactly at X = 109, as shown in the mouse coords at the bottom of the pic. I moved the GUI at the very left side of the screen so the scrollbar starts at 0 when related to screen or GUI) . 125 is correct too for xyThumbBottom (checked) as the scroll thumb isn't large.

In the help file example, as the horizontal scrollbar is (unfortunately) placed at the very left, that's why we had xyThumbTop = dxyLineButton

I guess in your script you don't calculate the maximal scrollable position immediately after the RichEdit control creation (when it's still empty) but later, with a thumb that isn't positioned at the very left any more, that's why you can't use xyThumbTop

Using xyThumbTop in the formula seems ok only if the calculation is done immediately after the RichEdit control creation. If you calculate it later in the script, when the RichEdit control already contains text, then dxyLineButton is required in the formula.

Though dxyLineButton is "the height of the horizontal scrollbar thumb", it can also be seen as "the height or width of the scroll arrow" as the scroll arrow is a square, that's why it did fit in your formula : by substracting dxyLineButton, you substracted in fact... the width of the right scroll arrow :)
Link to comment
Share on other sites

hi pixelsearch,

so far the workaround for the (personal) right arrow bug works fine:

1) i use the slider an put it to the very right, right arrow is disabled.

2) from that position I click the left arow once, and the right arrow is enabled.

2) i use the right arrow click by click to move to the right works fine an at last click it is disabled.

But if i move to the right constantly holding the mouse button down on the right arrow it passes the max position for ever.
I think this is because the current position is not verified, when holding the mouse button constatly down.

This is a pitty and for the moment I did not get an idea, how to make this case also working.

BTW Is there an option to change the color of arrow from disabled to enabled?

Cheers mike

Link to comment
Share on other sites

After verification:

if right constantly holding the mouse button down on the right arrow the max scroll is recognized (arrow gets greyed)
but it keeps scrolling nevertheless cause the mousebutton is not lifted. If you lift it and push it down afterwards,
the disabling takes effect. That means asson as the position is arrived and recognized, there must be an action to stop the scrolling.

Sounds a bit complicate though.

Cheers mike

Link to comment
Share on other sites

A quick fix could be to prevent the "constantly holding the mouse button down on the right arrow" when the scrollable limit is reached, like this :

#include <Misc.au3>

...

If $iRightScrollThumb = $iMaxScrollHoriz Then
    _GUIScrollBars_EnableScrollBar($hRichEdit, $SB_HORZ, $ESB_DISABLE_RIGHT)
    While _IsPressed("01") ; left mouse button
    Wend
Else
    _GUIScrollBars_EnableScrollBar($hRichEdit, $SB_HORZ, $ESB_ENABLE_BOTH)
EndIf

Also, I found this to retrieve exactly the width of the horizontal scroll arrow, to substract in the formula :

#include <WinAPISys.au3>

...

$iWidthScrollArrow = _WinAPI_GetSystemMetrics($SM_CXHSCROLL) ; the width of the arrow bitmap on a horizontal scroll bar, in pixels.
ConsoleWrite("$iWidthScrollArrow = " & $iWidthScrollArrow & @crlf)

$tSCROLLBARINFO = _GUIScrollBars_GetScrollBarInfoEx($hRichEdit, $OBJID_HSCROLL)
; $iMaxScrollHoriz = $tSCROLLBARINFO.Right - $tSCROLLBARINFO.xyThumbTop - $tSCROLLBARINFO.Left
; $iMaxScrollHoriz = $tSCROLLBARINFO.Right - $tSCROLLBARINFO.dxyLineButton - $tSCROLLBARINFO.Left
$iMaxScrollHoriz = $tSCROLLBARINFO.Right - $iWidthScrollArrow - $tSCROLLBARINFO.Left
ConsoleWrite("$iMaxScrollHoriz = " & $iMaxScrollHoriz & @crlf & @crlf)

Link to comment
Share on other sites

hi pixelsearch,

prevent constantly holding mousebutton down works,
but it makes no difference between slider and right arrowbutton.

that means i cannot move the slider anymore.
i can click on the left arrow though and than move the slider if I'm off the max position.

tricky ...

cheers mike

Link to comment
Share on other sites

I managed it so far:

GUIRegisterMsg($WM_NOTIFY, "ON_WINDOW_EDIT_NOTIFY")

Func ON_WINDOW_EDIT_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    Local $hWndFrom, $iCode, $tMsgFilter, $tNMHDR

    #forceref $hWnd, $iMsg, $wParam

    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $hRichEdit
            Switch $iCode
                Case $EN_MSGFILTER
                    $tMsgFilter = DllStructCreate($tagMSGFILTER, $lParam)

                    Switch DllStructGetData($tMsgFilter, "msg")
                        Case $WM_HSCROLL
                            WindowEditHorizontalArrowWorkAround()

                            Return 0
                    EndSwitch
            EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>ON_WINDOW_EDIT_NOTIFY

Func WindowEditHorizontalArrowWorkAround()
    Local $aPos, $iPosCurrent, $iPosMax, $tSCROLLBARINFO

    $tSCROLLBARINFO = _GUIScrollBars_GetScrollBarInfoEx($hRichEdit, $OBJID_HSCROLL)
    $iPosMax = $tSCROLLBARINFO.Right - $tSCROLLBARINFO.dxyLineButton - $tSCROLLBARINFO.Left

    $iPosCurrent = _GUIScrollBars_GetScrollBarXYThumbBottom($hRichEdit, $OBJID_HSCROLL)

    If $iPosCurrent = $iPosMax Then
        _GUIScrollBars_EnableScrollBar($hRichEdit, $SB_HORZ, $ESB_DISABLE_RIGHT)

        $aPos = MouseGetPos()

        If $aPos[0] > $iPosMax Then
            MouseUp($MOUSE_CLICK_PRIMARY)
            MouseClick($MOUSE_CLICK_PRIMARY, $iPosMax - 1, $aPos[1])
        EndIf
    Else
        _GUIScrollBars_EnableScrollBar($hRichEdit, $SB_HORZ, $ESB_ENABLE_BOTH)
    EndIf
EndFunc   ;==>WindowEditHorizontalArrowWorkAround

Cheers mike

Edited by mike1950r
Link to comment
Share on other sites

The following line solved it for me (after having finally checked what was found in the $tagMSGFILTER structure)

Local $nScrollCode = _WinAPI_LoWord(DllStructGetData($tMsgFilter, "wParam")) ; yes !

Here is my final code, without any forced mouse click and the scroll box can be dragged fluently, even when the scroll right arrow is disabled :
#include <GUIConstantsEx.au3>
#include <GuiRichEdit.au3>
#include <GuiScrollBars.au3>
#include <Misc.au3>
#include <WinAPISys.au3>
#include <WindowsConstants.au3>

Global $SB_ENDSCROLL = 8 ; found this value in WinUser.h (not found in AutoIt constants)
Global $sText = "", $hGui, $hRichEdit

$hDll = DllOpen("user32.dll")

For $n = 2 To 100
    $sText &= $n & " - This is a single long line intended to cause a hoizontal scroll bar to appear in the RichEdit control." & @CRLF
Next
$hGui = GUICreate("Example (" & StringTrimRight(@ScriptName, 4) & ")", 320, 350, -1, -1)
$hRichEdit = _GUICtrlRichEdit_Create($hGui, $sText, 10, 10, 300, 220, BitOR($ES_MULTILINE, $WS_VSCROLL, $WS_HSCROLL))

; _GUICtrlRichEdit_SetEventMask($hRichEdit, $ENM_SCROLL) ; WM_COMMAND !
_GUICtrlRichEdit_SetEventMask($hRichEdit, $ENM_SCROLLEVENTS) ; WM_NOTIFY
; _GUICtrlRichEdit_SetEventMask($hRichEdit, BitOr($ENM_SCROLL, $ENM_SCROLLEVENTS)) ; WM_COMMAND & WM_NOTIFY

GUISetState(@SW_SHOW)

$iWidthScrollArrow = _WinAPI_GetSystemMetrics($SM_CXHSCROLL)
ConsoleWrite("$iWidthScrollArrow = " & $iWidthScrollArrow & @crlf)

$tSCROLLBARINFO = _GUIScrollBars_GetScrollBarInfoEx($hRichEdit, $OBJID_HSCROLL)
$iMaxScrollHoriz = $tSCROLLBARINFO.Right - $iWidthScrollArrow - $tSCROLLBARINFO.Left
ConsoleWrite("$iMaxScrollHoriz = " & $iMaxScrollHoriz & @crlf & @crlf)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
; GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

While True
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            DllClose($hDll)
            _GUICtrlRichEdit_Destroy($hRichEdit)
            Exit
    EndSwitch
WEnd

;=============================================
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lparam)
    Local $tNMHDR, $hWndFrom, $iCode
    $tNMHDR = DllStructCreate($tagNMHDR, $lparam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hRichEdit
            Switch $iCode
                Case $EN_MSGFILTER
                    Local $tMsgFilter = DllStructCreate($tagMSGFILTER, $lparam)
                    Switch DllStructGetData($tMsgFilter, "msg")
                        Case $WM_HSCROLL
                            Local Static $iCounter = 0
                            $iCounter += 1
                            ConsoleWrite($iCounter & " - ")

                            Local $nScrollCode = _WinAPI_LoWord(DllStructGetData($tMsgFilter, "wParam")) ; yes !
                            Switch $nScrollCode
                                Case $SB_LINELEFT ; user clicked left scroll arrow
                                    ConsoleWrite("left arrow" & @crlf)

                                Case $SB_LINERIGHT ; user clicked right scroll arrow
                                    ConsoleWrite("right arrow" & @crlf)

                                Case $SB_PAGELEFT ; user clicked the scroll bar shaft left of the scroll box
                                    ConsoleWrite("page left" & @crlf)

                                Case $SB_PAGERIGHT ; user clicked the scroll bar shaft right of the scroll box
                                    ConsoleWrite("page right" & @crlf)

                                Case $SB_THUMBTRACK ; user dragging the scroll box
                                    ConsoleWrite("scroll box (dragging)" & @crlf)

                                Case $SB_THUMBPOSITION ; user released the scroll box after dragging it
                                    ConsoleWrite("scroll box (released)" & @crlf)

                                Case $SB_ENDSCROLL ; user released the mouse after holding it on an arrow or in the scroll bar shaft.
                                    ConsoleWrite("mouse released" & @crlf)

                                Case Else
                                    ConsoleWrite("????? " & $nScrollCode & @crlf)
                            EndSwitch

                            Local $iRightScrollThumb = _GUIScrollBars_GetScrollBarXYThumbBottom($hRichEdit, $OBJID_HSCROLL)
                            ConsoleWrite("$iRightScrollThumb = " & $iRightScrollThumb & "   /   " & _
                                "$iMaxScrollHoriz = " & $iMaxScrollHoriz & @crlf & @crlf)

                            If $iRightScrollThumb = $iMaxScrollHoriz Then
                                _GUIScrollBars_EnableScrollBar($hRichEdit, $SB_HORZ, $ESB_DISABLE_RIGHT)

                                While _IsPressed("01", $hDll) And $nScrollCode = $SB_LINERIGHT ; left mouse button on scroll right arrow
                                Wend
                            Else
                                _GUIScrollBars_EnableScrollBar($hRichEdit, $SB_HORZ, $ESB_ENABLE_BOTH)
                            EndIf

                        Case $WM_VSCROLL
                            ; ...
                    EndSwitch
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

;==============================================
Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg
    Local $hWndFrom, $iCode
    $hWndFrom = $lParam
    $iCode = _WinAPI_HiWord($wParam)
    Switch $hWndFrom
        Case $hRichEdit
            Switch $iCode
                Case $EN_HSCROLL
                    ConsoleWrite("--- $EN_HSCROLL... in WM_COMMAND ---" & @crlf)
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND

Plenty of verbose lines in the code, but better more than less :D
Link to comment
Share on other sites

hi pixelsearch,

cannot get your script working in my program.

for $nScrollCode I'm always getting value $SB_LINELEFT ("left arrow") no matter where i click.

also waiting until mouse is not pressed on arrow right will not prevent that it keeps on scrolling over max.
this will only stop continue scrolling when you lift the mouse at max position.

While _IsPressed("01", $hDll) And $nScrollCode = $SB_LINERIGHT ; left mouse button on scroll right arrow
Wend

the $nScrollCode would be interesting for identifying left arrow, slider, or right arrow,
I identify right arrow with mouseposition over max while scrolling.

Anyway would be interested why $nScrollCode only ouputs one value here.

cheers mike

Link to comment
Share on other sites

Mike, you wrote : "cannot get your script working in my program"
But is my script running correctly when not in your program ?

For the record, when I run the script on my computer, here are some results displayed in the Console (without the empty lines separators, to make it shorter) :

$iWidthScrollArrow = 17
$iMaxScrollHoriz = 262

1 - page right
$iRightScrollThumb = 157   /   $iMaxScrollHoriz = 262
2 - mouse released
$iRightScrollThumb = 262   /   $iMaxScrollHoriz = 262
3 - page left
$iRightScrollThumb = 262   /   $iMaxScrollHoriz = 262
4 - mouse released
$iRightScrollThumb = 157   /   $iMaxScrollHoriz = 262
5 - left arrow
$iRightScrollThumb = 157   /   $iMaxScrollHoriz = 262
6 - mouse released
$iRightScrollThumb = 157   /   $iMaxScrollHoriz = 262
7 - right arrow
$iRightScrollThumb = 157   /   $iMaxScrollHoriz = 262
8 - mouse released
$iRightScrollThumb = 161   /   $iMaxScrollHoriz = 262
9 - page right
$iRightScrollThumb = 161   /   $iMaxScrollHoriz = 262
10 - mouse released
$iRightScrollThumb = 262   /   $iMaxScrollHoriz = 262
11 - scroll box (dragging)
$iRightScrollThumb = 262   /   $iMaxScrollHoriz = 262
12 - scroll box (dragging)
$iRightScrollThumb = 262   /   $iMaxScrollHoriz = 262
13 - scroll box (released)
$iRightScrollThumb = 262   /   $iMaxScrollHoriz = 262
14 - mouse released
$iRightScrollThumb = 261   /   $iMaxScrollHoriz = 262

Don't you get the same kind of output when you run the script, without including it in your program ?
Link to comment
Share on other sites

Yes, your animation shows it doesn't work on your computer. This is really strange as everything works fluently by my side (especially the horizontal scrollbar, dragging etc...) no matter the AutoIt version I use (3.3.16.1 or 3.3.14.5), I'm not sure this mystery will be easily solved.

Anyway, as you already got a working script (with the forced mouse clicks) then you'll probably use it. If anyone got an idea why the same script brings such different results on 2 computers...

I won't be here until tomorrow, so see you soon online.
Link to comment
Share on other sites

Hi,

I have improved the workaround function also for resizable richedit with relative mouse positions.

GUIRegisterMsg($WM_NOTIFY, "ON_WINDOW_EDIT_NOTIFY")

Func ON_WINDOW_EDIT_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    Local $hWndFrom, $iCode, $tMsgFilter, $tNMHDR

    #forceref $hWnd, $iMsg, $wParam

    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $hRichEdit
            Switch $iCode
                Case $EN_MSGFILTER
                    $tMsgFilter = DllStructCreate($tagMSGFILTER, $lParam)

                    Switch DllStructGetData($tMsgFilter, "msg")
                        Case $WM_HSCROLL
                            WindowEditHorizontalArrowWorkAround()

                            Return 0
                    EndSwitch
            EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>ON_WINDOW_EDIT_NOTIFY

Func WindowEditHorizontalArrowWorkAround()
    Local $aPosMouse, $iPosMouse, $iPosScrollCurrent, $iPosScrollMax, $iWidthScrollArrow, $tSCROLLBARINFO

    $iWidthScrollArrow = _WinAPI_GetSystemMetrics($SM_CXHSCROLL)

    $tSCROLLBARINFO = _GUIScrollBars_GetScrollBarInfoEx($hRichEdit, $OBJID_HSCROLL)
    $iPosScrollMax = $tSCROLLBARINFO.Right - $iWidthScrollArrow - $tSCROLLBARINFO.Left

    $iPosScrollCurrent = _GUIScrollBars_GetScrollBarXYThumbBottom($hRichEdit, $OBJID_HSCROLL)

    $aPosMouse = MouseGetPos()
    $iPosMouse = $aPosMouse[0] - $tSCROLLBARINFO.Left

    If $iPosScrollCurrent = $iPosScrollMax Then
        If $iPosMouse > $iPosScrollMax And _IsPressed("01") Then
            While _IsPressed("01")
            WEnd

            _WinAPI_ShowCursor(False)
            MouseClick($MOUSE_CLICK_LEFT, $aPosMouse[0] - $iWidthScrollArrow, $aPosMouse[1])
            MouseMove($aPosMouse[0], $aPosMouse[1], 1)
            _WinAPI_ShowCursor(True)
        EndIf
    EndIf
EndFunc   ;==>WindowEditHorizontalArrowWorkAround


The whole workaround works perfect for those who have this horizontal right arrow bug.

Cheers and thanks for all the help.

mike

Edited by mike1950r
Link to comment
Share on other sites

On 6/29/2023 at 11:39 AM, pixelsearch said:

Yes, your animation shows it doesn't work on your computer. This is really strange as everything works fluently by my side (especially the horizontal scrollbar, dragging etc...) no matter the AutoIt version I use (3.3.16.1 or 3.3.14.5), I'm not sure this mystery will be easily solved.

Anyway, as you already got a working script (with the forced mouse clicks) then you'll probably use it. If anyone got an idea why the same script brings such different results on 2 computers...

I won't be here until tomorrow, so see you soon online.

Hi pixelsearch,

this did not work cause of:

$nScrollCode = _WinAPI_LoWord(DllStructGetData($tMsgFilter, "wParam"))

This unfortunately did not bring a result, cause in richedit the scrollbars are automaticly created. There is not _GUIScrollBars_Init possible and $nScrollCode would only work with this when the scrollbars are manually created. So the identification of the right arrow in your script didn't work.

In my script this identification is done by mouse position.

On the other hand your idea of:

While _IsPressed("01")
 WEnd

works fine for stopping the scroll action.
I have taken it in my script above also with getting the arrow size:

$iWidthScrollArrow = _WinAPI_GetSystemMetrics($SM_CXHSCROLL)

After stopping the scroll action it would be necessary to scroll back this last step (one letter),
which i did with clicking on the slider, may be better solution to scroll back this step exist ...

Anyway thanks for your ideas,
it's doing it's job now, but one can only verify if he has this bug. 😀

Cheers mike

Link to comment
Share on other sites

Mike, just to let you know : I asked yesterday a good friend of mine (he's MVP here) if he could be kind enough to run my script on his W7 pro x64 computer, because you wrote in one of your posts "I'm on windows 7 pro 64bit."

His answer is : "Your script (pixelsearch) works very fine on my W7 pro x64, probably OP got something wrong in his Windows installation"
Link to comment
Share on other sites

Hi pixelsearch,

does your friend have the bug, like me?

If not, what should your script be a workaround for?
Ask you friend if he has the same problem like me in wordpad. (video)

If he has not this problem, he does not have the bug.
If he does not have the bug no need for a workaround.

May be I'm wrong, but I remember, that you also did not have this bug.

My question stiil is, does this work if you have not run _GUIScrollBars_Init before and have created the scrollbars?

$nScrollCode = _WinAPI_LoWord(DllStructGetData($tMsgFilter, "wParam"))

May be we misunderstood eachother?

Cheers mike

 

Animation.gif.d05837bfed50cd0a4df671559420eb4a.gif

Edited by mike1950r
Link to comment
Share on other sites

Sorry but I won't bother him with all this again.

I have the exact bug that you described in your initial post (and I'm using Windows XP) that's why I started this conversation, because I had the same bug, which is now totally solved on my computer with the script I provided. It is solved without the use of _GUIScrollBars_Init.

I don't know where you got the info that "nScrollCode would only works with this when the scrollbars are manually created" but I don't agreee : first, it works fine on my computer with standard scrollbars and second, msdn never indicates that it requires scrollbar controls (generated with _GUIScrollBars_Init) to retrieve all these infos.
Link to comment
Share on other sites

Ok pixelsearch,

thanks for the info.

It's good to know, that you have the same problem even if it's on XP.

so nScrollCode should work also on my system.
I must find out why it doesn't. It only was a guess, that _GUIScrollBars_Init was needed, cause I didn't find another reason yet.

There is one script from melba where i can get the nScrollCode values.
I attach it completely afterwards. But this is with generated scrollbars.

Cheers mike

Melba.au3

Edited by mike1950r
Link to comment
Share on other sites

Forget to say, that I get the nScrollCode only in Melba's complete script.
I do not get the nScrollCode if I only take following in my program.

GUIRegisterMsg($WM_HSCROLL, "_Scrollbars_WM_HSCROLL")

Func _Scrollbars_WM_HSCROLL($hWnd, $Msg, $wParam, $lParam)
    #forceref $Msg, $lParam
    Local $nScrollCode = BitAND($wParam, 0x0000FFFF)

    MsgBox($MB_SYSTEMMODAL, "Title", $nScrollCode)

    Switch $nScrollCode
        Case $SB_LINELEFT
           
        Case $SB_LINERIGHT
            
        Case $SB_PAGELEFT
           
        Case $SB_PAGERIGHT
           
        Case $SB_THUMBTRACK
           
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>_Scrollbars_WM_HSCROLL

Thanks for assistance.

Cheers mike

Edited by mike1950r
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...