This Short AutoHotkey App Adds Pixel Level Precision to Mouse Cursor Movement in Any Windows Graphics Program.
This time we add more cursor directions by implementing numeric keypad Hotkey Scan Codes, plus a feature for temporarily adding these micro cursor hotkeys to any new graphics app.
In the last blog, I introduced the beginnings of the MousePrecise.ahk script. It uses the arrow keys to move the mouse cursor one pixel at a time—either Up, Down, Left, or Right—in designated Windows graphics programs. By using the Numpad0 key as a Hotkey up/down toggle for holding the left mouse button, you can precisely drag (LButton Down) the mouse cursor pixel-by-pixel in any Windows graphics program.

This beginning Hotkey blog builds upon the discussions in the previous parts. If you find any of the information too confusing, then reviewing earlier blogs may be worthwhile.
New to AutoHotkey? See “Introduction to AutoHotkey: A Review and Guide for Beginners.”
* * *
Discussed last time, the #IfWinActive directive isolates the arrow Hotkeys to specific graphics programs. Plus, streamlining the script code and adding flexibility, the GroupAdd command designates the target Windows programs for the mouse micro movement Hotkeys.
MousePrecise.ahk Issues
A number of issues from the script presented last time need addressing:
- The arrow keys only offer four directions (Up, Down, Left, and Right). Use the numeric keypad to add four more Hotkeys for micro movement angles (directions).
- There may be times when we want the temporary use of MousePrecise.ahk in other graphics programs not embedded in the script (e.g. a Web browser window which allows image editing). Include a Hotkey for interactively adding the temporary use of the MousePrecise.ahk Hotkeys to any active Windows program.
- When activating LButton Down, the #If toggle statement blocks left mouse button action, rendering it inactive everywhere in Windows. This creates an awkward mouseless condition if the graphic window loses focus (e.g. ALT+TAB). Create an escape (or cancel) Hotkey whenever AutoHotkey holds down the left mouse button.
- In addition to a cancel-left-mouse-down Hotkey, change conditions in the #If directive to allow use (unblock) of the left mouse in non-graphics apps whenever the active window accidentally changes.
- There is no obvious sign of success after pressing the Hotkey for left-mouse-button-down. Add a Tooltip message which reminds us of the current down position of the left mouse button.
Reader’s Note: While the final MousePrecise.ahk script does not appear in this blog, it is available for download at the ComputorEdge AutoHotkey download site.
In this blog. we remap the numeric keypad to expand the number of MousePrecise.ahk mouse cursor movement Hotkeys adding four new directions (Up Left, Up Right, Down Left, and Down Right). Plus, we implement a feature for the temporary addition of the mouse micro movement Hotkeys to any new graphics app window.
Next time, I’ll offer an in-depth discussion of how to use the ternary operator in conjunction with forced expressions (%) in AutoHotkey. Both techniques appear in the MousePrecise.ahk toggle for the holding down left mouse button. They offer methods for adding power and flexibility to many AutoHotkey commands. You’ll like these AutoHotkey tricks.
The remainder of the above MousePrecise.ahk issues will be addressed in a follow-up blog.
Adding More Cursor Micro Directions
Adding more direction arrows creates increased graphic options for mouse cursor micro movement. While many graphic software tools only use the last location of the mouse cursor when the left mouse button is released, a few (especially freehand drawing tools) record every movement of the mouse cursor. That means any micro adjustments at angles other than Up, Down, Left, or Right record extra, unwanted pixels. Drawing a smooth 45° line is impossible when only using the four cursor arrow keys. However, by adding extra Hotkeys which jump the mouse cursor directly to the chosen angle, the extra pixels are avoided.
For example, when adding a line which moves the mouse cursor both up and right simultaneously, the cursor actually jumps only one pixel at a 45° angle:
Numpad9::MouseMove, 1, -1, 0, R ; Numpad9 key up right
The drawing tool does not record either the single Up or Right pixel as it would if limited to the four arrow keys alone. By inserting the four angles between the standard Up, Down, Left, and Right keys in the numeric keypad, we create a compass rose of Hotkeys shown in the image above:
Numpad1::MouseMove, -1, 1, 0, R ; down left Numpad2::MouseMove, 0, 1, 0, R ; down Numpad3 ::MouseMove, 1, 1, 0, R ; down right Numpad4::MouseMove, -1, 0, 0, R ; left Numpad5::Return ; key does nothing Numpad6::MouseMove, 1, 0, 0, R ; right Numpad7::MouseMove, -1, -1, 0, R ; up left Numpad8::MouseMove, 0, -1, 0, R ; up Numpad9::MouseMove, 1, -1, 0, R ; up right
When dragging the freehand drawing tool with the extra cursor Hotkeys, the mouse cursor jumps directly to the catty-corner pixel without recording any right-angle pixels. This works great for these eight directions. However, reproducing other angles becomes more problematic.
Converting angles in degrees into pixel movement gets a little complicated. You’ll find it easy to add other general drawing directions to your keyboard, but replicating specific angles gets complex. For example, an intermediary angle can be added to the compass rose by adding one to the Up movement (-2) of the 45° angle for Numpad9:
^Numpad8::MouseMove, 1, -2, 0, R ; angle 26.6°
The key combination CTRL+Numpad8 moves the mouse cursor one pixel Right and two pixels Up. However, this movement does not split the angle between 0° and 45° evenly. The above code yields a 26.6° angle (calculated with the trigonometric tangent function) rather than 22.5°. If you want to produce a more exact angle, say 60°, then the tangent must be converted to a ratio of integer numbers—Right (x) and Up (-y):
^Numpad6::MouseMove, 7, -4, 0, R ; angle ~ 60 °
Even then, this merely approximates the desired result with 60.25°. For those who need exact angles of mouse micro movement, an AutoHotkey script which sets up Hotkeys with a reasonable level of accuracy for various angles can be written, but the math and techniques reach beyond the scope of this blog.
Using either the numbers (e.g. Numpad9) or navigational key names (e.g. NumpadPgUp) on the numeric keypad brings up the continual need to set NumLock to the proper position (on or off). Fix that with numeric keypad Scan Codes.
Scan Codes To Bypass Numeric Keypad Numlock Issues
As explained in previous blogs, Understanding AutoHotkey Keyboard Scan Codes and Virtual Key Codes (Beginning Hotkeys Part 12) and When to Use Virtual Keys and Keyboard Scan Codes with AutoHotkey (Beginning Hotkeys Part 14), the key Scan Codes can be considered the hardware assignment for each key on the keyboard. By using the Scan Code, AutoHotkey ignores both the key names (e.g. Numpad1, Numpad2, Numpad3), as well as, the corresponding Virtual Key codes. Unlike AutoHotkey key names and Virtual Keys, when using Scan Codes, the position of the NumLock key (on or off) has no effect on the Hotkeys. (The keyboard Scan Codes for each of the numeric keypad keys appear in the image above.)
Convert the numeric pad Hotkeys to Scan Codes Hotkeys with the following:
SC04F::MouseMove, -1, 1, 0, R ; Numpad1 key down left SC050::MouseMove, 0, 1, 0, R ; Numpad2 key down SC051::MouseMove, 1, 1, 0, R ; Numpad3 key down right SC04B::MouseMove, -1, 0, 0, R ; Numpad4 key left SC04C::Return ; Numpad5 key does nothing SC04D::MouseMove, 1, 0, 0, R ; Numpad6 key right SC047::MouseMove, -1, -1, 0, R ; Numpad7 key up left SC048::MouseMove, 0, -1, 0, R ; Numpad8 key up SC049::MouseMove, 1, -1, 0, R ; Numpad9 key up right
Using the Scan Code for the numeric pad zero key changes the ternary toggle Hotkey code line to:
SC052::Send % (toggle := !toggle) ? "{LButton Down}" : "{LButton Up}"
Reader’s Note: I’m saving the details of this line of toggle code for the next blog. I intend to spend an entire blog discussing the value of forcing expressions with the percent sign % and using the ternary expression above in other practical AutoHotkey applications.
Interactively Add Temporary Hotkeys to Graphic Apps
At times, you may want to activate these micro cursor Hotkeys in other graphic applications without hard coding them into the AutoHotkey script. Perhaps you’re using a graphics editor on the Web, but don’t want to permanently add the browser class to your Graphics group. (In fact, you could make all of the Hotkeys dormant until you need them by not adding any of the apps to the script with GroupAdd.) Activate the Hotkeys in real-time with the following code:
^SC053:: ;Hotkey CTRL+NumpadDel to add window class WinGetClass, class, A GroupAdd, Graphics, ahk_class %class% MsgBox, Class %class% temporarily`radded to Graphics group Return
The Scan Code for the NumpadDel key (also NumpadDot), when used in combination with the CTRL key, becomes the “Add-New-App” Hotkey . The WinGetClass command grabs the class of the active window—storing it into the variable class. Next, the GroupAdd command adds the window class to the group Graphics.
This activates the micro cursor Hotkeys for the new app. The MsgBox command line displays positive action feedback. The Hotkeys remain active until the MousePrecise.ahk script reloads.
Blocking Hotkeys in Common Windows
In a recent comment added to an earlier blog about GroupAdd, Jim S. presented code enhancing the GroupAdd example. I was intrigued by the technique Jim used to block the accidental adding of standard Windows system windows to the GroupAdd group:
; Ignore certain classes of windows ; Progman = Desktop; DV2ControlHost = Start Menu; Shell_TrayWnd = Taskbar WinGetClass, WinClass, A if WinClass in Progman,DV2ControlHost,Shell_TrayWnd Return
The If Var In conditional statement offers a method for quickly checking if an item appears within a list of options—handy if you have a list of conditions.
Note: While incorporating the feature into the MousePrecise.ahk script, I found that we need some additional classes included for Windows 10 (Windows.UI.Core.CoreWindow—Start Menu, WorkerW—Desktop, and MultitaskingViewFrame—TaskView):
^SC053:: ;Hotkey CTRL+NumpadDel to add window class WinGetClass, class, A ; Ignore certain classes of windows — This portion stolen from Jim S. ; Progman = Desktop; DV2ControlHost = Start Menu; Shell_TrayWnd = Taskbar If class in Progman,DV2ControlHost,Shell_TrayWnd ,Windows.UI.Core.CoreWindow,WorkerW,MultitaskingViewFrame Return Else { GroupAdd, Graphics, ahk_class %class% MsgBox, Class %class% temporarily`radded to Graphics group } Return
If the active window belongs to one of the classes listed in the If Var In conditional list, then the subroutine terminates (Return) with no action. Note: AutoHotkey line continuation techniques break the If class in line into two pieces for display purposes.
If you think that you always want the micro cursor Hotkeys active in a certain program, then add its class to the MousePrecise.ahk script. Otherwise, use the interactive temporary add Hotkey.
Again, next time, I’ll offer a brief overview of the toggle used in MousePrecise.ahk, plus explore forced expressions and the ternary operator in AutoHotkey. The use of the force expression (%) operator and the ternary conditional offers so much more in a variety of AutoHotkey situations, that I now plan to devote the next blog to that topic. The remaining issues and features found in the MousePrecise.ahk script will be discussed in later blogs.
[…] To understand and/or modify the MousePrecise.ahk script, see the blogs “AutoHotkey Script for Precision Hotkey Mouse Movement in Windows Graphics Programs” and “AutoHotkey Script for Precision Hotkey Mouse Movement in Windows Graphics Programs (continued).” […]
LikeLike