DEV Community

Cover image for Windows won't let you own Win+Shift+S. So I hooked the keyboard in Python.
Akhouri Anmol Kumar
Akhouri Anmol Kumar

Posted on

Windows won't let you own Win+Shift+S. So I hooked the keyboard in Python.

Low-level keyboard hooks bypass shell reservations

I wanted one small thing: press Win+Shift+S and get my own screenshot tool instead of Snipping Tool.

That turned into a 7,600-line Python project, and a pile of Windows internals that I couldn't find explained in one place. Here are the four that cost me the most hair.

1. RegisterHotKey can't claim Win+Shift+S

Every tutorial says to use RegisterHotKey. It works for Ctrl+Alt+D. It silently fails for Win+Shift+S, because the shell reserves that combo.

The way around it is a low-level keyboard hook (WH_KEYBOARD_LL, id 13), which sees the key before the shell does:

HOOKPROC = ctypes.WINFUNCTYPE(ctypes.c_ssize_t, ctypes.c_int,
                              ctypes.c_size_t, ctypes.c_ssize_t)

def cb(nCode, wParam, lParam):
    if nCode == 0 and wParam in (0x100, 0x101, 0x104, 0x105):
        kb = ctypes.cast(lParam, ctypes.POINTER(KBDLLHOOKSTRUCT)).contents
        if kb.vkCode == 0x53 and win_down() and shift_down():   # S
            u.keybd_event(0xE8, 0, 0, 0)   # see below
            u.keybd_event(0xE8, 0, 2, 0)
            QTimer.singleShot(0, on_trigger)   # hop back to the Qt thread
            return 1                           # swallow the key
    return u.CallNextHookEx(None, nCode, wParam, lParam)

self._proc = HOOKPROC(cb)   # keep a reference!
hook = u.SetWindowsHookExW(13, self._proc, k.GetModuleHandleW(None), 0)
Enter fullscreen mode Exit fullscreen mode

Three gotchas worth knowing:

  • Keep a reference to the callback. If HOOKPROC(cb) gets garbage-collected, your app crashes on the next keypress. There's no traceback, it just dies.
  • Swallowing S isn't enough. If you eat the keypress and the user then releases Win, Windows opens the Start menu. The fix is to inject an unassigned virtual key (0xE8) so Windows thinks Win was used in a combo.
  • Track the key-up too. If you swallow the key-down, you have to swallow its matching key-up, or apps see an orphaned release. I pulled this into a pure function (snip_hook_decision(...)) with no ctypes in it, so it's unit-testable.

The hook only looks at the specific keys it cares about while Win+Shift are held. Nothing is logged or stored. If you ship a keyboard hook, say that in your README.

2. Keeping your own UI out of your own recording

My screen recorder has a floating control bar. Early on, every video started with the recorder recording itself, which looks amateur.

Windows 10 (2004+) has a one-line fix:

WDA_EXCLUDEFROMCAPTURE = 0x11
ctypes.windll.user32.SetWindowDisplayAffinity(int(widget.winId()),
                                              WDA_EXCLUDEFROMCAPTURE)
Enter fullscreen mode Exit fullscreen mode

The window stays visible to the user but is invisible to capture APIs. It's best-effort on older builds, so wrap it in try/except and move on.

3. System audio in Python: sounddevice can't do it

Recording the microphone is easy. Recording what the PC is playing is not. sounddevice can't do WASAPI loopback.

What worked:

Source Library
Microphone sounddevice
System audio (loopback) PyAudioWPatch
Mixing + muxing into MP4 imageio-ffmpeg (bundles an ffmpeg binary)

The part that matters: don't mix in real time. I record each source to its own WAV on disk, then mix once after the take with ffmpeg's amix. Real-time mixing means two clocks drifting against each other. Post-mixing means a dropped buffer in one stream can't corrupt the other.

I also pad or trim each track to exactly the video duration before mixing, because mic and loopback streams never end at the same millisecond.

4. OCR with zero extra installs

I wanted "select text from a screenshot" without telling users to install Tesseract.

Windows 10/11 already ships an OCR engine: Windows.Media.Ocr. You can reach it from PowerShell, so Python just shells out:

subprocess.run(
    ["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", ps1],
    capture_output=True, timeout=120,
    creationflags=0x08000000,   # CREATE_NO_WINDOW, no console flash
)
Enter fullscreen mode Exit fullscreen mode

The PowerShell script tries the user's language packs first and falls back to whatever recognizer is available. It runs in a QThread, so the UI never freezes. The result: no models to download, no 200 MB dependency, and it works offline.

Small things that made it feel finished

  • Recycle Bin, not delete. os.remove is permanent. SHFileOperationW with FOF_ALLOWUNDO sends files to the Recycle Bin, so "delete capture" is never scary.
  • Atomic settings. Write to settings.json.tmp, then os.replace(). A crash mid-write can't corrupt your config.
  • Single instance. A named mutex (CreateMutexW + check for error 183) stops two copies fighting over the same global hotkeys.
  • Autostart is one registry value under HKCU\...\Run. No installer needed.

