Thursday, April 24, 2008

Massively Useful Software: AutoHotkey

Like most people, the first time you need to use a macro program it's for something completely immature and nonconstructive. For me, I needed something like AutoHotkey to quickly generate my 3-line Cute Bunny Giving You the Bird ASCII graphic into the game chat before someone realized what was going on—which was usually around the "( ._.) ..!." line—and then they assault it by quickly sending something like "asdf" which decapitates my bunny!

I wasn't going to take that kind of treatment anymore, and no bunny deserves to be decapitated, so I used AutoHotkey to create a macro that creates the bunny immediately without having to type it in by hand. No one could stop it and no more bunnies ever died again. Well, that's not entirely true. There were a couple of stray lines of text that killed a few Cute Bunnies Giving You the Bird, but the mortality rate was much lower.

Of course macros are useful for constructive things too. This neat little open source Windows program is extremely robust. It uses a powerful scripting language that not only lets you create simple keyboard macros, but you can also run programs, manipulate files, receive input from joysticks, control the mouse cursor, modify variables, and then save it either as a script file or an .exe file so AutoHotkey doesn't even have to be installed to use the script.

But for me, since I don't want to learn the scripting language that much, the only thing I really use it for is entering high bit characters, HTML entity references, and of course Cute Bunnies Giving You the Bird. Creating a script is simple, and there's a tool that comes with it that makes it easier.

Here's a script that I made that lets me use Unicode punctuation marks in the name of good typography: the en dash, the em dash, the ellipsis, and actual left/right quotation marks instead of the ambidextrous quotation marks that are on your keyboard (which are called primes actually, and they are only supposed to be used as inch and foot marks). The script is lovingly called "typography_nut", and it's in response to one of the things that I love about Macs.

The Mac already has neat shortcuts like Option-Hyphen to create and en dash. In Windows you have to hold down Alt, type 0150 on the numeric keypad, and then release the Alt key to create one. Once again AutoHotkey comes to the rescue, and this is one of the many reasons why it's one of my massively useful programs. I'll even go as far as saying that this is a must-have script for graphic designers that use a PC.

Anyway, here's the script:

; Script: typography_nut

; This AutoHotkey script lets you quickly input typographical characters without
; having to memorize the Alt code number. The glyph, Alt code number and hotkey
; are listed below. You are welcome to change the hotkeys to whatever you feel
; comfortable with. - Glen Moyes

; Em Dash - Alt 0151
; Ctrl-Hyphen

^-::Send, {ALTDOWN}{Numpad0}{Numpad1}{Numpad5}{Numpad1}{ALTUP}

; En Dash - Alt 0150
; Ctrl-Alt-Hyphen

^!-::Send, {ALTDOWN}{Numpad0}{Numpad1}{Numpad5}{Numpad0}{ALTUP}

; Ellipsis - Alt 0133
; Ctrl-Period

^.::Send, {ALTDOWN}{Numpad0}{Numpad1}{Numpad3}{Numpad3}{ALTUP}

; Left Single Quote - Alt 0145
; Ctrl-[

^[::Send, {ALTDOWN}{Numpad0}{Numpad1}{Numpad4}{Numpad5}{ALTUP}

; Right Single Quote - Alt 0146
; Ctrl-]

^]::Send, {ALTDOWN}{Numpad0}{Numpad1}{Numpad4}{Numpad6}{ALTUP}

; Left Double Quote - Alt 0147
; Ctrl-Alt-[

^![::Send, {ALTDOWN}{Numpad0}{Numpad1}{Numpad4}{Numpad7}{ALTUP}

; Right Double Quote - Alt 0148
; Ctrl-Alt-]

^!]::Send, {ALTDOWN}{Numpad0}{Numpad1}{Numpad4}{Numpad8}{ALTUP}
The script has all the documentation so you can read what the hotkeys are and what they do.

If you want to use this macro, just copy and paste it into a text file called "typography_nut.ahk" and double-click on the file after you've installed AutoHotkey. There will be an icon loaded on your System Tray for every script you have loaded.

