Categories
Uncategorized

How to Get Google Maps GPS Coordinates in AutoHotkey

This code returns the GPS coordinates of any point the mouse icon is hovered above in Google Maps using AutoHotkey.


; Right click the desired location in Google Maps. 
; It brings up a menu.
click, right 
sleep 400

; Highlight "What's Here?" by clicking the right arrow three times
Send {Right 3} 
Send {Enter} ; Selects "What's Here?"

Send ^+j ; Open Chrome Inspector console
sleep 1800

; Get the GPS coordinates, which are in the format of 35.878320, -97.394132
SendRaw copy(document.getElementsByClassName("widget-reveal-card-lat-lng")[0].innerHTML);
Sleep, 5
Send {Enter}

; Copy the value to the clipboard
ClipWait, 5

; Check for errors
if ErrorLevel
{
    MsgBox, The attempt to copy coordinates onto the clipboard failed.
    return
}

; Move the coordinates value from the clipboard to a variable
fullCoordinates := clipboard
Sleep, 20

; Empty the clipboard.
clipboard =   
Sleep, 200

Send ^+j ; Close Chrome Inspector console
sleep 50

; Split and set the full coordinates into longitude and lattitude
splittedCoordinates := strSplit(fullCoordinates,",") 

; The separate lattitude and longitude values
lattitude := Trim(splittedCoordinates[1]) ; looks like 35.878320
longitude := Trim(splittedCoordinates[2]) ; looks like -97.394132

		
Categories
Uncategorized

How To Create AutoHotkey Objects with GUI Input Boxes

One of the most powerful features of AutoHotkey is the ability to use Object-Oriented Programming (OOP) to create objects from classes.

In this tutorial we will use AutoHotkey input boxes to create objects with the input we enter into the boxes.

Using objects will make it easier for us to include logic that can analyze the data and make decisions based on the object’s properties. It organizes the data and makes it more easily transfer to a form or spreadsheet.

Imagine our job is to enter the results of sports games into a database. Our company requires us to record the name of the sport (baseball, football, etc.), the two team names and who won, and to create a summary of the game including game statistics (the total number of home runs for baseball, the total number of touch downs for football, etc.)

Let’s take a look at a few ways we can do this with input boxes.

Passing Data from Multiple Input Boxes into an Object

Let’s first start by creating a Game class. It looks like this.

class Game {
	
	sport := ""

	teamNameA := ""
	teamNameB := ""

	teamAPoints := 0
	teamBPoints := 0

	totalHomeRuns := 0
	totalTouchdowns := 0

	getWinner() {}

	getLoser() {}

	getSummary() {}
}

Let’s fill out the methods getWinner and getLoser. These methods return the team names of the winner and loser, respectively.

	getWinner() {
		if (this.teamAPoints > this.teamBPoints) {
			return this.teamNameA
		}
		return this.teamNameB
	}

	getLoser() {
		if (this.teamAPoints > this.teamBPoints) {
			return this.teamNameB
		}
		return this.teamNameA
	}

Let’s also add standard setters and getters for the properties.

	; Setters
	setSport(sportName) { this.sport := sportName }
	setTeamNameA(teamName) { this.teamNameA := teamName }
	setTeamNameB(teamName) { this.teamNameB := teamName }
	setTeamAPoints(points) { this.teamAPoints := points }
	setTeamBPoints(points) { this.teamBPoints := points }
	setTotalHomeRuns(homeRuns) { this.totalHomeRuns := homeRuns }
	setTotalTouchdowns(touchdowns) { this.totalTouchdowns := touchdowns}

	; Getters
	getSport() { return this.sport }

And finally, let’s fill out the getSummary method.

getSummary() {

	winner := this.getWinner()
	loser := this.getLoser()

	summary := "The " . winner . " won against the " . loser . ". "
	summary += "The score was " . this.teamAPoints . " to " . this.teamBPoints . ". "

	stats := ""

	Switch this.sport {
		Case: "baseball":
			stats := "There were " . this.homeRuns . " home runs in the game."
		Case: "football":
			stats := "There were " . this.touchdowns . " touchdowns in the game."
	}

	summary += stats

	return summary
}

The getSummary method returns a slightly different message depending on the sport type. It will always begin, as for example, “The Cleveland Guardians won against the New York Yankees. The score was 3 to 6.” The third sentence will change depending on the sports type. If it’s a baseball game, it will say something like, “There were 4 home runs in the game”, and if it’s a football game, it will say something like “There were 5 touchdowns in the game.”

