Vì vậy, tôi đang cố gắng tìm ra cách đăng ký móc khóa bàn phím chung bằng Python. Từ những gì tôi đã đọc, nó có vẻ là okay để không có gọi lại trong một DLL. Nếu bạn sử dụng WH_KEYBOARD_LL. Tôi không thể xác nhận rằng chắc chắn nhưng tôi thấy nó khuyến khích tôi không nhận được một lỗi 1428 như tôi làm gì nếu tôi cố gắng để móc vào nói WH_CBT
.Áp dụng móc khóa bàn phím mức thấp với Python và SetWindowsHookExA
Tôi nhận được một móc xử lý nhưng không có gì xuất hiện khi tôi nhấn các nút trên bàn phím như tôi mong đợi.
Bất kỳ ý tưởng nào về lý do tại sao cuộc gọi lại của tôi không được gọi? Hoặc điều này thậm chí có thể?
Mã liên quan:
import time
import string
import ctypes
import functools
import atexit
import pythoncom
from ctypes import windll
hookID = 0
class Keyboard(object):
KEY_EVENT_DOWN = 0
KEY_EVENT_UP = 2
KEY_ENTER = 2
KEY_SHIFT = 16
KEY_SPACE = 32
HOOK_ACTION = 13
HOOK_KEYBOARD = 13
HOOK_KEYDOWN = 0x100
HOOK_KEYUP = 0x101
class Hook:
'''Holds general hook information'''
def __init__(self):
self.hook = 0
self.struct = None
class HookStruct(ctypes.Structure):
'''Structure that windows returns for keyboard events'''
__fields__ = [
('keycode', ctypes.c_long),
('scancode', ctypes.c_long),
('flags', ctypes.c_long),
('time', ctypes.c_long),
('info', ctypes.POINTER(ctypes.c_ulong))
]
def ascii_to_keycode(self, char):
return windll.user32.VkKeyScanA(ord(char))
def inject_key_down(self, keycode):
scancode = windll.user32.MapVirtualKeyA(keycode, 0)
windll.user32.keybd_event(keycode, scancode, Keyboard.KEY_EVENT_DOWN, 0)
def inject_key_up(self, keycode):
scan = windll.user32.MapVirtualKeyA(keycode, 0)
windll.user32.keybd_event(keycode, scan, Keyboard.KEY_EVENT_UP, 0)
def inject_key_press(self, keycode, pause=0.05):
self.inject_key_down(keycode)
time.sleep(pause)
self.inject_key_up(keycode)
def inject_sequence(self, seq, pause=0.05):
for key in seq:
if key == ' ':
self.inject_key_press(Keyboard.KEY_SPACE, pause)
elif key == '\n':
self.inject_key_press(Keyboard.KEY_ENTER, pause)
else:
if key in string.ascii_uppercase:
self.inject_key_down(Keyboard.KEY_SHIFT)
self.inject_key_press(self.ascii_to_keycode(key), pause)
self.inject_key_up(Keyboard.KEY_SHIFT)
else:
self.inject_key_press(self.ascii_to_keycode(key), pause)
def _win32_copy_mem(self, dest, src):
src = ctypes.c_void_p(src)
windll.kernel32.RtlMoveMemory(ctypes.addressof(dest), src, ctypes.sizeof(dest))
def _win32_get_last_error(self):
return windll.kernel32.GetLastError()
def _win32_get_module(self, mname):
return windll.kernel32.GetModuleHandleA(mname)
def _win32_call_next_hook(self, id, code, wparam, lparam):
return windll.kernel32.CallNextHookEx(id, code, wparam, lparam)
def _win32_set_hook(self, id, callback, module, thread):
callback_decl = ctypes.WINFUNCTYPE(ctypes.c_long, ctypes.c_long, ctypes.c_long, ctypes.c_long)
return windll.user32.SetWindowsHookExA(id, callback_decl(callback), module, thread)
def _win32_unhook(self, id):
return windll.user32.UnhookWindowsHookEx(id)
def keyboard_event(self, data):
print data.scancode
return False
def capture_input(self):
self.hook = Keyboard.Hook()
self.hook.struct = Keyboard.HookStruct()
def low_level_keyboard_proc(code, event_type, kb_data_ptr):
# win32 spec says return result of CallNextHookEx if code is less than 0
if code < 0:
return self._win32_call_next_hook(self.hook.hook, code, event_type, kb_data_ptr)
if code == Keyboard.HOOK_ACTION:
# copy data from struct into Python structure
self._win32_copy_mem(self.hook.struct, kb_data_ptr)
# only call other handlers if we return false from our handler - allows to stop processing of keys
if self.keyboard_event(self.hook.struct):
return self._win32_call_next_hook(self.hook.hook, code, event_type, kb_data_ptr)
# register hook
try:
hookId = self.hook.hook = self._win32_set_hook(Keyboard.HOOK_KEYBOARD, low_level_keyboard_proc, self._win32_get_module(0), 0)
if self.hook.hook == 0:
print 'Error - ', self._win32_get_last_error()
else:
print 'Hook ID - ', self.hook.hook
except Exception, error:
print error
# unregister hook if python exits
atexit.register(functools.partial(self._win32_unhook, self.hook.hook))
def end_capture(self):
if self.hook.hook:
return self._win32_unhook(self.hook.hook)
kb = Keyboard()#kb.inject_sequence('This is a test\nand tHis is line 2')
kb.capture_input()
pythoncom.PumpMessages()
kb.end_capture()
Tốt, súc tích, trả lời –
Sau nhiều giờ thử một loạt các cách tiếp cận khác nhau, điều này có vẻ là cách hoàn hảo nếu bạn cần nghe bàn phím ở mức thấp (không có bàn điều khiển tập trung). Cảm ơn! –
Nó hoạt động tốt nhưng tôi nhận được 'key_code' như '240518168740'. Tôi nghĩ rằng nó sẽ trả về các giá trị như [this] (https://msdn.microsoft.com/en-us/library/dd375731%28v=vs.85%29.aspx). Vì vậy, làm cách nào để chuyển đổi thành ký tự/khóa thực tế được nhấn? –