Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

horizontal scrolling action


  • Please log in to reply
7 replies to this topic
tinaa
  • Members
  • 59 posts
  • Last active: Jan 30 2014 04:41 PM
  • Joined: 25 Nov 2004
Hi,

I want to remap the scroll wheel on my mouse so that if it's turned while the back button is being held, it will perform a horizontal scroll rather than a vertical scroll.

However, I haven't figured out a way to do this other than to send some keyboard commands like left or right arrow keys. However, the required commands tend to be different with different applications and in some cases, like in Excel, can cause the focus to change as well as just scrolling.

Is there any way to tell the active window (or the one under the cursor) to scroll horizontally, or send it the equivalent of a mouse click on the left or right scroll buttons on the horizontal scroll bar? Most applications have a horizontal scroll bar when horizontal scrolling is an option, and behave similarly when the scrollbar buttons are clicked or the bar is moved. But I'm not sure how, or if I can, send a command to the scrollbar through Autohotkey.

Thanks for your help.

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Try this topic:
http://www.autohotke...opic.php?t=3640

tinaa
  • Members
  • 59 posts
  • Last active: Jan 30 2014 04:41 PM
  • Joined: 25 Nov 2004
I tried your suggestion from that forum. It seems many (maybe most) windows respond properly to the WM_HSCROLL message but at least several don't. I've added exceptions for the applications I've found so far that don't respond to WM_HSCROLL and send an equivalent keyboard command in its place:

xbutton1 & WheelUp::  ; Turning the wheel up scrolls to the left.
    SetTitleMatchMode, 2
    IfWinActive, Microsoft Excel -
    {
        SetScrollLockState, on
        send,{left}
        SetScrollLockState, off
    }
    else IfWinActive, Adobe Acrobat Professional -
    {
        send,+{left}
    }
    else IfWinActive, - Mozilla Firefox
    {
        send,{left}
    }
    else IfWinActive, - Microsoft Word
    {
        send,^{left}    ; move to next word wince I haven't figured out how to scroll horizontally using the keyboard
    }
    else
    {
        ControlGetFocus, FocusedControl, A
        SendMessage, 0x114, 0, 0, %FocusedControl%, A  ; 0x114 is WM_HSCROLL ; 1 vs. 0 causes SB_LINEDOWN vs. UP
    }
return

xbutton1 & WheelDown::   ; Turning the wheel down while holding the back button scrolls to the right.
    SetTitleMatchMode, 2
    IfWinActive, Microsoft Excel -
    {
        SetScrollLockState, on
        send,{right}
        SetScrollLockState, off
    }
    else IfWinActive, Adobe Acrobat Professional -
    {
        send,+{right}
    }
    else IfWinActive, - Mozilla Firefox
    {
        send,{right}
    }
    else IfWinActive, - Microsoft Word
    {
        send,^{right}    ; move to next word wince I haven't figured out how to scroll horizontally using the keyboard
    }
    else
    {
        ControlGetFocus, FocusedControl, A
        SendMessage, 0x114, 1, 0, %FocusedControl%, A  ; 0x114 is WM_HSCROLL ; 1 vs. 0 causes SB_LINEDOWN vs. UP
    }
return

Do you think this is the best approach or might there be a way that will work with all windows and not require explicit exceptions? I'm using a Logitech mouse with tilt-wheel function. It seems the Logitech mouse driver, in response to the tilt-wheel, can tell the focused window to scroll horizontally in a way that seems to work more universally. Is there any way for AutoHotKey to tell the mouse driver to send that command?

Something interesting I noticed when testing this is that the WM_HSCROLL and WM_VSCROLL messages work in notes windows in Microsoft Outlook. I use notes extensively and the lack of scroll bars has always been an irritation. Now I can scroll around in them with the scroll wheel to my heart's content... Actually, the WM_HSCROLL message also scrolls any text in various text fields like the text/dropdown fields you get when browsing for files in a dialog. When pathnames get large they don't fit in the field so being able to scroll without resorting to moving the text cursor is also a nice touch.

Thanks!

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004

It seems the Logitech mouse driver, in response to the tilt-wheel, can tell the focused window to scroll horizontally in a way that seems to work more universally. Is there any way for AutoHotKey to tell the mouse driver to send that command?

Try using Rajat's SendMessage Tutorial to discover what messages the driver is sending to the active window and/or the focused control. If you find out something that works better than WM_HSCROLL, please post it here because it will be of interest to me and others.

tinaa
  • Members
  • 59 posts
  • Last active: Jan 30 2014 04:41 PM
  • Joined: 25 Nov 2004
