I'm making a custom paste script and need to block OS pasting on ctrl+v so that I can replace it with my own behaviour.
This is some test code that is supposed to block OS pasting but it doesn't:
import keyboard
block_os_paste = False # Flag to toggle blocking
print("Unblocked OS Ctrl+V. Default behavior.")
def toggle_blocking():
"""Toggle the blocking of OS Ctrl+V."""
global block_os_paste
block_os_paste = not block_os_paste
if block_os_paste:
print("Blocking OS Ctrl+V. Custom behavior enabled.")
else:
print("Unblocking OS Ctrl+V. Default behavior restored.")
def handle_ctrl_v(e):
"""Custom handler for Ctrl+V."""
if block_os_paste:
e.suppress = True
print("cookies") # Custom behavior
else:
keyboard.send("ctrl+v") # Send the default behavior
keyboard.add_hotkey("f9", toggle_blocking) # Assign hotkey to toggle blocking
keyboard.add_hotkey("ctrl+v", lambda: handle_ctrl_v(False)) # Intercept Ctrl+V
keyboard.wait("esc") # Exit the script when "Esc" is pressed
I have tried many other ways as well like using global keyboard listeners from pynput but nothing I've come up with is working. Any help would be greatly appreciated.
For anyone else looking into this I found the solution. Unfortunately it is extremely aids so implementing my own functionality into it and customizing it will be horrible. But possible.
import ctypes
import ctypes.wintypes
import keyboard
import win32api
import win32con
# Define virtual key codes if not available in win32con
VK_V = 0x56 # Virtual key code for 'V'
VK_ESCAPE = 0x1B # Virtual key code for 'Esc'
# Variable to toggle blocking
block_os_paste = False
hHook = None # Initialize hHook as a global variable
def toggle_blocking():
"""Toggle the blocking of OS Ctrl+V."""
global block_os_paste
block_os_paste = not block_os_paste
if block_os_paste:
print("Blocking OS Ctrl+V")
else:
print("Unblocking OS Ctrl+V")
# Hook callback prototype
def low_level_keyboard_handler(nCode, wParam, lParam):
"""Low-level keyboard hook handler."""
if nCode == 0: # If wParam is WM_KEYDOWN or WM_KEYUP
# Extract virtual key code from lParam
key_info = ctypes.cast(lParam, ctypes.POINTER(ctypes.c_long)).contents
vk_code = key_info.value # Extract the virtual key code
isCtrlPressed = win32api.GetAsyncKeyState(win32con.VK_CONTROL) < 0
# Check for only WM_KEYDOWN
if wParam == win32con.WM_KEYDOWN:
if (vk_code == VK_V) and isCtrlPressed:
if block_os_paste:
print("Pasting has been blocked!") # Print only once
return 1 # Block the Ctrl+V event
# Check for Esc key press to exit
if vk_code == VK_ESCAPE:
print("Exiting...")
ctypes.windll.user32.PostQuitMessage(0) # Exit the message loop
return ctypes.windll.user32.CallNextHookEx(hHook, nCode, wParam, lParam)
# Set keyboard hook
def set_keyboard_hook():
"""Set a low-level keyboard hook."""
global hHook
WH_KEYBOARD_LL = 13
# Use ctypes.CFUNCTYPE to define the correct function pointer
LOW_LEVEL_KEYBOARD_HOOK = ctypes.WINFUNCTYPE(ctypes.c_long, ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_int))
low_level_handler = LOW_LEVEL_KEYBOARD_HOOK(low_level_keyboard_handler)
hHook = ctypes.windll.user32.SetWindowsHookExA(WH_KEYBOARD_LL, low_level_handler, None, 0)
msg = ctypes.wintypes.MSG()
while ctypes.windll.user32.GetMessageA(ctypes.byref(msg), 0, 0, 0) != 0:
ctypes.windll.user32.TranslateMessage(ctypes.byref(msg))
ctypes.windll.user32.DispatchMessageA(ctypes.byref(msg))
if __name__ == "__main__":
keyboard.add_hotkey('f9', toggle_blocking)
print("Press F9 to toggle blocking, Esc to exit.")
try:
set_keyboard_hook() # Set the keyboard hook
except KeyboardInterrupt:
pass
finally:
if hHook is not None:
ctypes.windll.user32.UnhookWindowsHookEx(hHook)
This will block pasting and replace it with printing a statement that prints on key down. Can alter it so that it does something on key down and something else on key up.