wolfbartels

Translate MWheel to {UP} and {DOWN}

13 posts in this topic

Hi,

is it possible in an .au3 to detect the movements of the mouse wheel and translate these to corresponding {UP}s and {DOWN}s for use in Send() ???

I use a script to extend control of an old fashioned 16-bit program. I want to implement text scrolling with the mousewheel, as actually scrolling can be done only by using {UP} and {DOWN} keys.

Thanks for any idea.

Share this post


Link to post
Share on other sites

You have to catch WM_MOUSEWHEEL notification messages. Haven't needed to do it myself, so I don't have a demo of it. You might search for that message to get more help though.

:idea:


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

wolfbartels,

Try these:

GUIRegisterMsg($WM_MOUSEWHEEL, "_WM_MOUSEWHEEL")
GUIRegisterMsg($WM_MOUSEHWHEEL, '_WM_MOUSEHWHEEL')

Func _WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn = $SB_LINEDOWN
    If BitShift($wParam, 16) > 0 Then $iDirn = $SB_LINEUP
    _SendMessage($hWnd, $WM_VSCROLL, $iDirn)
    
    Return $GUI_RUNDEFMSG

EndFunc   ;==>_WM_MOUSEWHEEL

Func _WM_MOUSEHWHEEL($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn = $SB_LINERIGHT
    If BitShift($wParam, 16) > 0 Then $iDirn = $SB_LINELEFT
    _SendMessage($hWnd, $WM_HSCROLL, $iDirn)
    
    Return $GUI_RUNDEFMSG

EndFunc   ;==>_WM_MOUSEHWHEEL

You will need to change the _SendMessage lines as they currently send the scroll commands to a scrollbar! :idea:

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

wolfbartels,

Try these:

GUIRegisterMsg($WM_MOUSEWHEEL, "_WM_MOUSEWHEEL")
GUIRegisterMsg($WM_MOUSEHWHEEL, '_WM_MOUSEHWHEEL')

Func _WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn = $SB_LINEDOWN
    If BitShift($wParam, 16) > 0 Then $iDirn = $SB_LINEUP
    _SendMessage($hWnd, $WM_VSCROLL, $iDirn)
    
    Return $GUI_RUNDEFMSG

EndFunc   ;==>_WM_MOUSEWHEEL

Func _WM_MOUSEHWHEEL($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn = $SB_LINERIGHT
    If BitShift($wParam, 16) > 0 Then $iDirn = $SB_LINELEFT
    _SendMessage($hWnd, $WM_HSCROLL, $iDirn)
    
    Return $GUI_RUNDEFMSG

EndFunc   ;==>_WM_MOUSEHWHEEL

You will need to change the _SendMessage lines as they currently send the scroll commands to a scrollbar! :idea:

M23

Hi Melba23,

That's looks interesting, although I do not understand how this technic works.

Could you please show me some simple code where this is used, so that I can try to understand it?

Thanks anyway, Wolf

Share this post


Link to post
Share on other sites

A demo:

#include <GuiConstants.au3>
#include <WindowsConstants.au3>

Global $iX = 0, $iY = 0, $hGUI, $idLabel
$hGUI = GUICreate("Test", 300, 300)
$idLabel = GUICtrlCreateLabel("$iX = 0; $iY = 0", 20, 20, 260, 20)
GUISetState()

GUIRegisterMsg($WM_MOUSEWHEEL, "_WM_MOUSEWHEEL")
GUIRegisterMsg($WM_MOUSEHWHEEL, '_WM_MOUSEHWHEEL')

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func _WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn = -1
    If BitShift($wParam, 16) > 0 Then $iDirn *= -1
    $iY += $iDirn
    ControlSetText($hGUI, "", $idLabel, "$iX = " & $iX & "; $iY = " & $iY)
    Return $GUI_RUNDEFMSG

EndFunc   ;==>_WM_MOUSEWHEEL

Func _WM_MOUSEHWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn = -1
    If BitShift($wParam, 16) > 0 Then $iDirn *= -1
    $iX += $iDirn
    ControlSetText($hGUI, "", $idLabel, "$iX = " & $iX & "; $iY = " & $iY)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_MOUSEHWHEEL

My mouse doesn't have the horizontal scroll on the mousewheel, so I couldn't test that part.

:idea:


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

Thanks PsaltyDS and Melba23,

it works fine, both ways, moving the mousewheel vertically or horizontally. Excellent.

Now I'll try to translate these movements in Send ( arrow keys ).

I want to teach mouse scrolling to an old Win95 parametric CAD program that knows only arrow keys.

Share this post


Link to post
Share on other sites

I have a CAD application (Win 3.1) which I improved using an AutoIt script to add some buttons. This works fine.

Now I want the content in the CAD window to scroll using the mousewheel.

I added the following code (thanks to Melba23 and PsaltyDS):

GUIRegisterMsg($WM_MOUSEWHEEL, "_WM_MOUSEWHEEL")

.........
Func _WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $lParam
    $hWnd = $hCAD ;                    <--  to force scrolling in CAD window!
    Local $iDirn = $SB_LINEDOWN
    If BitShift($wParam, 16) > 0 Then $iDirn = $SB_LINEUP
    _SendMessage($hWnd, $WM_VSCROLL, $iDirn)
    Return $GUI_RUNDEFMSG

EndFunc   ;==>_WM_MOUSEWHEEL

There is only one problem, the content of the application window ($hCAD) scrolles only if the CAD window is not active, as soon as the CAD window is active the mousewheel is dead. How this can be fixed?

Share this post


Link to post
Share on other sites

CAD window is not active, as soon as the CAD window is active the mousewheel is dead. How this can be fixed?

Put a ConsoleWrite(), MsgBox(), or something in that event function to see if it is being called then failing to scroll, or if it's not called at all while the CAD app is active.

:idea:


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

Hi PsaltyDS,

I followed your advice, the event function Func _WM_MOUSEWHEEL in NOT called when the CAD window is active. After clicking anywhere on a GUI created by AutoIt the CAD window becomes not active and the scrolling in this non active window works fine. I suppose the problem has to do with GUIRegisterMsg. How can I force this registration for the CAD window, using AutoIt?

Is there a way to detect the MsgID? Is it possible that the old fashioned CAD program supresses the event message?

Share this post


Link to post
Share on other sites

Ouch. I should have seen that coming. We registered mouse messages coming to AutoIt. You want to get ("hook") mouse messages going to an outside app. Similar to this example, using hook.dll.

:idea:


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Hi, i think the PsaltyDS mousewheel sample (thx for that) can be improve with mousewheel delta use.
I have add some tips too on code.

 

;Original Code
;PsaltyDS
;Post 5
;https://www.autoitscript.com/forum/topic/114220-translate-mwheel-to-up-and-down/

;My change use delta
;See : https://msdn.microsoft.com/en-us/library/windows/desktop/ms645617%28v=vs.85%29.aspx

#include <GuiConstants.au3>
#include <WindowsConstants.au3>

Global $iX = 0, $iY = 0, $hGUI, $idLabel
Global $iX2 = 0, $iY2 = 0
$hGUI = GUICreate("Test", 300, 300)
$idLabel = GUICtrlCreateLabel("Without delta : $iX = 0; $iY = 0", 20, 20, 260, 20)
$idLabel2 = GUICtrlCreateLabel("With delta      : $iX2 = 0; $iY2 = 0", 20, 40, 260, 20);<=====with delta use
GUISetState()

GUIRegisterMsg($WM_MOUSEWHEEL, "_WM_MOUSEWHEEL")
GUIRegisterMsg($WM_MOUSEHWHEEL, '_WM_MOUSEHWHEEL')

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func _WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)

    ;Original Code without delta
    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn = -1
    If BitShift($wParam, 16) > 0 Then $iDirn *= -1
    $iY += $iDirn
    ControlSetText($hGUI, "", $idLabel, "Without delta : $iX = " & $iX & "; $iY = " & $iY)

    ;My change with delta
    #forceref $hWnd, $iMsg, $lParam
    $iY2 += BitShift($wParam, 16) / 120
    ControlSetText($hGUI, "", $idLabel2, "With delta      : $iX2 = " & $iX2 & "; $iY2 = " & $iY2)

    ;ConsoleWrite
    ConsoleWrite(BitShift($wParam, 16) & " " & $iY & " " & $iY2 & @CRLF)
    ;BitShift($wParam, 16) can be 120 or on fast move wheel 240/360/480... (neg value for scroll down)

    ;the "code execution time" here need to be fast for dont miss mousewheel event
    ;sleep(1000);<=====u can comment/uncommand that for test

    ;if your code need more time (ms) u can do something like this :
    AdlibRegister("_WM_MOUSEWHEEL_Long", 300)

    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_MOUSEWHEEL

Func _WM_MOUSEWHEEL_Long()

    AdlibUnRegister("_WM_MOUSEWHEEL_Long")

    ;the "code execution time" here can be more long
    Msgbox(0,"Pause",$iY2);<=====u can comment/uncommand that for test

EndFunc   ;==>_WM_MOUSEWHEEL

Func _WM_MOUSEHWHEEL($hWnd, $iMsg, $wParam, $lParam)

    ;Original Code
    #forceref $hWnd, $iMsg, $lParam
    Local $iDirn = -1
    If BitShift($wParam, 16) > 0 Then $iDirn *= -1
    $iX += $iDirn
    ControlSetText($hGUI, "", $idLabel, "Without delta : $iX = " & $iX & "; $iY = " & $iY)

    ;My change with delta
    #forceref $hWnd, $iMsg, $lParam
    $iX2 += BitShift($wParam, 16) / 120
    ControlSetText($hGUI, "", $idLabel2, "With delta     : $iX2 = " & $iX2 & "; $iY2 = " & $iY2)

    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_MOUSEHWHEEL

Tell me if i'm wrong

Edited by Synapsee

Share this post


Link to post
Share on other sites

I think this has your answer: 

 

Cheers :)

 

