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.

  Reveal hidden contents

 

  • Solution
Posted
  On 11/3/2022 at 11:56 AM, Nine said:

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

Expand  

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

  On 11/3/2022 at 12:06 PM, 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:

 

 

Expand  

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
  On 11/3/2022 at 2:26 PM, 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 ...

Expand  

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)
  On 11/3/2022 at 11:56 AM, Nine said:

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

Expand  

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

"I think you are searching a bug where there is no bug... don't listen to bad advice."

Posted
  On 11/3/2022 at 3:24 PM, 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

 

Expand  

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.

Posted

Glad we could help :)

If you don't mind, I'd like you to change the "solved by pixelsearch" to "solved by Nine", thanks !

"I think you are searching a bug where there is no bug... don't listen to bad advice."

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