Last active
April 28, 2024 17:10
-
-
Save willwade/2ee856037aedd8974a9d9f7e7747e925 to your computer and use it in GitHub Desktop.
capture keys - mac and Win code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from Quartz import * | |
from PyObjCTools.AppHelper import runConsoleEventLoop | |
def key_callback(proxy, type_, event, refcon): | |
# Get the key code | |
key_code = CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) | |
print("Key pressed:", key_code) | |
return event | |
def main(): | |
tap = CGEventTapCreate( | |
kCGSessionEventTap, | |
kCGHeadInsertEventTap, | |
kCGEventTapOptionDefault, | |
CGEventMaskBit(kCGEventKeyDown), # Listening only to key down events | |
key_callback, | |
None | |
) | |
if tap: | |
runloop_source = CFMachPortCreateRunLoopSource(None, tap, 0) | |
CFRunLoopAddSource(CFRunLoopGetCurrent(), runloop_source, kCFRunLoopCommonModes) | |
CGEventTapEnable(tap, True) | |
runConsoleEventLoop() | |
else: | |
print("Failed to create event tap") | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This uses the keyboard libarry. On a mac you need to run this as sudo | |
import sys | |
import keyboard | |
from PyQt5.QtWidgets import QApplication, QDialog | |
from PyQt5.QtCore import QThread, pyqtSignal | |
class KeyListenerThread(QThread): | |
keyPressed = pyqtSignal(str) | |
def run(self): | |
keyboard.hook(self.on_press) | |
self.exec_() # Start the Qt event loop | |
def on_press(self, event): | |
try: | |
# Emit the character pressed if it's a character key | |
if event.name and len(event.name) == 1: | |
self.keyPressed.emit(event.name) | |
else: | |
# Emit the key name if it's a special key (e.g., 'space') | |
self.keyPressed.emit(event.name) | |
except AttributeError: | |
# Fallback if event handling fails | |
self.keyPressed.emit('unknown key') | |
class MainWindow(QDialog): | |
def __init__(self): | |
super().__init__() | |
self.setWindowTitle("Key Listener Example") | |
self.resize(300, 200) | |
# Initialize and start the key listener thread | |
self.listenerThread = KeyListenerThread() | |
self.listenerThread.keyPressed.connect(self.handleKeyPress) | |
self.listenerThread.start() | |
def handleKeyPress(self, key): | |
print(f"Key pressed: {key}") | |
def closeEvent(self, event): | |
# Ensure all hooks are cleared when the window is closed | |
keyboard.unhook_all() | |
self.listenerThread.quit() | |
self.listenerThread.wait() | |
super().closeEvent(event) | |
if __name__ == "__main__": | |
app = QApplication(sys.argv) | |
mainWindow = MainWindow() | |
mainWindow.show() | |
sys.exit(app.exec_()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ctypes | |
from ctypes import wintypes | |
import win32con | |
user32 = ctypes.WinDLL('user32', use_last_error=True) | |
# Define necessary structures | |
class KBDLLHOOKSTRUCT(ctypes.Structure): | |
_fields_ = [("vkCode", wintypes.DWORD), | |
("scanCode", wintypes.DWORD), | |
("flags", wintypes.DWORD), | |
("time", wintypes.DWORD), | |
("dwExtraInfo", wintypes.ULONG_PTR)] | |
# Define the callback function | |
def low_level_keyboard_proc(nCode, wParam, lParam): | |
if nCode == win32con.HC_ACTION: | |
if wParam == win32con.WM_KEYDOWN: | |
kb = ctypes.cast(lParam, ctypes.POINTER(KBDLLHOOKSTRUCT)).contents | |
print(f"Key Pressed: {kb.vkCode}") | |
return user32.CallNextHookEx(None, nCode, wParam, lParam) | |
# Set hook | |
HOOKPROC = ctypes.WINFUNCTYPE(wintypes.LPARAM, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM) | |
pointer = HOOKPROC(low_level_keyboard_proc) | |
hook_id = user32.SetWindowsHookExA(win32con.WH_KEYBOARD_LL, pointer, 0, 0) | |
# Message loop to keep the hook active | |
msg = wintypes.MSG() | |
while user32.GetMessageW(ctypes.byref(msg), 0, 0, 0) != 0: | |
user32.TranslateMessage(ctypes.byref(msg)) | |
user32.DispatchMessageW(ctypes.byref(msg)) | |
# Unhook on exit | |
user32.UnhookWindowsHookEx(hook_id) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment