将 PIL/PILLOW 图像复制到 Windows 剪贴板

gcq*_*gcq 3 python winapi ctypes python-imaging-library

我已经看到这个问题,我遵循了每一步,更改代码以满足我的要求,即 Python3、Pillow 和 ctypes。库越少越好。

import ctypes
from PIL import ImageGrab, Image
from io import BytesIO

user32 = ctypes.windll.user32

img = ImageGrab.grab()
output = BytesIO()
img.convert("RGB").save(output, "BMP")
data = output.getvalue()[14:]
output.close()

user32.OpenClipboard()
user32.EmptyClipboard()
user32.SetClipboardData(user32.CF_DIB, data)
user32.CloseClipboard()
Run Code Online (Sandbox Code Playgroud)

这是从我的脚本中删除的代码,我认为它与移植到我的要求的问题中的代码相同。执行时,它应该将当前桌面复制到剪贴板。我得到这个:

File "C:\Users\Gcq\Documents\python\Screen\Screen.py", line 132, in shot
    user32.OpenClipboard()
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
Run Code Online (Sandbox Code Playgroud)

很抱歉我在这里问这样一个(可能)简单的问题,但我真的不知道什么失败了,而且 ctypes 不是我的菜。

小智 6

该示例使用的pywin32是 Win32 API 的 Python 包装器,它隐藏了一些低级细节,如果您想使用,则需要自己处理ctypes

这是使用的方法ctypes,它添加了创建全局分配的缓冲区并将其复制data到该缓冲区的功能:

#!python

from PIL import Image
#from cStringIO import StringIO
from io import BytesIO
from ctypes import *
from ctypes.wintypes import *

HGLOBAL = HANDLE
SIZE_T = c_size_t
GHND = 0x0042
GMEM_SHARE = 0x2000

GlobalAlloc = windll.kernel32.GlobalAlloc
GlobalAlloc.restype = HGLOBAL
GlobalAlloc.argtypes = [UINT, SIZE_T]

GlobalLock = windll.kernel32.GlobalLock
GlobalLock.restype = LPVOID
GlobalLock.argtypes = [HGLOBAL]

GlobalUnlock = windll.kernel32.GlobalUnlock
GlobalUnlock.restype = BOOL
GlobalUnlock.argtypes = [HGLOBAL]

CF_DIB = 8

OpenClipboard = windll.user32.OpenClipboard
OpenClipboard.restype = BOOL 
OpenClipboard.argtypes = [HWND]

EmptyClipboard = windll.user32.EmptyClipboard
EmptyClipboard.restype = BOOL
EmptyClipboard.argtypes = None

SetClipboardData = windll.user32.SetClipboardData
SetClipboardData.restype = HANDLE
SetClipboardData.argtypes = [UINT, HANDLE]

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

#################################################

image = Image.new("RGB", (200, 200), (255, 0, 0))

#output = StringIO()
output = BytesIO()
image.convert("RGB").save(output, "BMP")
data = output.getvalue()[14:]
output.close()

hData = GlobalAlloc(GHND | GMEM_SHARE, len(data))
pData = GlobalLock(hData)
memmove(pData, data, len(data))
GlobalUnlock(hData)

OpenClipboard(None)
EmptyClipboard()
SetClipboardData(CF_DIB, pData)
CloseClipboard()
Run Code Online (Sandbox Code Playgroud)