Jump to content

Detecting direction of scroll wheel in RichEdit control


Go to solution Solved by Nine,

Recommended Posts

Posted

Hello,

To make things short, for various reasons I'm using $WM_NOTIFY (I am aware of $WM_MOUSEWHEEL) to call the function and an event mask to detect multiple changes inside the edit control. However I am having trouble distinguishing scroll up and down. To me it seems like there's just no way to tell the difference between the two within the method that I'm using.

Spoiler
#include <GuiRichEdit.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

GUIRegisterMsg($WM_NOTIFY, 'TempFunc')

Local $hGUI = GUICreate('Test GUI', 200, 200, -1, -1)
Local $hRichEdit = _GUICtrlRichEdit_Create($hGUI, '', 20, 20, 160, 160, BitOR($ES_MULTILINE, $ES_AUTOVSCROLL), $WS_EX_TRANSPARENT) ;Yes $WS_VSCROLL is not enabled
_GUICtrlRichEdit_SetEventMask($hRichEdit, BitOR($ENM_LINK, $ENM_SCROLLEVENTS)) ;$ENM_SCROLLEVENTS - Sends EN_MSGFILTER notifications for mouse wheel events
For $i = 1 To 20
    _GUICtrlRichEdit_AppendText($hRichEdit, $i & ' - this is a test message' & @CRLF)
Next
GUISetState(@SW_SHOW, $hGUI)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GUICtrlRichEdit_Destroy($hRichEdit)
            GUIDelete($hGUI)
            Exit
    EndSwitch
    Sleep(10)
WEnd