Winspector Spy is a bit involved so I may have missed something, but I couldn't identify any particular message sent in response to the tilt wheel switches. In most windows I'd get a horizontal scroll but no message in Winspector. In some, like Acrobat, I'd see a number of scrollbarcolor and hscroll messages, but the parameters of the hscroll messages are different than the one you described and used in the script above. This is probably why these windows don't respond correctly when sending that message. instead of parameter 0 and 1 it uses 2 and 3 for the first parameter, and instead of 0, it uses a different hex number for the second parameter. It then seems to send a second message with the same second parameter, but 8 as the first parameter. I tried replicating these messages in my script to see if they'd cause a horizontal scroll but that didn't seem to work.

I thought I might be able to remap the back and forward mouse buttons in the driver to left and right scroll then call those buttons from AutoHotKey. I don't know if that would work, but the driver doesn't allow left and right scrolling as an action for any buttons other than the tilt wheel.

So I think my current script is the best solution at the moment. It would be nice if a future version of AutoHotkey would include some kind of universal scrolling commands, but I have no idea how feasible that is.

One modification to the script above that I found useful is to use

        MouseGetPos,,,hovwin, hovcontrol
        SendMessage, 0x114, 1, 0, %hovcontrol%, A  ; 0x114 is WM_HSCROLL ; 1 vs. 0 causes SB_LINEDOWN vs. UP

instead of

         ControlGetFocus, FocusedControl, A
        SendMessage, 0x114, 1, 0, %FocusedControl%, A  ; 0x114 is WM_HSCROLL ; 1 vs. 0 causes SB_LINEDOWN vs. UP

I find this give more predictable results. In some applications where there are more than 1 child window or pane the focused control isn't where the cursor is and you would need to click within a particular window to give it the focus before you can do a horizontal scroll. For instance, if you open up the AutoHotKey help file, you might have horizontal scroll bars both in the topic pane and the main text pane. I would find myself scrolling the wrong pane, or if only one of them has a horizontal bar, nothing would happen because the wrong pane was in focus. Using the control under the cursor seems more intuitive to me.

tinaa
  • Members
  • 59 posts
  • Last active: Jan 30 2014 04:41 PM
  • Joined: 25 Nov 2004
I do a lot of scrolling in Excel so I thought I'd see if I could improve my scrolling scripts. The script I posted above turns on scrolllock then sends arrow keys to scroll. This works okay when you're not editing a cell, but if you try to scroll while editing a cell (something I do often when creating or editing formulae) this isn't very good since it will generally exit the editing mode and sometimes also change the cell with the focus.

So I went back to Winspector Spy to see if I could figure out how to send an appropriate WM_HSCROLL message to Excel. I had better luck this time.

My use of
MouseGetPos,,,hovwin, hovcontrol
SendMessage, 0x114, 1, 0, %hovcontrol%, A  ; 0x114 is WM_HSCROLL ; 1 vs. 0 causes SB_LINEDOWN vs. UP
doesn't work in Excel, but
ControlGetFocus, FocusedControl, A
SendMessage, 0x114, 1, 0, %FocusedControl%, A  ; 0x114 is WM_HSCROLL ; 1 vs. 0 causes SB_LINEDOWN vs. UP
does. Alternatively, just using
SendMessage, 0x114, 1, 0, EXCEL71, A  ; 0x114 is WM_HSCROLL ; 1 vs. 0 causes SB_LINEDOWN vs. UP

Well, that works in the sense of sending the message to the right control, but it doesn't work because Excel doesn't use 0 as the lParam for these messages. I was able to find the correct the lParam with Winspector Spy. This number is different for horizontal and vertical scrolling messages but is the same for all child windows within an Excel session. When using this method scrolling an any direction is achieved perfectly.

The problem, is that the lParam values change with each Excel session. So short of manually finding the correct lParam values with Winspector and editing the script manually, each time I load Excel, this doesn't work. The guide on sending messages does note that it doesn't work on VB applications because the lParam changes each time, which seems to be the case here. Has anyone found a way to make this work with such applications?

In the meantime, I thought I'd try a different approach. I've found that the name of the horizontal scrollbar control is always "ScrollBar2". Therefore, in theory, I should be able to use the ControlClick command with this control to click at the left or rightmost edge to simulate a mouse click on the left or right arrow buttons on the scrollbar. Using the mouse to click these buttons on the scrollbar scrolls properly without interfering with editing of a cells contents.

