学习一门语言最好的方法便是实践,想要拿Python写一个截图工具,网上一搜资料果然已经很多,前辈们都已经做的很到位了。现在就一步步来学习一下:
首先学习截图整个桌面的方法,可以使用Python中的PIL(Python Imaging Library)库里边的ImageGrab.grab()函数来获取截图。然后使用save()函数将图片保存下来。简单的不能再简单了,源码如下:
from PIL import ImageGrab pic = ImageGrab.grab() pic.save("D:\picture.jpg")
这样我们便可以将整个桌面截图保存在D盘根目录下。So easy。另外关于图片存储格式,使用save()函数保存时路径中文件格式为jpg、bmp、png均可,亲测可行,bmp格式存储空间最大,理论上来说数据失真率也最低。
下面我们考虑如何将当前窗口截图保存,ImageGrab.grab()函数没有参数时默认将整个屏幕截图,当我们给它传递一个矩形的坐标时,它便可以将制定矩形进行截图。同时这里我们需要在python中调用win32的GUI函数来获取当前窗口的句柄、进而获取当前窗口的位置坐标。同时,我们需要在python中定义一个结构体来存储获取的坐标值,于是我们又学习了python中结构体的定义以及win32 gui函数调用的方法,源码如下:
import win32gui from ctypes import * import ctypes from PIL import ImageGrab import win32api,win32con import pyHook import pythoncom #定义结构体,存储当前窗口坐标 class RECT(ctypes.Structure): _fields_ = [('left', ctypes.c_int), ('top', ctypes.c_int), ('right', ctypes.c_int), ('bottom', ctypes.c_int)] rect = RECT() HWND = win32gui.GetForegroundWindow()#获取当前窗口句柄 ctypes.windll.user32.GetWindowRect(HWND, ctypes.byref(rect))#获取当前窗口坐标 coordinate = (rect.left+2, rect.top+2, rect.right-2, rect.bottom-2)#转换为预截图窗口坐标 pic = ImageGrab.grab(coordinate)#截图 pic.save("D:\321.jpg")#保存
其中ctypes中的byref()方法是用来返回结构体的指针,从而将窗口坐标存储在结构体中。
在实现了全屏截图以及指定窗口截图以后,我们便需要考虑如何实现指定范围截图。我的思路是利用pyHook工具包实现对鼠标事件的监听,在鼠标左键按下时,记录一个坐标,鼠标左键抬起时再记录一个坐标,于是便可以确定整个所要截图区域的矩形坐标,再使用ImageGrab.grab(coordinate)函数实现截图。源码如下:
coordinate = [1,1,1,1] #监听键盘事件 def on_mouse_event(event): if event.MessageName == 'mouse left down': coordinate[0:2] = event.Position elif event.MessageName == 'mouse left up': coordinate[2:4] = event.Position win32api.PostQuitMessage()#退出监听循环 pic = ImageGrab.grab(coordinate) pic.save("D:\321.jpg") return True hm = pyHook.HookManager()#创建一个钩子管理对象 hm.MouseAll = on_mouse_event#监听所有鼠标事件 hm.HookMouse()#设定鼠标钩子 pythoncom.PumpMessages()#进入循环,程序一直监听
这里我们在鼠标完成截图矩形坐标确定后,需要推出鼠标事件的监听。另外,目前存在一个问题,在用鼠标选取范围时会导致窗口焦点的改变,从而影响实际截图内容。因此可以进一步考虑先将屏幕锁定,再进行范围选定。或者也许可以先进行全屏截图,但仅显示而不保存,在显示的全屏截图上再进行区域截图。
恩,好了,一步步来,慢慢学习。菜鸟慢飞。