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
Code:
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
Code:
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
Code:
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):
Code:
ControlClick, ScrollBar2, Microsoft Excel,, LEFT, 1, X0
and to scroll right:
Code:
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:
Code:
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!