So to scroll left (note: in all cases I've set SetTitleMatchMode, 2):
ControlClick, ScrollBar2, Microsoft Excel,, LEFT, 1, X0
and to scroll right:
ControlGetPos, sx, sy, sw, sh, ScrollBar2, Microsoft Excel
ControlClick, ScrollBar2, Microsoft Excel,, LEFT, 1, X%sw%
Well for the left scroll this seems to work. There's a minor flaw in that after this code is executed, the left scroll button appears as if it's depressed. It doesn't behave as if the left mouse button is being held down on it (this would result in continuous scrolling) but it looks that way. I can perform several left scroll operations this way without issue. As soon as the mouse cursor is moved over the scrollbar, the appearance of the left scroll button returns to the un-pressed look (without having to actually press any buttons - it's enough to hover the cursor over any part fo the scrollbar).

However, the right scroll is much uglier. When running that code, it works only ONCE. After the initial success, the scrollbar gets messed up. Initially, the right scroll button appears as if it's depressed, but when hovering the cursor over the scrollbar, rather than return to the un-pressed appearance, the right scroll button is just replaced with a grey box. At this point, the horizontal scroll bar ceases to function at all. Dragging on any part of the scrollbar is interpreted as if it were the resize box at the lower, right corner of the window, therefore causing the window to be resized rather than scrolled. Closing the window seems to be the only way to "fix" the scrollbar.

If I change the X position so it's to the left of the right scroll button it then seems to behave properly, as if I'd clicked the scrollbar just to the left of this button. This results in a full page scroll to the right and the scrollbar remains functional. But if the click is set at any position within the right scroll button, I get the behaviour described above.

So as a workaround I've implemented this for the right scroll:
ControlClick, ScrollBar2, Microsoft Excel,, RIGHT, 1, X0
send, {up}{enter}
This is equivalent of bringing up the scrollbar's context sensitive menu with a right click, the scrolling to the "scroll right" menu option and selecting it with the keyboard. This actually seems to work fine with the minor annoyance of the context menu flickering in and out of existence as I scroll to the right.

Still, it would be nicer if this flickering didn't occur and the left scroll button didn't always look like it was pressed down. Does anyone know why the scrollbar is behaving this way? Is there some way I can get clicks on this scrollbar to be better behaved?


Finally, when editing a formula in a cell, references in the formula to other cells are colour coded within the formula and a box of the same colour is drawn around the referenced cells. This makes deciphering a formula a lot easier. With AutoHotKey disabled, using the scrollwheel to scroll up and down, or using the scrollbars with the mouse to scroll in any direction, does not disrupt the colour coding. However, using the code I just described to scroll horizontally, or using the "mouseclick, wheeldown" or the "send, {wheeldown}" (or wheelup) causes the colour coding to disappear. The text cursor also disappears from the cell being edited. The colour coding can be restored by clicking in the formula bar since the cell being edited retains the correct focus. But it's useful for the colour coding to not disappear at all during scrolling for visually tracking down referenced cells not currently visible in the window. Why do the scrollwheel and scrollbar clicks behave differently when called through AutoHotKey than physically from the mouse?

(Note: when using the WM_HSCROLL and WM_VSCROLL messages for scrolling, the colour coding and text cursor remain intact. This would be an ideal solution if not for the ever-changing lParam...)

Thanks for any help!

Hammillian7
  • Members
  • 9 posts
  • Last active: Dec 31 2010 01:01 PM
  • Joined: 08 Jun 2008
Is there a way of getting the lParam of an Excel session from the AHK script?

It looks like the evident answer to Tinaa's question.

I'm also very interested in scrolling Excel (in my case, translating ^z and ^w to ScrollUp and ScrollDown).

Thanks a lot.
Regards.

theflysurfer
  • Members
  • 5 posts
  • Last active: Sep 30 2014 07:44 AM
  • Joined: 26 May 2011
I tried today.
With Excel 2007, the horizontal scrollbar is designated by ClassNN = NetUIHWND6.

So I got this code, which works even when editing a cell

;Scroll left and right with Shift + Wheel
		;Go left with WheelDown
		+WheelDown::
			;horizontal bar : ClassNN NetUIHWND6
			ControlClick, NetUIHWND6, Microsoft Excel,, LEFT, 1, X0
		return
		;Go right with WheelUp
		+WheelUp::
			;horizontal bar : ClassNN NetUIHWND6
			ControlGetPos, sx, sy, sw, sh, NetUIHWND6, Microsoft Excel
			sw-=1 ;in order to be "inside"
			ControlClick, NetUIHWND6, Microsoft Excel,, LEFT, 1, X%sw%
		return

The only restriction, is that the NetUIHWND number changes sometimes between excel workbooks. It is either 6 or 7. One can send click to both NetUIHWND6 AND NetUIHWND7 when the hotkey is triggered.

Otherwise, here is a post with alternative solutions :
http://www.autohotke...topic38499.html