AutoHotkey Community

It is currently May 25th, 2012, 1:26 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 32 posts ]  Go to page 1, 2, 3  Next
Author Message
PostPosted: August 17th, 2005, 12:35 am 
Offline

Joined: August 17th, 2005, 12:07 am
Posts: 6
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 August 17th, 2005, 1:53 am, edited 3 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 17th, 2005, 1:19 am 
Offline

Joined: March 2nd, 2004, 3:36 pm
Posts: 10720
Anything that reduces RSI during mousing is a great thing to have in the forum. Thanks for sharing this carefully crafted technique.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 17th, 2005, 7:33 am 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
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
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 17th, 2005, 1:49 pm 
Offline

Joined: August 17th, 2005, 12:07 am
Posts: 6
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 17th, 2005, 4:31 pm 
Offline

Joined: March 2nd, 2004, 3:36 pm
Posts: 10720
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
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 17th, 2005, 5:14 pm 
Offline

Joined: August 17th, 2005, 12:07 am
Posts: 6
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject: is it possible...
PostPosted: May 3rd, 2006, 6:15 am 
is it possible to make this script work with scrolling horizontally as it is with scrolling vertically


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: May 3rd, 2006, 6:26 am 
Offline

Joined: August 17th, 2005, 12:07 am
Posts: 6
Quote:
is it possible to make this script work with scrolling horizontally as it is with scrolling vertically

Yes, very easily.


Report this post
Top
 Profile  
Reply with quote  
 Post subject: another trackball script
PostPosted: May 4th, 2006, 5:02 am 
Offline

Joined: May 4th, 2006, 3:39 am
Posts: 3
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


Report this post
Top
 Profile  
Reply with quote  
PostPosted: June 1st, 2006, 5:19 am 
Hey, this is a great script but in Microsoft Word it scrolls too quickly. Anyone know how to slow it down?

Thanks!


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 8th, 2007, 10:24 pm 
Don't spin the ball so fast


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: April 15th, 2007, 6:23 am 
Offline

Joined: April 15th, 2007, 4:21 am
Posts: 1
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?


Report this post
Top
 Profile  
Reply with quote  
PostPosted: August 25th, 2007, 4:00 pm 
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...:)
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


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: August 25th, 2007, 7:25 pm 
I just add more change, that I add a delay, so it will only put pointer back after about 100ms.

Hope this is better :)

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


Report this post
Top
  
Reply with quote  
 Post subject: Great Script
PostPosted: September 25th, 2007, 9:13 am 
Offline

Joined: October 26th, 2005, 5:11 pm
Posts: 28
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


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 32 posts ]  Go to page 1, 2, 3  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Bing [Bot] and 15 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group