Also, make sure that whatever shortcut you choose for your macro isn't also the same shortcut as one that's used in the current application. For example, the above macro uses Ctrl-[ and Ctrl-] as shortcuts, which is an Illustrator shortcut as well, meaning that the shortcut can only be used by the macro. Changing the "^" to a "#" (representing the Windows key) in the script will fix that problem because the Windows key is not used in individual applications, so there won't be any shortcut conflicts. However, you may not like the having the Start Menu pop up when you fumble on a shortcut. And remember that you can turn the macro off at any time easily.

So have fun with this script and have fun with AutoHotkey.


Rife said...

Hi Glen.
My name is Rife,
I can see that you are a guru of AutohotKey and a fan of UT 2004. I'm addicted to UT 2004 too, I have a question. Is it possible to make a macro to use within the UT? I mean I'd like to assign to a key a combination of two or three keys, namely the dodging. I play online UT2004, will the server allow the AHK script?
Thank you very muck.
Regards: Rife

Glen Moyes said...

Yeah, AutoHotkey works with every application that I've used it in, including games. It basically sends a bunch of key presses to the OS very quickly, and it isn't instantaneous, so things like dodging and adrenaline combos will work just fine. I'll just assume that it's standard keyboard input. You can set the delay between key strokes if UT won't recognize it because the keystrokes are too fast.

All of that stuff is done client side and the server won't know how you are doing it. The only time the server might care is if you are spamming messages with macros.

Rife said...

That's very good news.
Will you be so kind and tell me how to do that script? This AHK is all greek to me. I made something like this:

o::Send, LeftLeft


o::SendPlay, LeftLeft

but they don't work... Quite surprisingly when I press "o" within the game it starts the TeamChat and in the chat line the string LeftLeft is put.

Help me please.

Glen Moyes said...

Put curly brackets around it like this:

o::Send, {Left}{Left}

That should do the trick.

Rife said...

Thanks for your patience...

o::Send, {Left}{Left}

It has no effect at all, as if would be defined nothing to key "o".

Glen Moyes said...

Oh, I know what's going on. I bet you have WASD assigned to movement instead of the arrow keys. Either of the following should work:

o::Send, {a}{a}
o::Send, aa

Rife said...

Unfortunately not, I don't use WASD, I use the arrow keys...
Moreover, with this script

o::Send, {Left 2}{RCtrl}
o::Send, {Left}{Left}{RCtrl}

