python分享一个在Windows下对应用程序python窗口后台截图的方法
Posted @fai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python分享一个在Windows下对应用程序python窗口后台截图的方法相关的知识,希望对你有一定的参考价值。
最近心血来潮想自己用python写一个图色操作游戏的脚本,于是上百度一查“python后台截图”,事实上能用的也就是pywin32读取内存截图(什么设备环境、设备描述表、内存设备描述表的),而且翻来翻去就是这一套代码。
类似这个:
#获取后台窗口的句柄,注意后台窗口不能最小化
hWnd = win32gui.FindWindow("NotePad",None) #窗口的类名可以用Visual Studio的SPY++工具获取
#获取句柄窗口的大小信息
left, top, right, bot = win32gui.GetWindowRect(hWnd)
width = right - left
height = bot - top
#返回句柄窗口的设备环境,覆盖整个窗口,包括非客户区,标题栏,菜单,边框
hWndDC = win32gui.GetWindowDC(hWnd)
#创建设备描述表
mfcDC = win32ui.CreateDCFromHandle(hWndDC)
#创建内存设备描述表
saveDC = mfcDC.CreateCompatibleDC()
#创建位图对象准备保存图片
saveBitMap = win32ui.CreateBitmap()
#为bitmap开辟存储空间
saveBitMap.CreateCompatibleBitmap(mfcDC,width,height)
#将截图保存到saveBitMap中
saveDC.SelectObject(saveBitMap)
#保存bitmap到内存设备描述表
saveDC.BitBlt((0,0), (width,height), mfcDC, (0, 0), win32con.SRCCOPY)
但这个代码似乎只是针对MFC应用(不知到有多过时了),在win10下对某些游戏截图总是不完整,还被被各路神仙转来转去,乍一看博文 发布时间2021年,其实早就是20年前的代码(就连后面的print都python是不带括号的,2.x的代码)。
思来想去,PyQt不是自带一个screen模块,可以对句柄窗口就行截图吗,不知道内部实现的原理是啥,不妨试试看了:
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import QApplication
import win32gui
from numpy import array,uint8,ndarray
# 直接写一个类,方便以后使用
class Screen:
def __init__(self,win_title=None,win_class=None,hwnd=None) -> None:
self.app = QApplication(['WindowCapture'])
self.screen = QApplication.primaryScreen()
self.bind(win_title,win_class,hwnd)
def bind(self, win_title=None,win_class=None,hwnd=None):
'可以直接传入句柄,否则就根据class和title来查找,并把句柄做为实例属性 self._hwnd'
if not hwnd: self._hwnd = win32gui.FindWindow(win_class, win_title)
else: self._hwnd = hwnd
def capture(self, savename='') -> ndarray:
'截图方法,在窗口为 1920 x 1080 大小下,最快速度25ms (grabWindow: 17ms, to_cvimg: 8ms)'
def to_cvimg(pix):
'将self.screen.grabWindow 返回的 Pixmap 转换为 ndarray,方便opencv使用'
qimg = pix.toImage()
temp_shape = (qimg.height(), qimg.bytesPerLine() * 8 // qimg.depth())
temp_shape += (4,)
ptr = qimg.bits()
ptr.setsize(qimg.byteCount())
result = array(ptr, dtype=uint8).reshape(temp_shape)
return result[..., :3]
self.pix = self.screen.grabWindow(self._hwnd)
self.img = to_cvimg(self.pix)
if savename: self.pix.save(savename)
return self.img
if __name__ =='__main__':
screen = Screen(win_title='')
screen.capture('test.bmp')
一顿操作+实验,总结如下:
1.在对某些大型应用截图时,PyQt更完整,至少不会出现漏缺的情况,虽然在windows的不同缩放比例下会出现大的黑边,但都是分布在右、下,对实际使用影响不大。
2.缺点也很明显:当窗口被拖动到屏幕可视区域之外时,无法捕捉。
这时候有的同学就急了,啥?那不是跟前台截图一样事儿的吗?那我还用个屁的PyQt,用XXX一行代码搞定了。
事实上只要这个窗口不被拖动到屏幕之外或者最小化,你想堆叠多少个都没问题(即使被其他应用遮挡),你自己看着办咯。
以上是关于python分享一个在Windows下对应用程序python窗口后台截图的方法的主要内容,如果未能解决你的问题,请参考以下文章
Windows下对Sublime text2进行Python编译环境配置