1 person likes this

Share this post


Link to post
Share on other sites

The JRowe's post you quote don't use wheel delta. So i have transfrom it for use wheel delta and now both script run together return same result.
so my wheel delta use seems ok, one method have confirmed another. thx u mpower for remember me this hook dll method.

Jrowe code with wheel delta use :

#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

Global Const $MSLLHOOKSTRUCT = $tagPOINT & ";dword mouseData;dword flags;dword time;ulong_ptr dwExtraInfo"

Global $currentEvent[2]

Global $iLBUTTONDOWN = 0
Global $iRBUTTONDOWN = 0
Global $iMBUTTONDOWN = 0
Global $LRClickStatus = 0
Global $RLClickStatus = 0
Global $LRDrag = 0
Global $RLDrag = 0
Global $LMDrag = 0
Global $RMDrag = 0
Global $doubleClickTime = 400

#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1", 633, 447, 192, 124)
$Label1 = GUICtrlCreateLabel("Label1", 200, 8, 228, 49)
GUISetState(@SW_SHOW)

;Register callback
$hKey_Proc = DllCallbackRegister("_Mouse_Proc", "int", "int;ptr;ptr")
$hM_Module = DllCall("kernel32.dll", "hwnd", "GetModuleHandle", "ptr", 0)
$hM_Hook = DllCall("user32.dll", "hwnd", "SetWindowsHookEx", "int", $WH_MOUSE_LL, "ptr", DllCallbackGetPtr($hKey_Proc), "hwnd", $hM_Module[0], "dword", 0)