my character only jumps (that's the Right Control), the two left keypresses are ignored.

Rife said...

With this script

o::Send, {a down}{a up}

it moves to left ("a" is assigned to sarfe left), curiously it jumps, almost like a dodging, but it's not good. Ehen I press the "o" I havr to keep it pressed for about half a second to begin to move to the left.
I'm so desperate, I'm sure with AHK is possible to make this macro to work, but it's so complicated.
I've found a macro recorder for AHK, but is doesn't work either.

Glen Moyes said...

Hmm, it may be playing back the keys too fast for UT to recognize. You can try this:

SetKeyDelay, 100
o::Send, {Left}{Left}

The SetKeyDelay is in milliseconds, so 100 is a 10th of a second. Still fast, but slow enough for UT to recognize.

If that still doesn't work you can try doing key up and key downs, just to make sure that UT is recognizing that a key was pressed.

It's possible that instead of queuing up all the input like a word processor does, the game just looks to see what key is being held down. The macro could be playing back so fast that it's slipping in between the frames that the game checks for input, so explicitly saying how long a key is held down may be necessary.

Rife said...

It's strange...
The direction keys defined in AHK are ignorred in UT. Doesn't matter if I define the arrow keys or the WASD.
In this script
o::Send, {Left}{Left}{RCtrl}


o::Send, {a}{a}{RCtrl}
only the RightControk is executed (Jump). When the "o" is pressed in the game only a jump is made.

Glen Moyes said...

Have you tried the macro in a program other than UT? It's possible that you are using a keyboard driver that runs at too low a level for AutoHotkey to pick up. This is especially true for media keyboards that have a lot of buttons on it.

Other then that I can't think of what else to suggest. I don't have UT2004 installed on this machine so I can't tell if AutoHotkey will work on it or not.

Glen Moyes said...

Oh, and are you using a non-QWERTY layout?

Rife said...

Here I'm again.
Things are quite entangled here.
Now I tried with this simple script:

o::Send, {Left}
i::Send, {a}

No double key strokes this time, no dodging, just to make it to move leftwards. (I tried without the curly brackets, as well).

In notepad or any other app it works fine, but not in games. I tried it three different games...
You gave me the clue, my keyboard might be to blame. My keyboard is no that media type. There are two extra buttons on it, a volume up and down key, it has QWERTY layout, and USB connected. I've brought home another keyboard with PS/2 connection, everything goes the same way. As I said before the jump is executed but the moving in four directions are not! Moreover, using the script shown above, in UT if a chat is sarted, when I type my text, and I press the key 'o' the cursor moves to left, respectively instead of 'i' an 'a' is put. That means it is recognised, AHK works in the background.

So, I'm realy confused now, I have no idea what's wrong...

Anyway, thank you very much for your patience, you did your best to help me.

Best Regards:
Rife Fox

Rife said...

It's me again :)

What do you think about this?

Glen Moyes said...

The DirectInput thing makes sense. I've played some games that disable OS shortcuts like the Windows key, Alt-Tab, and so on, so I can see how that would cause problems with AutoHotkey. It sounds like it's checking for scan codes from the keyboard directly for game input (similar to what you have to do for checking gamepad input). So that would explain it as well, and that sounds pretty hard to fake.

Trying what the FAQ suggested might work. I noticed you joined the AutoHotkey forums, and they'll be able to be of more help than I would. :)

If you find something that works, please let me know because I'll probably run into that same problem in the future.

daley said...

Hi Glen,

Sorry to bother you..

I know google is my best friend xD But not today as i cant find what i have been looking for untill i stumbled across this blog <3

Anyway i am looking to put a mouse scroll delay on my WheelUp, WheelDown of 137 milliseconds

so that when i am playing oldskool FPS games i dont over scroll my weapons ^^

This is what i have so far, please tell me were i am going wrong :)


SetKeyDelay, 137
WheelUp::Send, {WheelUp}

SetKeyDelay, 137
WheelDown::Send, {WheelDown}


Thanks in advance

Farrel said...

Your blog entry inspired me to overcome my dislike of having to put quotation marks in after I have typed the words that need to go in quotes. I got sick and tired of having to get the cursor exactly where I needed it and then hitting shift-prime and then going to the right end of a word or phrase and hitting shift-prime.

It is a lot easier to just drag the mouse over all words (especially if one starts with a double click so that it selects in word-long strings at a time and then hit ctrl-prime. Also if I am in a search box sometimes one has to put the words in quotation marks - but you only realize you need it after you get whole bunch of spurious results. In that case, you simply put the cursor anywhere in the box and select all with ctrl-a

Here is my scautohotkey script. It is a simply modification ow what you taught me. For documents it is good to have the proper inverted commas. For search engines and the like it does not matter if one has double primes or quotation marks.

;quotation marks around selection
Send, ^x
; Left Double Quote - Alt 0147
Send, {ALTDOWN}{Numpad0}{Numpad1}{Numpad4}{Numpad7}{ALTUP}^v{ALTDOWN}{Numpad0}{Numpad1}{Numpad4}{Numpad8}{ALTUP}

igor said...

Hi Rife,
I'm also trying to do this script.
My code is:
SetKeyDelay, 100

WinActivate, Unreal Tournament 2004,


Send, {Up} {Up down}


I could not make dodging script sending UP twice . UT program understand like jump, I don't know why.
and you, could you get this ?