最近心血來潮想自己用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一行代碼搞定了,
事實上只要這個視窗不被拖動到螢屏之外或者最小化,你想堆疊多少個都沒問題(即使被其他應用遮擋),你自己看著辦咯,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/402559.html
標籤:其他
下一篇:約瑟夫以及其變異體總結