Func TempFunc($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    ;Local $tEnLink = DllStructCreate($tagENLINK, $lParam)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $tMsgFilter = DllStructCreate($tagMSGFILTER, $lParam)
    Switch DllStructGetData($tNMHDR, 'hWndFrom')
        Case $hRichEdit
            Switch DllStructGetData($tNMHDR, 'Code')
                Case $EN_MSGFILTER
                    If DllStructGetData($tMsgFilter, 'msg') <> 0 Then
                        ConsoleWrite('Scroll ' & DllStructGetData($tMsgFilter, 'msg') & @CRLF)
                    EndIf
                Case $EN_LINK
                    If DllStructGetData($tMsgFilter, 'msg') = $WM_RBUTTONUP Then
                        ;Removed
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

 

 

  • Solution
Posted
42 minutes ago, Nine said:

The wParam member of the $tagMSGFILTER structure tells whether it is mouse wheel up or down (0 or 1).

I'm getting a 0 only from that parameter. Unless I'm missing a step, fairly new to WM commands.

33 minutes ago, Zedna said:
If $wParam > 0 Then
    $direction = 'up'
Else
    $direction = 'down'
EndIf

 

Note: Above code works when used in WM_MOUSEWHEEL message.

example of use here:

 

 

I've actually seen that topic before however the richedit control seems to intercept the scrolling message and it won't detect scrolling when hovering over it.

Posted

I meant something like this

#include <GuiRichEdit.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Local $hGUI = GUICreate('Test GUI', 200, 200, -1, -1)
Local $hRichEdit = _GUICtrlRichEdit_Create($hGUI, '', 20, 20, 160, 160, BitOR($ES_MULTILINE, $ES_AUTOVSCROLL), $WS_EX_TRANSPARENT) ;Yes $WS_VSCROLL is not enabled
;~ Local $hRichEdit = _GUICtrlRichEdit_Create($hGUI, '', 20, 20, 160, 160, BitOR($ES_MULTILINE, $ES_AUTOVSCROLL, $WS_VSCROLL), $WS_EX_TRANSPARENT) ;Yes $WS_VSCROLL is not enabled
_GUICtrlRichEdit_SetEventMask($hRichEdit, BitOR($ENM_LINK, $ENM_SCROLLEVENTS)) ;$ENM_SCROLLEVENTS - Sends EN_MSGFILTER notifications for mouse wheel events
For $i = 1 To 200
    _GUICtrlRichEdit_AppendText($hRichEdit, $i & ' - this is a test message' & @CRLF)
Next
GUISetState(@SW_SHOW, $hGUI)

GUIRegisterMsg($WM_NOTIFY, 'TempFunc')
GUIRegisterMsg($WM_MOUSEWHEEL, "MY_WM_MOUSEWHEEL")

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GUICtrlRichEdit_Destroy($hRichEdit)
            GUIDelete($hGUI)
            Exit
    EndSwitch
    Sleep(10)
WEnd

Func TempFunc($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    ;Local $tEnLink = DllStructCreate($tagENLINK, $lParam)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $tMsgFilter = DllStructCreate($tagMSGFILTER, $lParam)
    Switch DllStructGetData($tNMHDR, 'hWndFrom')
        Case $hRichEdit
            Switch DllStructGetData($tNMHDR, 'Code')
                Case $EN_MSGFILTER
                    If DllStructGetData($tMsgFilter, 'msg') <> 0 Then
                        ConsoleWrite('Scroll ' & DllStructGetData($tMsgFilter, 'msg') & @CRLF)
                    EndIf
                Case $EN_LINK
                    If DllStructGetData($tMsgFilter, 'msg') = $WM_RBUTTONUP Then
                        ;Removed
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

 Func MY_WM_MOUSEWHEEL($hWnd, $Msg, $wParam, $lParam)
;~  $Keys           = BitAnd($wParam, 0x0000FFFF)
    $nDistance      = BitShift($wParam, 16)

;~  If $wParam > 0 Then
    If $nDistance > 0 Then
        $direction = 'up'
    Else
        $direction = 'down'
    EndIf
     _GUICtrlRichEdit_AppendText($hRichEdit, 'WM_MOUSEWHEEL direction:' & $direction & @CRLF)
EndFunc

but it really seems that WM_MOUSEWHEEL event is not fired in this case ...

Posted
11 minutes ago, Zedna said:

I meant something like this

#include <GuiRichEdit.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Local $hGUI = GUICreate('Test GUI', 200, 200, -1, -1)
Local $hRichEdit = _GUICtrlRichEdit_Create($hGUI, '', 20, 20, 160, 160, BitOR($ES_MULTILINE, $ES_AUTOVSCROLL), $WS_EX_TRANSPARENT) ;Yes $WS_VSCROLL is not enabled
;~ Local $hRichEdit = _GUICtrlRichEdit_Create($hGUI, '', 20, 20, 160, 160, BitOR($ES_MULTILINE, $ES_AUTOVSCROLL, $WS_VSCROLL), $WS_EX_TRANSPARENT) ;Yes $WS_VSCROLL is not enabled
_GUICtrlRichEdit_SetEventMask($hRichEdit, BitOR($ENM_LINK, $ENM_SCROLLEVENTS)) ;$ENM_SCROLLEVENTS - Sends EN_MSGFILTER notifications for mouse wheel events
For $i = 1 To 200
    _GUICtrlRichEdit_AppendText($hRichEdit, $i & ' - this is a test message' & @CRLF)
Next
GUISetState(@SW_SHOW, $hGUI)

GUIRegisterMsg($WM_NOTIFY, 'TempFunc')
GUIRegisterMsg($WM_MOUSEWHEEL, "MY_WM_MOUSEWHEEL")

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GUICtrlRichEdit_Destroy($hRichEdit)
            GUIDelete($hGUI)
            Exit
    EndSwitch
    Sleep(10)
WEnd

Func TempFunc($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    ;Local $tEnLink = DllStructCreate($tagENLINK, $lParam)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $tMsgFilter = DllStructCreate($tagMSGFILTER, $lParam)
    Switch DllStructGetData($tNMHDR, 'hWndFrom')
        Case $hRichEdit
            Switch DllStructGetData($tNMHDR, 'Code')
                Case $EN_MSGFILTER
                    If DllStructGetData($tMsgFilter, 'msg') <> 0 Then
                        ConsoleWrite('Scroll ' & DllStructGetData($tMsgFilter, 'msg') & @CRLF)
                    EndIf
                Case $EN_LINK
                    If DllStructGetData($tMsgFilter, 'msg') = $WM_RBUTTONUP Then
                        ;Removed
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

 Func MY_WM_MOUSEWHEEL($hWnd, $Msg, $wParam, $lParam)
;~  $Keys           = BitAnd($wParam, 0x0000FFFF)
    $nDistance      = BitShift($wParam, 16)

;~  If $wParam > 0 Then
    If $nDistance > 0 Then
        $direction = 'up'
    Else
        $direction = 'down'
    EndIf
     _GUICtrlRichEdit_AppendText($hRichEdit, 'WM_MOUSEWHEEL direction:' & $direction & @CRLF)
EndFunc

but it really seems that WM_MOUSEWHEEL event is not fired in this case ...

Yeah that's what I've tried earlier. Seems to me like RichEdit has own messages (https://learn.microsoft.com/en-us/windows/win32/controls/rich-edit-control-event-mask-flags) it listens to and that's why I wanted to do it using WM_NOTIFY and event mask so I could have everything under single function for future.

Posted (edited)
3 hours ago, Nine said:

The wParam member of the $tagMSGFILTER structure tells whether it is mouse wheel up or down (0 or 1).

I got same result as Nine :

#include <GuiRichEdit.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Local $hGUI = GUICreate('Test GUI', 200, 200, -1, -1)
Local $hRichEdit = _GUICtrlRichEdit_Create($hGUI, '', 20, 20, 160, 160, BitOR($ES_MULTILINE, $ES_AUTOVSCROLL), $WS_EX_TRANSPARENT) ;Yes $WS_VSCROLL is not enabled
_GUICtrlRichEdit_SetEventMask($hRichEdit, $ENM_SCROLLEVENTS) ;$ENM_SCROLLEVENTS - Sends EN_MSGFILTER notifications for mouse wheel events
For $i = 1 To 20
    _GUICtrlRichEdit_AppendText($hRichEdit, $i & ' - this is a test message' & @CRLF)
Next

GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState(@SW_SHOW, $hGUI)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GUICtrlRichEdit_Destroy($hRichEdit)
            GUIDelete($hGUI)
            Exit
    EndSwitch
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam

    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    ; Local $tMsgFilter = DllStructCreate($tagMSGFILTER, $lParam)
    Switch DllStructGetData($tNMHDR, 'hWndFrom')
        Case $hRichEdit
            Switch DllStructGetData($tNMHDR, 'Code')
                Case $EN_MSGFILTER
                    Local Static $iCounter = 0
                    $iCounter += 1
                    ConsoleWrite("$EN_MSGFILTER " & $iCounter & @crlf)

                    ; reminder $tagMSGFILTER = "align 4;" & $tagNMHDR & ";uint msg;wparam wParam;lparam lParam"
                    Local $tMsgFilter = DllStructCreate($tagMSGFILTER, $lParam)
                    ConsoleWrite("$tMsgFilter.msg = " & $tMsgFilter.msg & "   $tMsgFilter.wparam = " & $tMsgFilter.wparam & _
                        "   $tMsgFilter.lparam = " & $tMsgFilter.lparam & @crlf)

                    If DllStructGetData($tMsgFilter, 'msg') <> 0 Then
                        ConsoleWrite('Scroll ' & DllStructGetData($tMsgFilter, 'msg') & @CRLF & @CRLF)
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Scite Console, after mousewheel scrolled down ($tMsgFilter.wparam = 1) then mousewheel scrolled up ($tMsgFilter.wparam = 0)

$EN_MSGFILTER 1
$tMsgFilter.msg = 277   $tMsgFilter.wparam = 1   $tMsgFilter.lparam = 0
Scroll 277

$EN_MSGFILTER 2
$tMsgFilter.msg = 277   $tMsgFilter.wparam = 0   $tMsgFilter.lparam = 0
Scroll 277

 

Edited by pixelsearch
nothing important
Posted
14 minutes ago, pixelsearch said:

I got same result as Nine :

-snip-

Scite Console, after mousewheel scrolled down ($wParam 1) then mousewheel scrolled up ($wParam 0)

$EN_MSGFILTER 1
$tMsgFilter.msg = 277   $tMsgFilter.wparam 1   $tMsgFilter.lparam 0
Scroll 277

$EN_MSGFILTER 2
$tMsgFilter.msg = 277   $tMsgFilter.wparam 0   $tMsgFilter.lparam 0
Scroll 277

 

Well now that I see this I could've called the parameter as a string. I was not aware that I could do that and what I had was: DllStructGetData($tMsgFilter, $wParam) instead of DllStructGetData($tMsgFilter, 'wParam').

Thanks to both of you.

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
  • Recently Browsing   0 members

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