Where all this ended up

All of the above lives in ASNIPP, a screenshot tool, screen recorder and editor that sits as a small "Dynamic Island" pill at the top of your screen. The parts I'm proudest of:

  • Screenshots with pen, highlighter, arrows, shapes, text and pixelate (for hiding sensitive info)
  • A color picker with a magnifier loupe, and a pixel ruler
  • Pin-to-screen floating captures
  • Screen recording with system audio and mic, plus live drawing that gets recorded into the video
  • A built-in video editor: trim, speed, reverse, color looks, fades, rotate and GIF export
  • OCR on any capture

It's one 7600+ lines of python code packed into .exe, PyQt6, mss for capture and OpenCV for video. If you've ever wondered how far a python desktop app can go, it's a decent case study.

๐Ÿ‘‰ [https://github.com/Akhouri-Systems/ASNIPP/releases/download/v1.0.0/ASNIPP_v1.zip]


If you've built something with ctypes and Win32, I'd love to hear what bit you. Drop it in the comments.

Top comments (24)

Collapse
 
star123 profile image
Sแด›แด€ส€โญ •

โค๏ธ

Collapse
 
akhourianmolkumar profile image
Akhouri Anmol Kumar •

thanks star for comment
what about your channel?

Collapse
 
star123 profile image
Sแด›แด€ส€โญ •

After Diwali ๐Ÿ˜€

Thread Thread
 
akhourianmolkumar profile image
Akhouri Anmol Kumar •

oh okay channel name StarDev?

Thread Thread
 
star123 profile image
Sแด›แด€ส€โญ •

Idk yet. Bro please share your github link.๐Ÿ˜€

Thread Thread
 
akhourianmolkumar profile image
Akhouri Anmol Kumar •
Thread Thread
 
star123 profile image
Sแด›แด€ส€โญ •

Thanks ๐Ÿฅฐ

Thread Thread
 
akhourianmolkumar profile image
Akhouri Anmol Kumar •

my personal ones is not updated wait let me update it ๐Ÿ˜†

Thread Thread
 
akhourianmolkumar profile image
Akhouri Anmol Kumar •

yeah star now I've updated my personal ones too.

Thread Thread
 
akhourianmolkumar profile image
Akhouri Anmol Kumar •

@star123 can you suggest some upgrades, changes needed in my personal readme to make it look better?

Thread Thread
 
star123 profile image
Sแด›แด€ส€โญ •

Very beautiful ๐Ÿ˜€

Thread Thread
 
akhourianmolkumar profile image
Akhouri Anmol Kumar •

what?

Thread Thread
 
akhourianmolkumar profile image
Akhouri Anmol Kumar •

@star123 if you want to join Akhouri Systems server then you can, currently it is not active or honestly it is dead because my goal is to first collect some top individuals in the server and then start the server 24/7 like big companyy servers are... and currently it has @effessdev, puneet kumar mishra, @nyaomaru @xulingfeng
discord.gg/Hb7Mk8vh5
Akhouri Systems is ready to welcome you ๐Ÿคฒ

Thread Thread
 
akhourianmolkumar profile image
Akhouri Anmol Kumar •

@effessdev bro can you come online in discord?

Thread Thread
 
effessdev profile image
EffessDev •

Ok...

Thread Thread
 
akhourianmolkumar profile image
Akhouri Anmol Kumar •

ok..

Thread Thread
 
effessdev profile image
EffessDev •

You mean youtube channel right?

Thread Thread
 
akhourianmolkumar profile image
Akhouri Anmol Kumar •

yeah star wants to open a channel so I was suggesting a name, like I also love these channel stuff But I failed but seeing her trying I'm motivated to help her.

Thread Thread
 
star123 profile image
Sแด›แด€ส€โญ •

โค๏ธ

Thread Thread
 
effessdev profile image
EffessDev •

I also tried a couple of times (a guitar covers channel) but recording was too
hard without proper equipment so I gave up.

Thread Thread
 
star123 profile image
Sแด›แด€ส€โญ • • Edited

So I give up.๐Ÿค”

Collapse
 
pengeszikra profile image
Peter Vivo •

Good to remember how can we will solve this kind of promblems! โœŒ๏ธ
I always fight with windows keyboard settings ( forced company laptop ) until I give up the fight. My trick: I use AutoHotkey program to redefine my keyboard to
capsLock + ; = รฉ
capsLock + ' = รก
... and so on
Because my main problem is the hungarian languge special character. In chat with my hungarian collegues I like to use full hungarian char set, but I always use english keyboard set and really hate to install multiple language keyboard set because windows do not saw which keyboard currently use, plus many program using english keyboard shortkeys. The whole question is so anoying.

Collapse
 
koda2026 profile image
Harun - solo dev •

Bro please change profile pic ๐Ÿ–ผ๏ธ ๐Ÿคฃ

Collapse
 
technogamerz profile image
๐“๐ก๐ž ๐‹๐š๐ณ๐ฒ ๐†๐ข๐ซ๐ฅ • • Edited

You changed your profile image! Wow!! :D