While Digging into On-Screen Graphic Line Generation, I Discovered a Number of New AutoHotkey Techniques to Add to the MouseMeasure.ahk Distance Capturing Script
Last time, I looked into adding a line drawn on-screen to visually represent a linear measurement (“Drawing Lines on Screens with AutoHotkey“). However, I didn’t feel that the drivers I used presented the result I wanted for the MouseMeasure.ahk script. The line jittered too erratically and I found holding down the left-mouse button while dragging awkward and lacking precision. Therefore, I didn’t post the final product—although I did provide a download for the curious.
I have since drawn upon the expertise of other AutoHotkey Forum users to revise the script and create a much more robust app. The new script includes the following improvements:
- Only one Hotkey combination (
Ctrl+LButton
) activates both the calibration and measuring subroutine. - The script no longer requires holding down the left mouse button while positioning the end point of the measurement. The end-point remains attached to the moving mouse cursor.
- The more advanced GDIPlus graphics used to draw the line make the line smoother and more robust.

Shift
or Alt
key.I pulled these improvements from a number of sources.
Drawing the On-Screen Line
I reviewed a number of GDIPlus on-screen line drawing scripts. Some scripts directly calling the DllCall() function proved too tedious for me to follow. The best examples placed the DLLCall() function inside separate user-defined functions—each achieving a specific result. One of the earliest GDIPlus libraries—along with example scripts—was initiated by the tic (Tariq Porter): GDIP Standard Library examples. The library GDIP_All.ahk looks like a good starting point for many of the AutoHotkey on-screen graphics routines.
However, since none of the examples specifically drew a single line, I moved on to a forum reply by the user Hellbent to the Forum post “[Gdip] How to draw lines and retrieve pixel length?” offering an example of a line generator. With a little modification, I implemented the Hellbent line drawing technique in my MouseMeasure.ahk script.
I plan to discuss these line-drawing techniques (and more) in future blogs, but this time I concentrate on another technique—specifically, how Hellbent eliminated (or at least minimized) the use of Hotkeys. This technique alone made the MouseMeasure.ahk script much more user friendly by simulating temporary Hotkeys using the GetKeyState() function.
Using the GetKeyState() Function to Eliminate Hotkeys
By adding the Hellbent approach to Hotkey elimination (or minimization), I significantly changed how the new MouseMeasure.ahk script works (as shown in this image):