The Game class now looks like this.

class Game {
	
	sport := ""

	teamNameA := ""
	teamNameB := ""

	teamAPoints := 0
	teamBPoints := 0

	totalHomeRuns := 0
	totalTouchdowns := 0

	getWinner() {
		if (this.teamAPoints > this.teamBPoints) {
			return this.teamNameA
		}
		return this.teamNameB
	}

	getLoser() {
		if (this.teamAPoints > this.teamBPoints) {
			return this.teamNameB
		}
		return this.teamNameA
	}

	getSummary() {

		winner := this.getWinner()
		loser := this.getLoser()

		summary := "The " . winner . " won against the " . loser . ". "
		summary += "The score was " . this.teamAPoints . " to " . this.teamBPoints . ". "

		stats := ""

		Switch this.sport {
			Case: "baseball":
				stats := "There were " . this.homeRuns . " home runs in the game."
			Case: "football":
				stats := "There were " . this.touchdowns . " touchdowns in the game."
		}

		summary += stats

		return summary
	}


	; Setters
	setSport(sportName) { this.sport := sportName }
	setTeamNameA(teamName) { this.teamNameA := teamName }
	setTeamNameB(teamName) { this.teamNameB := teamName }
	setTeamAPoints(points) { this.teamAPoints := points }
	setTeamBPoints(points) { this.teamBPoints := points }
	setTotalHomeRuns(homeRuns) { this.totalHomeRuns := homeRuns }
	setTotalTouchdowns(touchdowns) { this.totalTouchdowns := touchdowns}

}

We now have a class from which we can create an object to store all of the game’s data. But how do we get the data? From the user. We will pass it to our script with input boxes.

The simplest way to create an input box in AutohotKey is in the format:

InputBox, variableName, text shown in the input box

Let’s add a bunch of input boxes that will store the data we need.

; Ask the user for the sport name, e.g. baseball
InputBox, sportName, What is the sport?

; Ask the user for one team's name, e.g. Cleveland Guardians
InputBox, teamNameA, What was one team's name?

; Ask the user for the team's total points, e.g. 8
InputBox, teamAPoints, How many points did they score?

; Ask the user for the other team's name, e.g. New York Yankees
InputBox, teamNameB, What was the other team's name?

; Ask the user for the team's total points, e.g. 6
InputBox, teamBPoints, How many points did they score?

; Ask the user the number of home runs, e.g. 3
InputBox, totalHomeRuns, What was the total number of home runs in the game between both teams?

; Ask the user the number of touchdowns, e.g. 4
InputBox, totalTouchdowns, What was the total number of touchdowns in the game between both teams?

Excellent! Thanks to the input boxes, we now have data to put into our object. Let’s create the object and put the data inside using its setter methods.

; Create a game object
game := New Game()

; Set the sport
game.setSport(sportName)

; Set the first team
game.setTeamNameA(teamNameA)

; Set their score
game.setTeamAPoints(teamAPoints)

; Set the other team
game.setTeamNameB(teamNameB)

; Set their score
game.setTeamBPoints(teamBPoints)

; Set the total home runs
game.setTotalHomeRuns(totalHomeRuns)

; Set the total touchdowns
game.setTotalTouchdowns(totalTouchdowns)

Now that all of the data is in the object, we can call the getSummary method to process it and return the game summary that our job requires.

; Get the game summary
gameSummary := game.getSummary()

To continue with our baseball example, getSummary would return a message like this: “The Cleveland Guardians won against the New York Yankees. The score was 8 to 6. There were 3 home runs in the game.”

The game object now has all of the data required for you to complete your job. Use the object’s getters methods to enter the data into your company’s online form or spreadsheet.

The final script looks like this:

; Ask the user for the sport name, e.g. baseball
InputBox, sportName, What is the sport?

; Ask the user for one team's name, e.g. Cleveland Guardians
InputBox, teamNameA, What was one team's name?

; Ask the user for the team's total points, e.g. 8
InputBox, teamAPoints, How many points did they score?

; Ask the user for the other team's name, e.g. New York Yankees
InputBox, teamNameB, What was the other team's name?

; Ask the user for the team's total points, e.g. 6
InputBox, teamBPoints, How many points did they score?

