Measure Multiple Line Segments with an AutoHotkey On-Screen Ruler

Taking the MouseMeasure.ahk Script to the Next Level, We Add Multiple Calculations for Going Around Corners

The original MouseMeasure.ahk script captures a single-length in a straight line—as a crow flies. While this works great for many applications, roads and highways generally wind over travel distances. Depending upon where you’re going, this can cause a significant variation in the total calculation. To return a more accurate overall estimate, we must break the measurement line into shorter segments.

Start the measurement with the Ctrl+LButton Hotkey, then click the left mouse button for each new leg of the journey. Press the Shift key to terminate the last leg and display the total distance.

The original form of the MouseMeasure.ahk script only allows for a sole straight line. To add more legs to our journey (at different angles), we must implement AutoHotkey techniques for:

  1. Terminating one segment and starting a new one.
  2. Tracking the position of each segment, its length, and the total distance traveled.
  3. Refreshing the screen to include all past legs as well as the new leg.
  4. Sending multiple saved data items for each leg to documents and forms.

You’ll find these changes in the new MouseMeasureMultiLine.ahk script. There’s a lot to unpack in these improvements and I plan to continue discussing the rationale and details of these techniques in upcoming blogs.

1. Adding Multiple Line Segments

Library Benefits

Maybe the easiest part of the new script was adding multiple lines. I only needed to change the line-drawing starting point to a new location. To make the technique as intuitive as possible, I used the left mouse button (LButton) to both terminate the original line and start the new one. However, since a mouse click ranks as the number-one user interaction technique, I isolated the mouse-click—preventing it from intruding upon other applications.1.0310.72834

After initiating the measurement process, capture the current leg and start a new line segment by merely clicking the left mouse button. This action continues until you press the Shift key for final data-capture and display.

2. Tracking Line Segments

While you’ll find many AutoHotkey techniques for tracking data, by far, associative arrays make the most sense. An array (similar to a matrix of variables) can save an unlimited number of data points and make information retrieval easy. This aids in the redrawing of the graphics as well as maintaining readily accessible data.

I added MyArray[] for tracking the start and end coordinates, pixel distance, calculated unit distance, and the total distance for all legs:

MyArray[Array_count] := {sx:sx,sy:sy,ex:ex,ey:ey,pixellength:dist
     ,length:distCalibrated,total:legtotCalibrated}

3. Redrawing Graphic Screens

To maintain dynamic screen redrawing, the entire set of graphics images frequently refreshes. That includes the current unterminated line and each saved leg. This requires looping through the array of captured data during each update. The line-tracking MyArray[] makes this possible:

	Gdip_DrawLine(GdipOBJ.G, myPen, sx, sy, ex, ey)
	Loop, % MyArray.Length()	{
		Gdip_DrawLine(GdipOBJ.G, myPen, MyArray[A_Index].sx, MyArray[A_Index].sy, MyArray[A_Index].ex, MyArray[A_Index].ey)
	}

4. Inserting Results into Documents

The more legs used, the greater
the accuracy of the the total
distance measured—although
only the first nine legs assign
Hotkeys (1-9) for retrieving
leg-lengths.

Since it only holds one value, the Windows Clipboard falls short when inserting data from separate line lengths into documents. The new script inserts the individual distances directly from the data array using temporary Hotkeys (currently only the first nine legs, 1-9). The Clipboard continues to hold the total length of the combined legs.

; Inside array loop
If A_Index < 10
 Hotkey, % "$" A_Index , DistanceSend
; Called subroutine		
DistanceSend:
keyvar := substr(A_ThisHotkey,2,1)
SendInput, % MyArray[keyvar].Length Return

Starting a New Line Segment

Each of these four topics deserves in-depth attention. In this blog, I plan to dig into the method for drawing multiple lines. In future blogs, I’ll discuss the other three techniques:

  • Tracking Line Segments with Arrays.
  • Redrawing Graphic Screens Using Multiple Line Arrays.
  • Hotkey Techniques for Inserting Multiple Results into Documents.

