检测键盘的焦点并使用Python自动从剪贴板粘贴

问题描述 投票:0回答:1

我正在使用Python,并尝试将剪贴板中已复制的文本自动粘贴到活动文本框或具有键盘焦点的任何内容中。换句话说,例如,当我单击浏览器的地址栏或任何文本编辑器或任何文本框时,该程序应自动从剪贴板粘贴复制的数据。

这在python中可能吗?有什么功能吗?我已经在网站上搜索过,但没有找到任何好的解决方案。

如果可能的话,将进行一个小型演示。

谢谢。

python python-3.x windows automation copy-paste
1个回答
0
投票

您可以使用SendInput抓住当前窗口的焦点并输入字符。这是一个适合您目的的实现。如果焦点对象收集了此类键盘输入,它将取出剪贴板的内容并将其键入。

import time
import string
import ctypes
import ctypes.wintypes

# part one: clipboard text retrieval
CF_UNICODETEXT = 13  # unicode text format; terminates with a linefeed

OpenClipboard = ctypes.windll.user32.OpenClipboard
OpenClipboard.argtypes = ctypes.wintypes.HWND,
OpenClipboard.restype = ctypes.wintypes.BOOL

GetClipboardData = ctypes.windll.user32.GetClipboardData
GetClipboardData.argtypes = ctypes.wintypes.UINT,
GetClipboardData.restype = ctypes.wintypes.HANDLE

GlobalLock = ctypes.windll.kernel32.GlobalLock
GlobalLock.argtypes = ctypes.wintypes.HGLOBAL,
GlobalLock.restype = ctypes.wintypes.LPVOID

GlobalUnlock = ctypes.windll.kernel32.GlobalUnlock
GlobalUnlock.argtypes = ctypes.wintypes.HGLOBAL,
GlobalUnlock.restype = ctypes.wintypes.BOOL

CloseClipboard = ctypes.windll.user32.CloseClipboard
CloseClipboard.argtypes = None
CloseClipboard.restype = ctypes.wintypes.BOOL


def get_clipboard_text():
    text = ""
    if OpenClipboard(None):
        h_clip_mem = GetClipboardData(CF_UNICODETEXT)
        text = ctypes.wstring_at(GlobalLock(h_clip_mem))
        GlobalUnlock(h_clip_mem)
        CloseClipboard()
    return text


CB_TEXT = get_clipboard_text()

# part two: typing it into the focused element of a window

LONG = ctypes.c_long
DWORD = ctypes.c_ulong
ULONG_PTR = ctypes.POINTER(DWORD)
WORD = ctypes.c_ushort

VK_SHIFT = 0x10  # Shift key
# special keys
VK_OEM_1 = 0xBA
VK_OEM_PLUS = 0xBB
VK_OEM_COMMA = 0xBC
VK_OEM_MINUS = 0xBD
VK_OEM_PERIOD = 0xBE
VK_OEM_2 = 0xBF
VK_OEM_3 = 0xC0
VK_OEM_4 = 0xDB
VK_OEM_5 = 0xDC
VK_OEM_6 = 0xDD
VK_OEM_7 = 0xDE
KEYEVENTF_KEYUP = 0x0002  # Releases the key
INPUT_KEYBOARD = 1


UPPER = frozenset('~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:"ZXCVBNM<>?')
LOWER = frozenset("`1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./")
ORDER = string.ascii_letters + string.digits + ' \b\r\t'
ALTER = dict(zip('!@#$%^&*()', '1234567890'))
OTHER = {
    '`': VK_OEM_3, '~': VK_OEM_3, '-': VK_OEM_MINUS, '_': VK_OEM_MINUS,
    '=': VK_OEM_PLUS, '+': VK_OEM_PLUS, '[': VK_OEM_4, '{': VK_OEM_4,
    ']': VK_OEM_6, '}': VK_OEM_6, '\\': VK_OEM_5, '|': VK_OEM_5,
    ';': VK_OEM_1, ':': VK_OEM_1, "'": VK_OEM_7, '"': VK_OEM_7,
    ',': VK_OEM_COMMA, '<': VK_OEM_COMMA, '.': VK_OEM_PERIOD,
    '>': VK_OEM_PERIOD, '/': VK_OEM_2, '?': VK_OEM_2
}


class KEYBDINPUT(ctypes.Structure):
    _fields_ = (
        ('wVk', WORD),
        ('wScan', WORD),
        ('dwFlags', DWORD),
        ('time', DWORD),
        ('dwExtraInfo', ULONG_PTR)
    )


class INPUT(ctypes.Structure):
    _fields_ = ('type', DWORD), ('ki', KEYBDINPUT), ('pad', ctypes.c_ubyte * 8)


def Input(structure):
    return INPUT(INPUT_KEYBOARD, structure)


def KeyboardInput(code, flags):
    return KEYBDINPUT(code, code, flags, 0, None)


def Keyboard(code, flags=0):
    return Input(KeyboardInput(code, flags))


def SendInput(*inputs):
    nInputs = len(inputs)
    LPINPUT = INPUT * nInputs
    pInputs = LPINPUT(*inputs)
    cbSize = ctypes.c_int(ctypes.sizeof(INPUT))
    return ctypes.windll.user32.SendInput(nInputs, pInputs, cbSize)


def stream(string):
    mode = False
    for character in string.replace('\r\n', '\r').replace('\n', '\r'):
        if mode and character in LOWER or not mode and character in UPPER:
            yield Keyboard(VK_SHIFT, mode and KEYEVENTF_KEYUP)
            mode = not mode
        character = ALTER.get(character, character)
        if character in ORDER:
            code = ord(character.upper())
        elif character in OTHER:
            code = OTHER[character]
        else:
            continue
            raise ValueError('Undecoded')
        yield Keyboard(code)
        yield Keyboard(code, KEYEVENTF_KEYUP)
    if mode:
        yield Keyboard(VK_SHIFT, KEYEVENTF_KEYUP)


def send_clipboard():
    for k in stream(CB_TEXT):
        SendInput(k)


def demo(wait=3):
    time.sleep(wait)
    send_clipboard()


if __name__ == '__main__':
    demo()
© www.soinside.com 2019 - 2024. All rights reserved.