Mac-like Special Characters in Windows

I am a bit of a geek for proper punctuation: Em dashes… en dashes… curly quotes… ellipses… I love them all! Prior to 2007, I was a long-time Windows user and was a master of the Alt + numeric code system of entering special characters on that operating system.[1] For nearly a decade, however, I’ve been writing and developing on a Mac and I absolutely love how much easier it is to use special characters. When I started setting up my new Surface Book, I began searching for a way to bring Mac-like special character entry to Windows 10.

Disclaimer: I take absolutely no credit for the code you see below. I will give full credit to the sources as I discuss each. I just wanted to bring it all into one place so it’ll save you a few hours of research to get everything working.

Step 1: Set up AutoHotKey

David Nagel’s solid article on mapping keystrokes in Windows, I introduced me to AutoHotKey. It’s an incredibly powerful program that’s like the lovechild of TextExpander and Quicksilver.

In his article, David walks through the process of getting set up with AutoHotKey:

  1. Download & install it.
  2. Create a new .ahk file (New > AutoHotKey Script in Windows Explorer) and name it whatever you like.[2]
  3. Right-click the script, and choose Edit Script from the context menu.
  4. Enter some keyboard shortcuts (more on that in a moment).
  5. Save the script. I chose to save it to Dropbox to make it portable.
  6. Double click it to run the script.
  7. Open up your favorite writing tool and see your handiwork in action.

Step 2: Create some shortcuts

AutoHotKey is completely scriptable and adding shortcuts is relatively straightforward. There are a few reserved characters, but once you understand what they are it’s pretty easy to get going very quickly. Here’s Dave’s intro example:


In AutoHotKey scripting, “!” stands in for Alt and “+” stands in for Shift. So, to translate:

  1. Alt + - will produce an en dash (–)
  2. Shift Alt + - will produce an em dash (—)

With these two examples, I was able to jump right in and map many of the most common shortcuts I use while writing. Before I got too far, however, I realized I really needed accents, umlauts, and the like. I searched some more and eventually discovered a post in the AutoHotKey forum archive by “Veil” from way back in 2008.

Veil broke his solution into two parts, but I’ve combined them here to make it easier for your to copy into your AutoHotKey script file. This code has provided everything I’ve needed so far, so Veil—wherever you are—thank you!

!VKC0SC029::Return ; grave -> the grave ` accent gave some probs, used the virtualkey + scancode instead
!e::Return ; acute
!i::Return ; circumflex
!t::Return ; tilde
!u::Return ; umlaut

; 1 2 3 4 5 6 7 8 9 1
; 0
; r g G a A c C t T u U

diacritic(regular,accentedCharacters) {
StringSplit, char, accentedCharacters, `,
graveOption := char1
graveShiftOption := char2
acuteOption := char3
acuteShiftOption := char4
circumflexOption := char5
circumflexShiftOption := char6
tildeOption := char7
tildeShiftOption := char8
umlautOption := char9
umlautShiftOption := char10

if (A_PriorHotKey = "!VKC0SC029" && A_TimeSincePriorHotkey < 2000) {
if (GetKeyState("Shift")) {
SendInput % graveShiftOption
} else {
SendInput % graveOption
} else if (A_PriorHotKey = "!e" && A_TimeSincePriorHotkey < 2000) {
if (GetKeyState("Shift")) {
SendInput % acuteShiftOption
} else {
SendInput % acuteOption
} else if (A_PriorHotKey = "!i" && A_TimeSincePriorHotkey < 2000) {
if (GetKeyState("Shift")) {
SendInput % circumflexShiftOption
} else {
SendInput % circumflexOption
} else if (A_PriorHotKey = "!t" && A_TimeSincePriorHotkey < 2000) {
if (GetKeyState("Shift")) {
SendInput % tildeShiftOption
} else {
SendInput % tildeOption
} else if (A_PriorHotKey = "!u" && A_TimeSincePriorHotkey < 2000) {
if (GetKeyState("Shift")) {
SendInput % umlautShiftOption
} else {
SendInput % umlautOption
} else {
if (GetKeyState("Shift") or GetKeyState("Capslock","T")) {
SendInput % "+" regular
} else {
SendInput % regular

; Alt + Shift + key

*!d::altShift("partial difference","Î")
*!x::altShift("approximately equal","Ù")


altShift(accented,accentedShift) {
if (!GetKeyState("Shift")) {
SendInput % accented
} else {
SendInput % accentedShift

; Fix for some CTRL + stuff that may not work
; TODO - Add more as we find them
^a::Send ^{end}^+{home}
^o::WinMenuSelectItem, A, , File, Open

Step 3: Run your script when Windows starts

The last thing you’ll want to do is add your .ahk file to Windows’ startup items. Dave covered that in his piece as well:

  1. Create a shortcut to your file (Right click > Create Shortcut)
  2. Run shell:startup (⊞ Win + R opens the Run dialog or you can type ”Run“ in the Cortana Search Box)
  3. Move your shortcut to the folder that opens.

Once you’ve followed those steps, you’re done. You can update your .ahk scripts needed and just double click it to replace the instance that’s currently running.

If, like me (and Dave and Jonathan and Dan), you’re using Windows after a long time in Mac land and you’re a typography nerd, hopefully you’ll find this helpful. And if you come up with any improvements to the character mapping, please share!

  1. I actually memorized a ton of the codes, much to my amazement. I still remember a few, but I am thankful to have reclaimed a bit of that memory space over the last few years. ↩︎

  2. If you shun the mouse, you can create a text file in your favorite editor and name it with the .ahk extension, but you might run into character encoding issues. I created mine in VS Code as UTF-8, but had to open the file in Notepad and re-save it again to get it to actually work. I never figured out the exact issue, but I thought I’d give you a heads-up. ↩︎


  1. Snook
    I set up a shortcut for – already. :)
    | Permalink
  2. Dave Rupert
    Oh wow. Mac-bindings for special chars? This is a dream.
    | Permalink
  3. Dean Leigh
    This is great! As much as I hate Alt-3 for # on the Mac I hate Alt-0133 for … on W10 more :-)
    | Permalink
  4. Christopher Mallard
    Thank you for that!
    | Permalink
  5. Quentin Roy
    Thanks for the tip! I run into this issue exactly. It took me some time to figure out how to make the grave accent work though. Turned out I had to replace "VKC0SC029" by "sc029".
    | Permalink