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. I set up a shortcut for – already. :)
  2. Oh wow. Mac-bindings for special chars? This is a dream.
  3. Thîs M増style áutø–key $k®¡pt for Wïndows is wöndérfül! Thanks @AaronGustafson…
  4. Thîs M増style áutø–key $k®¡pt for Wïndows is wöndérfül! Thanks @AaronGustafson…
  5. This is great! As much as I hate Alt-3 for # on the Mac I hate Alt-0133 for … on W10 more :-)
  6. I knew the tool but not "run shell:startup" - that is neat indeed, hard to find the folder these days…
  7. If you are a designer working in a Windows office, this will save your life: iOS's typographic keyboard shortcuts with @autohotkey_…
  8. 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".
  9. When I’ve used windows I’ve literally installed key binding software that changes accents to Mac defaults…


  1. Dan Mall


Note: These are comments exported from my old blog. Going forward, replies to my posts are only possible via webmentions.
  1. Craig Patik

    This is great and I've been wanting something like this for years.

    If you run across a problem where this override some control-key shortcuts (e.g. control-A writes an 'a' character instead of performing "Select All"), be sure to open the gist, click the Raw button, and copy that script. Don't just copy the script straight from this page; the loss of formatting seems to affect it.

    1. Aaron Gustafson

      I actually updated the Gist last week when Dave Rupert ran into the same issue. I fixed Ctrl+A & Ctrl+O. As I find more, I'll continue to update the Gist.

      1. Craig Patik

        I just updated my post. The problem was that I copied the text directly from this blog post rather than opening the gist and viewing the raw code. The gist itself works great. Apologies for the confusion.

        1. Aaron Gustafson

          Yay! I will get the code in the post updated too. I think the ServiceWorker is in the way :-)

          1. Craig Patik

            I created a fork of your gist with real characters in place of words like "omega", "integral", "approximately equal", etc. Only the word "Apple" remains since AFAIK that logo doesn't render in Windows without a special font.

            I also made the control shortcuts work a little better, e.g. Ctrl-A in Chrome wouldn't select an entire (read-only) page's contents. I added support for Ctrl-N (new window) and Ctrl-Y (redo).


  2. Shaz De Jav

    Absolutely great work Aaron, A big thank you.
    I just have one question before installing...Does the script over-ride the shortcuts already in play on programs like Adobe Premiere? For instance while editing i have ALT+SHIFT+V setup for "Paste Attributes". But when im in the Text Tool i would like to write possible alt character like "^" using the same keystrokes.

    1. Aaron Gustafson

      I have not tested that, so I can’t say for sure. My guess would be that it might interfere. But you can test and re-map if necessary.

  3. Daniel Wilson

    Hi! I'm having an issue where this script results in — being outputted for the en and em dashes. ‰ for alt+shift+e. Any idea what I'm doing wrong?

    1. Aaron Gustafson

      My first thought is that your document may not be UTF-8. It sounds like a character encoding issue.

      1. Daniel Wilson

        I thought so as well but the document shows as UTF-8 encoded in vscode—for whatever reason, it's definitely not registering as such in AutoHotkey. Strange.

  4. Kevin Kelly

    When I run the script I get an error message for "invalid hotkey" because of VKC0SC029. Anyone else have that problem? It's got something to do with how the grave key works. I have an American keyboard.