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



我已经看到了这个问题,我遵循了每个步骤,更改代码以满足我的要求,即python3,枕头和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()

这是我脚本中剥离的代码,我认为在我要求的问题上是相同的代码。执行后,它应将当前桌面复制到剪贴板。我得到了这个:

File "C:UsersGcqDocumentspythonScreenScreen.py", line 132, in shot
    user32.OpenClipboard()
ValueError: Procedure probably called with not enough arguments (4 bytes missing)

很抱歉,我在这里问这个简单的问题,但是我真的不知道什么是失败,而CTYPES也不是我的事。

该示例使用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()

whew。显然,与ctypes相比,win32clipboard库确实简化了一些事情。您尝试简单地用另一个替换一个是不正确的。

所以我启动了我的Windows虚拟机,安装了枕头并重写了您的程序,从其他两个答案中学习:

import io
import ctypes
msvcrt = ctypes.cdll.msvcrt
kernel32 = ctypes.windll.kernel32
user32 = ctypes.windll.user32
from PIL import ImageGrab
img = ImageGrab.grab()
output = io.BytesIO()
img.convert('RGB').save(output, 'BMP')
data = output.getvalue()[14:]
output.close()
CF_DIB = 8
GMEM_MOVEABLE = 0x0002
global_mem = kernel32.GlobalAlloc(GMEM_MOVEABLE, len(data))
global_data = kernel32.GlobalLock(global_mem)
msvcrt.memcpy(ctypes.c_char_p(global_data), data, len(data))
kernel32.GlobalUnlock(global_mem)
user32.OpenClipboard(None)
user32.EmptyClipboard()
user32.SetClipboardData(CF_DIB, global_mem)
user32.CloseClipboard()

最新更新