python 剪贴板 读取/写入中文乱码

132 阅读2分钟

python 剪贴板 读取/写入中文乱码

涉及 str.encode() 和 bytes.decode() 搭配encoding, errors参数的具体使用

写入测试

import ctypes
import ctypes.wintypes
import clipboard

# Define necessary constants
CF_TEXT = 1
CF_LOCALE = 16
CF_UNICODETEXT = 13
GMEM_MOVEABLE = 0x0002
GMEM_ZEROINIT = 0x0040
GHND = GMEM_MOVEABLE | GMEM_ZEROINIT

# Set up the required functions
user32 = ctypes.windll.user32
kernel32 = ctypes.windll.kernel32

GlobalAlloc = kernel32.GlobalAlloc
# GlobalAlloc.argtypes = ctypes.wintypes.UINT, ctypes.wintypes.SIZE_T
GlobalAlloc.argtypes = ctypes.wintypes.UINT, ctypes.c_size_t
GlobalAlloc.restype = ctypes.wintypes.HGLOBAL

GlobalLock = kernel32.GlobalLock
GlobalLock.argtypes = ctypes.wintypes.HGLOBAL,
GlobalLock.restype = ctypes.c_void_p

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

memcpy = ctypes.cdll.msvcrt.memcpy
memcpy.argtypes = ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t

GlobalFree = kernel32.GlobalFree
GlobalFree.argtypes = ctypes.wintypes.HGLOBAL,
GlobalFree.restype = ctypes.wintypes.HGLOBAL

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

EmptyClipboard = user32.EmptyClipboard
EmptyClipboard.argtypes = None
EmptyClipboard.restype = ctypes.wintypes.BOOL

SetClipboardData = user32.SetClipboardData
SetClipboardData.argtypes = ctypes.wintypes.UINT, ctypes.wintypes.HANDLE
SetClipboardData.restype = ctypes.wintypes.HANDLE

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

# Function to set the clipboard text


def set_clipboard_text(text):
    try:
        OpenClipboard(None)
        EmptyClipboard()

        # Allocate global memory and lock it
        data = ctypes.create_string_buffer(text.encode('utf-8'))
        handle = GlobalAlloc(GHND, len(data))
        data_ptr = GlobalLock(handle)

        # Copy data to global memory
        memcpy(data_ptr, ctypes.addressof(data), len(data))

        # Unlock and set clipboard data
        GlobalUnlock(handle)
        SetClipboardData(CF_TEXT, handle)
    finally:
        CloseClipboard()


# Example usage
text_to_copy = "Hello, Clipboard!"
text_to_copy = "Ae测〇试ñçÁïºou"
set_clipboard_text(text_to_copy)

text = clipboard.paste()
print('paste', text)

读取测试

import ctypes
import ctypes.wintypes
import clipboard

# Define necessary constants
CF_TEXT = 1
GMEM_DDESHARE = 0x2000

# Set up the required functions
user32 = ctypes.windll.user32
kernel32 = ctypes.windll.kernel32

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

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

GlobalLock = kernel32.GlobalLock
GlobalLock.argtypes = ctypes.wintypes.HANDLE,
GlobalLock.restype = ctypes.c_void_p

GlobalUnlock = kernel32.GlobalUnlock
GlobalUnlock.argtypes = ctypes.wintypes.HANDLE,
GlobalUnlock.restype = ctypes.wintypes.BOOL

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

# Function to get the clipboard text

def test_encode(text, enc, err):
    try:
        b = text.encode(enc, err)
        s = b.decode(enc, err)
        print('encode', enc, err[0], s, b)
    except:
        pass
    
def test_decode(text, enc, err):
    try:
        s = text.decode(enc, err)
        print('decode', enc, err[0], s)
    except:
        pass
    # except Exception as e:
    #     print('exp', type(e), e)


def get_clipboard_text():
    try:
        OpenClipboard(None)
        handle = GetClipboardData(CF_TEXT)
        data = GlobalLock(handle)
        text = ctypes.c_char_p(data).value
        GlobalUnlock(handle)
        print('repr', repr(text))
        print('text', text)
        #for enc in ['ascii', 'cp1252', 'latin1', 'latin9', 'gb2312', 'gbk', 'gb18030', 'utf-7', 'utf-8', 'utf-8-sig', 'utf-16']:
        for enc in ['ascii', 'cp1252', 'gb2312', 'gb18030', 'utf-8']:
            for err in ['ignore', 'replace', 'backslashreplace', 'surrogateescape'][0:-1]:
                test_decode(text, enc, err)
        return text.decode('utf-8', 'replace')
    finally:
        CloseClipboard()

text = 'Ae测〇试ñçÁïºou'

print('repr', repr(text))
print('text', text)
#for enc in ['ascii', 'cp1252', 'latin1', 'latin9', 'gb2312', 'gb18030', 'gbk', 'utf-7', 'utf-8', 'utf-8-sig', 'utf-16']:
for enc in ['ascii', 'cp1252', 'gb2312', 'gb18030', 'utf-8']:
    for err in ['ignore', 'replace', 'backslashreplace', 'surrogateescape', 'xmlcharrefreplace', 'namereplace'][0:-3]:
        test_encode(text, enc, err)

# input('pause')

text = clipboard.paste()
print('cb', repr(text))
print('cb', text)

# Example usage
clipboard_text = get_clipboard_text()
print(repr(clipboard_text))
print(f"Clipboard text: {clipboard_text}")