#EndRegion ### END Koda GUI section ###

$i = 0

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            OnAutoItExit()
            Exit

    EndSwitch
WEnd

Func _Mouse_Proc($nCode, $wParam, $lParam)

    Local $info, $mouseData, $time, $timeDiff
    If $nCode < 0 Then
        $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
                "int", $nCode, "ptr", $wParam, "ptr", $lParam)
        Return $ret[0]
    EndIf

    $info = DllStructCreate($MSLLHOOKSTRUCT, $lParam)
    $mouseData = DllStructGetData($info, 3)

    Select
        Case $wParam = $WM_MOUSEWHEEL
            If _WinAPI_HiWord($mouseData) > 0 Then
                ;Up
                ConsoleWrite("up " & $mouseData/7864320 & @crlf);<===== Delta count return
                $i = $i + $mouseData/7864320;<========================= delta use
                ;$i = $i + 1<========================================== no delta use
                ConsoleWrite($i & @CRLF);<============================= $i console return
                $currentEvent[0] = "WheelUp"
                $currentEvent[1] = $time
            Else
                ;Down
                $count = $mouseData - 4287102976
                if $count <> 0 Then
                    $count = - (($count / 7864320)-1)
                Else
                    $count = 1
                Endif
                ConsoleWrite("down " & $count & @crlf);<=============== Delta count return
                $i = $i - $count;<===================================== delta use
                ;$i = $i - 1<========================================== no delta use
                ConsoleWrite($i & @CRLF);<============================= $i console return
                $currentEvent[0] = "WheelDown"
                $currentEvent[1] = $time
            EndIf

    EndSelect
    GUICtrlSetData($Label1, $currentEvent[0] & @CRLF & $currentEvent[1])

    $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
            "int", $nCode, "ptr", $wParam, "ptr", $lParam)
    Return $ret[0]
EndFunc   ;==>_Mouse_Proc

Func OnAutoItExit()
    DllCall("user32.dll", "int", "UnhookWindowsHookEx", "hwnd", $hM_Hook[0])
    $hM_Hook[0] = 0
    DllCallbackFree($hKey_Proc)
    $hKey_Proc = 0
EndFunc   ;==>OnAutoItExit

 

Share this post


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