Jump to content

Detecting direction of scroll wheel in RichEdit control


Go to solution Solved by Nine,

Recommended Posts

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

 

 

Link to post
Share on other sites
  • Solution
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.

Link to post
Share on other sites

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 ...

Link to post
Share on other sites
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.

Link to post
Share on other sites
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
Link to post
Share on other sites
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.

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

    No registered users viewing this page.

×
×
  • Create New...