AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Wheel button emulation script
Goto page 1, 2  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
The Iron Savior



Joined: 17 Aug 2005
Posts: 4

PostPosted: Wed Aug 17, 2005 12:35 am    Post subject: Wheel button emulation script Reply with quote

I suffer with SERIOUS RSI in both of my arms and hands. Using a mouse is the most painful thing I can think of these days. Lately I've been using different trackballs to see which ones I like best. The one that is most comfortable to me so far is the Logitech Marble Mouse. It's just beautiful, one light flick of my finger gets the cursor wherever I need it. It has precision, ease of manipulation, comfortable form, and best of all it can be used with either hand without too much trouble (I'm not ambidextrous, after all). This trackball has 4 buttons and NO SCROLL WHEEL! I was at a loss for words when I found out that the included software didn't have any way to compensate for this. I assumed that it would have some sort of function where I can click a button and then spin the ball to get that scrolling effect. Sigh... no such software was included.

I started scouring the internet for something useful and I came upon AHK, it looked like just the thing. Took me little time to grasp the language and I started banging out all kinds of crazy non-working code. Luckily, my experience from my previous career in software development (which was ended very early by RSI--I'm sure there's irony in there somewhere) kicked in and I got some code here for you all that I'm sure at least one of you can appreciate.

This script will make any mouse (sans wheel or otherwise) have access to a middle-click and scroll wheel function! If you use the default settings, the 3rd (perhaps more accurately the 4th since the scroll wheel is usually considered the 3rd) button on my trackball can be held down while I spin the ball foreward or back to generate WheelUp and WheelDown events. As an added bonus, I'm throwing in the middle-click for free. I always used the middle button for opening links in new tabs in Firefox. To generate a middle click event, just click the trigger key down and up without moving the mouse at all.

You Can't drag and drop with the middle click, but who drags and drops with the middle button anyway? Also, it doesn't work with joystick buttons as I have it here--Joystick buttons appearantly don't generate key-up events. As you can see in the code, I use KeyDown and KeyUp hotkeys to set a variable to the state of the key. I could have eliminated the KeyDown variable in favor of GetKeyState() within the Timer function, but I thought that might hit the system too hard. Anywho, it would be easy to drop KeyDown for GetKeyState(), if you needed to use a joystick.

Don't forget to configure it before using it. Your mouse may not have "XButton"s and you might prefer to use another key or combination of keys.

Here it is:
Code:
;;
;; Emulate_Scrolling_Middle_Button.ahk
;; Author: Erik Elmore <erik@ironsavior.net>
;; Version: 1.1 (Aug 16, 2005)
;;
;; Enables you to use any key with cursor movement
;; to emulate a scrolling middle button.  While
;; the TriggerKey is held down, you may move the
;; mouse cursor up and down to send scroll wheel
;; events.  If the cursor does not move by the
;; time the TriggerKey is released, then a middle
;; button click is generated.  I wrote this for my
;; 4-button Logitech Marble Mouse (trackball), 
;; which has no middle button or scroll wheel.
;;

;; Configuration

;#NoTrayIcon

;; Higher numbers mean less sensitivity
esmb_Threshold = 5

;; This key/Button activates scrolling
esmb_TriggerKey = XButton1

;; End of configuration

#Persistent
CoordMode, Mouse, Screen
Hotkey, %esmb_TriggerKey%, esmb_TriggerKeyDown
HotKey, %esmb_TriggerKey% Up, esmb_TriggerKeyUp
esmb_KeyDown = n
SetTimer, esmb_CheckForScrollEventAndExecute, 10
return

esmb_TriggerKeyDown:
esmb_Moved = n
esmb_FirstIteration = y
esmb_KeyDown = y
MouseGetPos,, esmb_OldY
return

esmb_TriggerKeyUp:
esmb_KeyDown = n
;; Send a middle-click if we did not scroll
if esmb_Moved = n
    MouseClick, Middle
return

esmb_CheckForScrollEventAndExecute:
if esmb_KeyDown = n
    return

MouseGetPos,, esmb_NewY
esmb_Distance := esmb_NewY - esmb_OldY
if esmb_Distance
    esmb_Moved = y

;; Do not send clicks on the first iteration
if esmb_FirstIteration = y
    esmb_FirstIteration = n
else if esmb_Distance > %esmb_Threshold%
{
    esmb_OldY := esmb_OldY + esmb_Threshold
    MouseClick, WheelDown
}
else if esmb_Distance < -%esmb_Threshold%
{
    esmb_OldY := esmb_OldY - esmb_Threshold
    MouseClick, WheelUp
}

return

It's my first script ever for AHK, so try to keep the criticism constructive. I'm sure I can use it.

Enjoy!

[Edit: added "esmb_" (emulate scrolling middle button) to all symbols so people can easily add this to existing scripts without namespace collisions.]


Last edited by The Iron Savior on Wed Aug 17, 2005 1:53 am; edited 3 times in total
Back to top
View user's profile Send private message
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10467

PostPosted: Wed Aug 17, 2005 1:19 am    Post subject: Reply with quote

Anything that reduces RSI during mousing is a great thing to have in the forum. Thanks for sharing this carefully crafted technique.
Back to top
View user's profile Send private message Send e-mail
toralf



Joined: 31 Jan 2005
Posts: 3842
Location: Bremen, Germany

PostPosted: Wed Aug 17, 2005 7:33 am    Post subject: Reply with quote

Nice work,

Here are my comments:
- instead of using y/n for the status vars, you could use ":=True" and ":= False" and then evaluate them with "If var" or "If not Var". But that is cosmetics.
- another cosmetic: If you would indent the script syntactically it would help to read the code. (have a look at the script Auto-Syntax-Tidy, if you do not want to do it manually)
- And at last: What happens when you finished scrowlling? Does the mouse move back to where it has been when started? A mouse with a scroll wheel doesn't move it's pointer when scrolling. So I suggest to get the mouse position at the start of scrolling and place it at the same position after scrolling. Just an idea.
_________________
Ciao
toralf
Back to top
View user's profile Send private message Send e-mail Visit poster's website
The Iron Savior



Joined: 17 Aug 2005
Posts: 4

PostPosted: Wed Aug 17, 2005 1:49 pm    Post subject: Reply with quote

I wasn't 100% sure on how AHK handled booleans but most of the code I saw used y and n. I have always prferred "If x" and "If not x", anyway. I'll redo this when I get off work. I may be wrong here, but I'm pretty sure I already indented the code syntatically. Some elaboration would be appreciated if I'm breaking some sort of AHK script conventions. I'm pretty irritated that I had to use the style of blocks like this:
Code:
if whatever
{
    ...
}
when I MUCH prefer this:
Code:
if whatever {
    ...
}

The really irritating part is AHK didn't raise any flags when I did my braces my own way and that style of blocking was causing all sorts of undefined flow of execution.

About returning the cursor to its original location. THIS script as it is presented here (v1.1) does not move the mouse back. I did have a version before posting that would try to keep the mouse in the same spot all the time and it worked well and it was even a feature that you could turn off and on. In the end, it didn't really add anything valuable and I didn't like the way it made my code look, so I just scrapped the whole idea.
Back to top
View user's profile Send private message
Chris
Site Admin


Joined: 02 Mar 2004
Posts: 10467

PostPosted: Wed Aug 17, 2005 4:31 pm    Post subject: Reply with quote

The Iron Savior wrote:
I MUCH prefer this:
Code:
if whatever {
    ...
}
That can't be supported for old-style IF statements due to ambiguity (because the "{" might be a literal part of the line itself). I'll look into supporting it for expressions such as if (x > 3) {.

Quote:
The really irritating part is AHK didn't raise any flags when I did my braces my own way
A script such as the following should produce the error "attempt to close a non-existent block":

if x = 3 {
msgbox
}
Back to top
View user's profile Send private message Send e-mail
The Iron Savior



Joined: 17 Aug 2005
Posts: 4

PostPosted: Wed Aug 17, 2005 5:14 pm    Post subject: Reply with quote

I'm sure I messed up all kinds of other stuff while trying to learn the syntax, it might not have been that, exactly. I had a real hard time for a few hours trying to wrap my brain around the syntax.
Back to top
View user's profile Send private message
dmitri926
Guest





PostPosted: Wed May 03, 2006 6:15 am    Post subject: is it possible... Reply with quote

is it possible to make this script work with scrolling horizontally as it is with scrolling vertically
Back to top
The Iron Savior



Joined: 17 Aug 2005
Posts: 4

PostPosted: Wed May 03, 2006 6:26 am    Post subject: Reply with quote

Quote:
is it possible to make this script work with scrolling horizontally as it is with scrolling vertically

Yes, very easily.
Back to top
View user's profile Send private message
dmitri926



Joined: 04 May 2006
Posts: 3

PostPosted: Thu May 04, 2006 5:02 am    Post subject: another trackball script Reply with quote

Hey I used your script for a bit and it was awsome but i personally had a few issues with it.

I think you should give this one a shot, I found it somewere and tinkered with it for a bit to my liking.

If you click the XButton1 it acts as a regular MButton click (just a click), this works in firefox for opening/closing tabs, scrolling (you click it again to stop scrolling, etc). In addition to that, you can PRESS&HOLD XButton1 and move the cursor vert or horz to scroll. This works not only in firefox, but everywhere else also, whereas, the MButton mostly works in firefox because it has it's own mechanism for handling mice.

And XButton2 = back button...

This is the script i modified: http://www.autohotkey.com/forum/viewtopic.php?t=5186

Also you would have to dl the images for the autoscroll icons: http://www.almondcroissant.com/Images.zip and place them in C:\mouse_images or wherever you want (just modify the script with new location)

Code:

DetectHiddenWindows, On
CoordMode, Mouse, Screen

;// AutoScroll: Root Directory for images
as_imageroot = C:\mouse_images

;// AutoScroll: One acceleration notch in pixels
as_notch = 20

;// Bind Middle Mouse Button to AutoScroll
$XButton1::GoSub, MouseButtonHandler
XButton2::Send, {BROWSER_BACK}


;// Mouse Button Handler Function.
;// Any windows that you don't want AutoScroll to function in
;// can be filtered out here. I've filtered out FireFox; it
;// has its own AutoScroll mode.
MouseButtonHandler:
  MouseGetPos, mbh_x, mbh_y, mbh_id, mbh_ctrl, 1
  WinGetClass, mbh_class, ahk_id %mbh_id%

  if ( mbh_class = "1MozillaUIWindowClass" )
  {

    MouseClick, Middle
  }
  else
  {
   KeyWait, XButton1, T0.15
   if ErrorLevel
      GoSub, AutoScroll
   else
      MouseClick, Middle
   
  }
  return


;// Main AutoScroll Function
AutoScroll:

  ;// Store the point where the button was clicked
  as_startx = %mbh_x%
  as_starty = %mbh_y%

  ;// Figure out the center point of the image
  as_splashx := ( as_startx - 10 )
  as_splashy := ( as_starty - 10 )

  ;// Provide the first image name
  as_image = center
 
  ;// Initialize some values
  as_xlast = 0
  as_ylast = 0
  as_xlastvector = 0
  as_ylastvector = 0

  Loop
  {
    as_changed = 0
   
    ;// Get the latest mouse position
    MouseGetPos, as_x, as_y

    ;// Break out of the loop if the Left Mouse Button is clicked
 ;   GetKeyState, as_state, LButton, P
;    if as_state = D
 ;     break
   
        ;//break ouf of loop if XButton1 is depressed
   GetKeyState, as_state2, XButton1, P
    if as_state2 = U
      break
 
   if as_x != %as_xlast%
    {
      as_xvector := round((as_startx - as_x)/100)

      if as_xvector != %as_xlastvector%
      {
        as_xspeed := 10 // Abs(as_xvector)
 
        if as_xvector = 0
          SetTimer, AutoScrollX, Off
        else
          SetTimer, AutoScrollX, %as_xspeed%
   
        as_xlastvector = %as_xvector%
      }
      as_xlast = %as_x%
      as_changed = 1
    }


 
    if as_y != %as_ylast%
    {
      as_yvector := round((as_starty - as_y)/as_notch)
      as_yvector := (as_yvector * Abs(as_yvector))

      if as_yvector != %as_ylastvector%
      {
        if as_yvector = 0
        {
          SetTimer, AutoScrollY, Off
        }
        else
        {
          as_yspeed := ((400 // Abs(as_yvector)) + 1)
          SetTimer, AutoScrollY, %as_yspeed%
        }
   
        as_ylastvector = %as_yvector%
      }
      as_ylast = %as_y%
      as_changed = 1
    }



    ;// Update the image if necessary
    if as_changed = 1
    {
      if (as_xvector=0 and as_yvector=0)
        as_image = center
      else if (as_xvector=0 and as_yvector>0)
        as_image = n
      else if (as_xvector=0 and as_yvector<0)
        as_image = s
      else if (as_xvector>0 and as_yvector=0)
        as_image = w
      else if (as_xvector<0 and as_yvector=0)
        as_image = e
      else if (as_xvector<0 and as_yvector>0)
        as_image = ne
      else if (as_xvector>0 and as_yvector>0)
        as_image = nw
      else if (as_xvector>0 and as_yvector<0)
        as_image = sw
      else if (as_xvector<0 and as_yvector<0)
        as_image = se

      if as_image != %as_lastimage%
      {
        SplashImage, %as_imageroot%\%as_image%.bmp, b X%as_splashx% Y%as_splashy% Hide, , , autoscrollsplash
        WinSet, TransColor, FF00FF , autoscrollsplash
        SplashImage, Show, , , , autoscrollsplash
        as_lastimage = %as_image%
      }
    

    }

    sleep, 10
  }

  GoSub, AutoScrollQuit
  return

AutoScrollY:
  ControlGetFocus, asy_control, A
  if as_yvector > 0
    MouseClick, WU
  else
    MouseClick, WD
  return

AutoScrollX:
  ControlGetFocus, asx_control, A
  if as_xvector > 0
    SendMessage, 0x114, 0, 0, %asx_control%, A
  else
    SendMessage, 0x114, 1, 0, %asx_control%, A
  return

AutoScrollQuit:
  SplashImage, Off
  SetTimer, AutoScrollY, Off
  SetTimer, AutoScrollX, Off
  return
Back to top
View user's profile Send private message
Trabatar57
Guest





PostPosted: Thu Jun 01, 2006 5:19 am    Post subject: How can I decelerate this? Reply with quote

Hey, this is a great script but in Microsoft Word it scrolls too quickly. Anyone know how to slow it down?

Thanks!
Back to top
Guest






PostPosted: Thu Mar 08, 2007 10:24 pm    Post subject: Reply with quote

Don't spin the ball so fast
Back to top
rk_keys



Joined: 15 Apr 2007
Posts: 1

PostPosted: Sun Apr 15, 2007 6:23 am    Post subject: Reply with quote

Thanks!.. this is such an useful script for me as my bluetooth mouse does not have a middle/scroll button. I did not know how to use the XButton1 and had to map it to delayed RightMouse Click to enable the scroll.

However, I got a question -- why doesn't this functionality work in Windows Explorer?
Back to top
View user's profile Send private message
xordos
Guest





PostPosted: Sat Aug 25, 2007 4:00 pm    Post subject: a little (i think) improvement to lock the pointer Reply with quote

Thanks a lot for this script, my mouse(actually trackball) don't have scrollwheel, this works great, but I found when scrolling, the point actually still moves, so for long docs, it may move to out of the window.

Following is my patch, give it a try, you may like it, may be not...Smile
after line:
MouseGetPos,, esmb_OldY
add line:
MouseGetPos, esmb_OrigX, esmb_OrigY

Then at very end just before last line:
return
add lines:
else
{
MouseMove,esmb_OrigX,esmb_OrigY
MouseGetPos,, esmb_OldY
}

Hope you like the patch
Back to top
xordos
Guest





PostPosted: Sat Aug 25, 2007 7:25 pm    Post subject: Reply with quote

I just add more change, that I add a delay, so it will only put pointer back after about 100ms.

Hope this is better Smile

Code:

; IMPORTANT INFO ABOUT GETTING STARTED: Lines that start with a
; semicolon, such as this one, are comments.  They are not executed.

; This script has a special filename and path because it is automatically
; launched when you run the program directly.  Also, any text file whose
; name ends in .ahk is associated with the program, which means that it
; can be launched simply by double-clicking it.  You can have as many .ahk
; files as you want, located in any folder.  You can also run more than
; one ahk file simultaneously and each will get its own tray icon.

;;
;; Emulate_Scrolling_Middle_Button.ahk
;; Author: Erik Elmore <erik@ironsavior.net>
;; Version: 1.1 (Aug 16, 2005)
;;
;; Enables you to use any key with cursor movement
;; to emulate a scrolling middle button.  While
;; the TriggerKey is held down, you may move the
;; mouse cursor up and down to send scroll wheel
;; events.  If the cursor does not move by the
;; time the TriggerKey is released, then a middle
;; button click is generated.  I wrote this for my
;; 4-button Logitech Marble Mouse (trackball), 
;; which has no middle button or scroll wheel.
;;

;; Configuration

;#NoTrayIcon

;; Higher numbers mean less sensitivity
esmb_Threshold = 5
;; Delay 10*10ms, then put pointer back to original location
esmb_delay = 10

;; This key/Button activates scrolling
esmb_TriggerKey = XButton1

;; End of configuration

#Persistent
CoordMode, Mouse, Screen
Hotkey, %esmb_TriggerKey%, esmb_TriggerKeyDown
HotKey, %esmb_TriggerKey% Up, esmb_TriggerKeyUp
esmb_KeyDown = n
return

esmb_TriggerKeyDown:
esmb_Moved = n
esmb_FirstIteration = y
esmb_KeyDown = y
MouseGetPos,, esmb_OldY
MouseGetPos, esmb_OrigX, esmb_OrigY
esmb_counter := 0
SetTimer, esmb_CheckForScrollEventAndExecute, 10
return

esmb_TriggerKeyUp:
esmb_KeyDown = n
SetTimer, esmb_CheckForScrollEventAndExecute, Off
;; Send a middle-click if we did not scroll
if esmb_Moved = n
    MouseClick, Middle
return

esmb_CheckForScrollEventAndExecute:
if esmb_KeyDown = n
    return

MouseGetPos,, esmb_NewY
esmb_Distance := esmb_NewY - esmb_OldY
if esmb_Distance
    esmb_Moved = y

;; Do not send clicks on the first iteration
if esmb_FirstIteration = y
    esmb_FirstIteration = n
else if esmb_Distance > %esmb_Threshold%
{
    esmb_OldY := esmb_OldY + esmb_Threshold
    MouseClick, WheelDown
}
else if esmb_Distance < -%esmb_Threshold%
{
    esmb_OldY := esmb_OldY - esmb_Threshold
    MouseClick, WheelUp
}
else
{
    esmb_counter := esmb_counter + 1
    if( esmb_counter > esmb_delay)
    {
        esmb_counter := 0
        MouseMove,esmb_OrigX,esmb_OrigY
        MouseGetPos,, esmb_OldY
    }
}
return
Back to top
q335r49



Joined: 26 Oct 2005
Posts: 15

PostPosted: Tue Sep 25, 2007 9:13 am    Post subject: Great Script Reply with quote

A great idea... really shows the power and simplicity of Autohotkey. I had just switched to using a trackpoint exclusively, and had no scroll function. I was googling various expressions ("Trackpoint scrolling" etc.) filled with extensive fixes for hours before I remembered this forum. I'll have to go through the modifications later, but ... this script would take like 3 hours to write? That's pretty incredible ... anyways, im gushing
Back to top
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group