[英]Python - Take screenshot including mouse cursor
我目前正在嘗試使用PIL.ImageGrab
截取包含鼠標光標的屏幕截圖。
這是我的代碼:
import ctypes, win32gui, win32ui
from PIL import Image, ImageGrab
size = round(ctypes.windll.shcore.GetScaleFactorForDevice(0) / 100 * 32)
cursor = get_cursor()
pixdata = cursor.load()
minsize = [size, None]
width, height = cursor.size
for y in range(height):
for x in range(width):
if pixdata[x, y] == (0, 0, 0, 255):
pixdata[x, y] = (0, 0, 0, 0)
else:
if minsize[1] == None:
minsize[1] = y
if x < minsize[0]:
minsize[0] = x
ratio = ctypes.windll.shcore.GetScaleFactorForDevice(0) / 100
img = ImageGrab.grab(bbox=None, include_layered_windows=True)
pos_win = win32gui.GetCursorPos()
pos = (round(pos_win[0]*ratio), round(pos_win[1]*ratio))
img.paste(cursor, pos, cursor)
img.save("screenshot.png")
這是我的get_cursor()
函數:
def get_cursor():
hcursor = win32gui.GetCursorInfo()[1]
hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
hbmp = win32ui.CreateBitmap()
hbmp.CreateCompatibleBitmap(hdc, 36, 36)
hdc = hdc.CreateCompatibleDC()
hdc.SelectObject(hbmp)
hdc.DrawIcon((0,0), hcursor)
bmpinfo = hbmp.GetInfo()
bmpbytes = hbmp.GetBitmapBits()
bmpstr = hbmp.GetBitmapBits(True)
cursor = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1).convert("RGBA")
win32gui.DestroyIcon(hcursor)
win32gui.DeleteObject(hbmp.GetHandle())
hdc.DeleteDC()
pixdata = cursor.load()
minsize = [32, None]
width, height = cursor.size
for y in range(height):
for x in range(width):
if pixdata[x, y] == (0, 0, 0, 255):
pixdata[x, y] = (0, 0, 0, 0)
else:
if minsize[1] == None:
minsize[1] = y
if x < minsize[0]:
minsize[0] = x
return cursor
問題是某些光標沒有粘貼在正確的位置,因為它們的位置左側有這樣的像素(不要注意質量)。
如何正確放置光標圖像(或以其他方式解決問題)?
鼠標光標有一個“熱點”,它是相對於光標位置放置圖像的位置。這個“熱點”可以這樣獲得:
import win32gui
hcursor = win32gui.GetCursorInfo()[1]
hotspot = win32gui.GetIconInfo(hcursor)[1:3]
所以完整的代碼是:
import ctypes, win32gui, win32ui
from PIL import Image, ImageGrab
def get_cursor():
hcursor = win32gui.GetCursorInfo()[1]
hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
hbmp = win32ui.CreateBitmap()
hbmp.CreateCompatibleBitmap(hdc, 36, 36)
hdc = hdc.CreateCompatibleDC()
hdc.SelectObject(hbmp)
hdc.DrawIcon((0,0), hcursor)
bmpinfo = hbmp.GetInfo()
bmpstr = hbmp.GetBitmapBits(True)
cursor = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1).convert("RGBA")
win32gui.DestroyIcon(hcursor)
win32gui.DeleteObject(hbmp.GetHandle())
hdc.DeleteDC()
pixdata = cursor.load()
width, height = cursor.size
for y in range(height):
for x in range(width):
if pixdata[x, y] == (0, 0, 0, 255):
pixdata[x, y] = (0, 0, 0, 0)
hotspot = win32gui.GetIconInfo(hcursor)[1:3]
return (cursor, hotspot)
cursor, (hotspotx, hotspoty) = get_cursor()
cursor.save("cursor.png")
ratio = ctypes.windll.shcore.GetScaleFactorForDevice(0) / 100
img = ImageGrab.grab(bbox=None, include_layered_windows=True)
pos_win = win32gui.GetCursorPos()
pos = (round(pos_win[0]*ratio - hotspotx), round(pos_win[1]*ratio - hotspoty))
img.paste(cursor, pos, cursor)
img.save("screenshot.png")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.