How to Add More Lines to the Invisible Graphics GUI

As discussed in “How to Draw Lines with AutoHotkey Using Windows GDIPlus Graphics“, this AutoHotkey script formulates lines between the start point (sx,sy) and the endpoint (ex,ey).

Gdip_DrawLine(GdipOBJ.G, myPen, sx, sy, ex, ey)

AutoHotkey works on the invisible GUI surface (GdipOBJ.G) using the graphic tool myPen to draw the line from sx,sy to ex,ey.

Since the line endpoint (ex,ey) continuously updates to the current mouse cursor location during redrawing, we only need to reset the start point (sx,sy) to initiate a new line segment. We can use the old endpoint coordinates (sx := ex and sy := ey) for the new start point or capture the new coordinates using the MouseGetPos command as shown here:

#If (active_Draw=1)
LButton::
	Array_count++
	totdist := totdist + dist
	MyArray[Array_count] := {sx:sx,sy:sy,ex:ex,ey:ey,pixellength:dist,length:distCalibrated,total:legtotCalibrated}
	MouseGetPos,sx,sy
	ToolTip, %distCalibrated% %units%, %ex%, %ey%, % Array_count + 1
Return
#If

This code activates the left mouse button (LButton) as a Hotkey only when the app enters the line-drawing mode (active_Draw=1). After entering this graphics-drawing session, you can’t use your left mouse button to interact with other programs. Both the Shift key (end measurements) and the Alt key (calibrate scale) terminate this active drawing mode—ending the capture of the mouse-click. (You can also press the Delete key to terminate this mode and clear the screen.)

Note: In the future, I may alter the Delete key action to remove the current or last leg of the series and implement Alt+Delete to clear the graphics.

The first three lines of the mouse-click Hotkey subroutine save current measurement line data to MyArray[]. They enable the storing of the current line data, the redrawing of the graphics screen to include all segments, and the inserting of individual distances into documents and editing fields. (I plan to talk about the setup and use of MyArray in my next blog. For now, reviewing the code in the posted script might offer enough insight for many users to figure out what’s going on.)

For this blog the highlighted MouseGetPos,sx,sy resets the start point without changing any other portion of the script. In other words, if I did not add the array to save the line data for redrawing (to test, comment-out those three lines), the mouse-click will merely draw the line from the new start point.

Note: I used a Hotkey rather than the GetKeyState() function to activate this subroutine 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), using GetKeyState() tends to add redundant zero-length legs.

Separate Measurement Lines

In a similar manner, If I want to draw and track multiple—yet separated—lines, I can toggle the left mouse click to first terminate the current line, save data and turn off the line-drawing subroutine, then reset the start point (MouseGetPos,sx,sy) and restart the line-drawing subroutine on the subsequent mouse-click:

LButton::
if mouse_click = 1        ; toggle
{
	mouse_click := 0  ; toggle off
	Array_count++
	totdist := totdist + dist
	MyArray[Array_count] := {sx:sx,sy:sy,ex:ex,ey:ey,pixellength:dist,length:distCalibrated,total:legtotCalibrated}
	ToolTip, %distCalibrated% %units%, %ex%, %ey%, % Array_count + 1
	SetTimer,DrawStuff,off
}
else
{																															
	mouse_click := 1  ; toggle on
	MouseGetPos,sx,sy
	SetTimer,DrawStuff,50
}
Return

To incorporate this change into the script, replace the current LButton Hotkey code with the above subroutine. (You’ll find this code available, yet commented-out, in the posted MouseMeasureMultiLine.ahk script.)

Set the mouse_click toggle variable to 1 in the Ctrl+LButton line-drawing-initiating subroutine. (This change appears in the current version of the script—although it has no effect without implementing the above toggling code.)

Although not discussed in this blog, these features totally depend upon the proper implementation of the data array. Next time, I’ll discuss how and why I added the MyArray[] array object.

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.)

jack

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“!

2 thoughts on “Measure Multiple Line Segments with an AutoHotkey On-Screen Ruler

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s