Drag the scrollbar down (or click at the bottom of the image) to view the original four-Hotkey instructions. Drag up (or click at the top of the image) to view the new single-Hotkey method. In the new script, the Hotkey combination
Ctrl+Left Mouse Button
initiates the calibration/measurement subroutine. Next, to pin the line end point, press Alt
for calibration or press Shift
for measurement.As near as I can determine, Hellbent prefers not to use Hotkeys at all. I completely understand that perspective. I usually look for ways to avoid Hotkeys (“Eliminate Hotkeys with AutoHotkey Menus“). In his sample script, Hellbent presented an alternative technique for creating a Hotkey-like response to the keyboard action. After initiating SetTimer action with a single Hotkey (Ctrl+LButton
), the subroutine reacts to specific keyboard action using the GetKeyState() function before moving on:
^LButton::
active_Draw:=1
MyPen:=New_Pen("FF0000",,5)
MouseGetPos,sx,sy
SetTimer,DrawStuff,10
return
DrawStuff:
Gdip_GraphicsClear(GdipOBJ.G)
MouseGetPos,ex,ey
Gdip_DrawLine(GdipOBJ.G, myPen, sx, sy, ex, ey)
UpdateLayeredWindow(GdipOBJ.hwnd, GdipOBJ.hdc)
if(GETKEYSTATE("Shift")){
active_Draw:=0
SetTimer,DrawStuff,off
tooltip,% "The lenght is " abs(Sqrt(((sx-ex)**2) + ((sy-ey)**2)))
Gdip_DeletePen(myPen)
}
return
The SetTimer,DrawStuff,10
statement (line 5) initiates the DrawStuff subroutine relaunching it every 10 milliseconds. When GetKeyState() detects the Shift
key (line 13), AutoHotkey stops the timer and displays the calculated distance in pixels between the start and stop points.
Note: I did observe that occasionally the subroutine would not detect the Shift
key action—forcing me to press it again. I suspect that occurred because I happened to hit the key during the instant that SetTimer relaunched the subroutine—a minor inconvenience that seemed to lessen when I increased the cycle time to 50 milliseconds.
Using GetKeyState() in the MouseMeasure.ahk Script
I immediately recognized that I no longer needed to hold down the left-mouse button while dragging the line across the target span—tremendous relief for my index finger. Plus, it allowed me to add varied results for calibration and measurement (or any future action, i.e. multi-segment measurement). Losing the requirement to detect Shift & LButton Up
and Ctrl & LButton Up
represents progress.
I modified the MouseMeasure.ahk script as follows:
#If (active_Draw=0)
^LButton::
active_Draw:=1
MyPen:=New_Pen("FF0000",,5)
MouseGetPos,sx,sy ; start position for measurement
SetTimer, UpdatePos,50
SetTimer,DrawStuff,50
Return
#If
By placing the Hotkey inside the #If (active_Draw=0)
directive, the Hotkey deactivates while running the SetTimer routines.
Note: I could probably combine the UpdatePos subroutine (from “Capturing Computer Screen Measurements“) and DrawStuff subroutine but I want to wait until I add other features. I may need to combine them or prefer to keep them separate.
The DrawStuff subroutine appears as follows:
DrawStuff:
Gdip_GraphicsClear(GdipOBJ.G)
MouseGetPos,ex,ey
Gdip_DrawLine(GdipOBJ.G, myPen, sx, sy, ex, ey)
UpdateLayeredWindow(GdipOBJ.hwnd, GdipOBJ.hdc)
if(GETKEYSTATE("Shift")){
active_Draw:=0
setTimer UpdatePos, off
SetTimer,DrawStuff,off
tooltip Distance measured is : %distCalibrated% %units%
clipboard := distCalibrated
Gdip_DeletePen(myPen)
}
if(GETKEYSTATE("Alt")){
active_Draw:=0
setTimer UpdatePos, off
SetTimer,DrawStuff,off
ToolTip
Gdip_GraphicsClear(GdipOBJ.G)
UpdateLayeredWindow(GdipOBJ.hwnd, GdipOBJ.hdc)
clipboard := distCalibrated
GuiControl, Calibrate:, Pixels, %dist%
Gui, Calibrate:Show, , Scale Calibration
}
Return
This approach to detecting keyboard input using the GetKeyState() function (line 6 and line 13) eliminates three previous Hotkey combinations found in the original MouseMeasure.ahk script—as well as, the requirement to hold-and-drag the left-mouse button.
You can find the above changes (plus the new GDIPlus features and functions) in the currently posted version of the MouseMeasure.ahk script.
GDIPlus Graphics
I plan to discuss the GDIPlus graphics used in the MouseMeasure.ahk script in much greater detail. As I develop a better understanding of how they work and the methods for implementation, I’ll use changes in this script to demonstrate the limited ways I use the DLLCall() functions. While I don’t yet have it all figured out, I plan to:
- Show how to use the GDIPlus functions provided by Hellbent to draw a line on an invisible screen cover—a mini tutorial.
- Add connected lines for measuring non-straight distances with multiple legs using an array.
- Add informational GDIPlus text for each leg of the measured distance.
As usual, I may deviate from the above plan.
Click the Follow button at the top of the sidebar on the right of this page for e-mail notification of new blogs. (If you’re reading this on a tablet or your phone, then you must scroll all the way to the end of the blog—pass any comments—to find the Follow button.)

This post was proofread by Grammarly
(Any other mistakes are all mine.)
(Full disclosure: If you sign up for a free Grammarly account, I get 20¢. I use the spelling/grammar checking service all the time, but, then again, I write a lot more than most people. I recommend Grammarly because it works and it’s free.)
Find my AutoHotkey books at ComputorEdge E-Books!
Find quick-start AutoHotkey classes at “Robotic Desktop Automation with AutoHotkey“!
Thank you very much for improving this. I use it daily now!
LikeLike
[…] my last blog (“Replace Hotkeys with the AutoHotkey GetKeyState() Function“), I explained a Hotstring replacement trick as well as introducing GDIPlus graphics drawing […]
LikeLike
[…] movement in an editing window without disabling or closing the MouseMeasure.ahk app. (See “Replace Hotkeys with the AutoHotkey GetKeyState() Function” for an introduction to the GDIPlus version of the script. See “How to Draw Lines with […]
LikeLike
[…] because I found the Hotkey more reliably interrupted the SetTimer subroutine. (See “Replace Hotkeys with the AutoHotkey GetKeyState() Function for more information.”) Since the SetTimer routine fires so rapidly (every 50 milliseconds), […]
LikeLike