; Ask the user the number of home runs, e.g. 3
InputBox, totalHomeRuns, What was the total number of home runs in the game between both teams?

; Ask the user the number of touchdowns, e.g. 4
InputBox, totalTouchdowns, What was the total number of touchdowns in the game between both teams?


; Create a game object
game := New Game()

; Set the sport
game.setSport(sportName)

; Set the first team
game.setTeamNameA(teamNameA)

; Set their score
game.setTeamAPoints(teamAPoints)

; Set the other team
game.setTeamNameB(teamNameB)

; Set their score
game.setTeamBPoints(teamBPoints)

; Set the total home runs
game.setTotalHomeRuns(totalHomeRuns)

; Set the total touchdowns
game.setTotalTouchdowns(totalTouchdowns)

; Get the game summary
gameSummary := game.getSummary()

; Save the game summary to a form, spreedsheet row, etc.


class Game {
	
	sport := ""

	teamNameA := ""
	teamNameB := ""

	teamAPoints := 0
	teamBPoints := 0

	totalHomeRuns := 0
	totalTouchdowns := 0

	getWinner() {
		if (this.teamAPoints > this.teamBPoints) {
			return this.teamNameA
		}
		return this.teamNameB
	}

	getLoser() {
		if (this.teamAPoints > this.teamBPoints) {
			return this.teamNameB
		}
		return this.teamNameA
	}

	getSummary() {

		winner := this.getWinner()
		loser := this.getLoser()

		summary := "The " . winner . " won against the " . loser . ". "
		summary += "The score was " . this.teamAPoints . " to " . this.teamBPoints . ". "

		stats := ""

		Switch this.sport {
			Case: "baseball":
				stats := "There were " . this.homeRuns . " home runs in the game."
			Case: "football":
				stats := "There were " . this.touchdowns . " touchdowns in the game."
		}

		summary += stats

		return summary
	}


	; Setters
	setSport(sportName) { this.sport := sportName }
	setTeamNameA(teamName) { this.teamNameA := teamName }
	setTeamNameB(teamName) { this.teamNameB := teamName }
	setTeamAPoints(points) { this.teamAPoints := points }
	setTeamBPoints(points) { this.teamBPoints := points }
	setTotalHomeRuns(homeRuns) { this.totalHomeRuns := homeRuns }
	setTotalTouchdowns(touchdowns) { this.totalTouchdowns := touchdowns}

	; Getters
	getSport { return this.sport }
}
Categories
Uncategorized

How to Paste with AutoHotkey

There are a few different ways to paste with AutoHotkey, and this is what we recommend:

SendInput %Clipboard%

Two other ways to paste are:

Send %Clipboard%

and

Send ^v

SendInput prevents accidental physical keyboard and mouse input from the user interfering with the paste.

Send will output letters one by one, unlike the behavior of SendInput which will paste all the letters at one time.

Send ^v will paste the clipboard in rich text format, while Send %Clipboard% will paste the clipboard in plain text format.

Categories
Uncategorized

How to Switch to a Specific Browser Tab with AutoHotkey

Do you have a bunch of tabs open in your web browser and you want switch to the one with a specific title?

This script will loop through all of the open tabs in your browser and stop when it finds part of the page title that says “Automate This”.


NumOfTimesToCheck = 40 ; timeout - circle through tabs this many times
TimesChecked = 0
SetTitleMatchMode 2
needle := "Automate This"
WinActivate, Chrome
Loop {
  TimesChecked++
  if (NumOfTimesToCheck == TimesChecked)
    return
  WinGetTitle, title
  IfWinNotActive, Chrome
    break
  if (InStr(title,needle))
    Break
  Else
    send ^{Tab}
  sleep 50
}

It contains a timeout, NumOfTimesToCheck, which means if the script can’t find the tab it’s looking for after 40 tries it will stop. If you have more than 40 tabs open, you will want to increase this value.

Another thing to note is that this script will stop when it finds the first tab that contains the needle in the title. If there are two tabs with the words “Automate This” in the title, it will stop at the first one it encounters, which might not be the one you want. To prevent this, make sure each tab you’re trying to find has a unique title, and if two titles are similar, try to make the needle as detailed as possible.

This script works with Chrome. Want to use Firefox instead? Replace WinActivate, Chrome with WinActivate, Firefox