麻烦捕捉窗与WINAPI的BitBlt对于某些应用只(Trouble capturing windo

2019-10-19 03:01发布

我已经把一个应该采取一个窗口,其名称中包含特定字符串的一个截图简单的Python脚本。 我使用的代码如下,


import win32gui, win32ui, win32con
import PIL.Image

def getWindowHandle(name):        
    windowList = []
    win32gui.EnumWindows(lambda hwnd, wndList:
                             wndList.append((win32gui.GetWindowText(hwnd), hwnd)),
                         windowList)

    for pair in windowList:
        if name in pair[0]:
            return pair[1]

    return None


class Window():
    def __init__(self, hwnd = None):
        if not hwnd: return

        l, t, r, b   = win32gui.GetClientRect(hwnd)
        sl, st, _, _ = win32gui.GetWindowRect(hwnd)
        cl, ct       = win32gui.ClientToScreen(hwnd, (l, t))

        self.size     = (r - l, b - t)
        self.position = (cl - sl, ct - st)

        hDC   = win32gui.GetWindowDC(hwnd)
        self.windowDC  = win32ui.CreateDCFromHandle(hDC)
        self.newDC = self.windowDC.CreateCompatibleDC()

        #win32gui.ReleaseDC(hwnd, hDC)

        self.bitmap = win32ui.CreateBitmap()
        self.bitmap.CreateCompatibleBitmap(self.windowDC, self.size[0], self.size[1])
        self.newDC.SelectObject(self.bitmap)

    def __del__(self):
        self.newDC.DeleteDC()
        self.windowDC.DeleteDC()
        del self.bitmap

    def screenshot(self, location = 'C:\\Users\\Grieverheart\\Desktop\\'):
        self.newDC.BitBlt((0, 0), self.size, self.windowDC, self.position, win32con.SRCCOPY)
        self.bitmap.Paint(self.newDC)

        bmpinfo = self.bitmap.GetInfo()
        bmpstr  = self.bitmap.GetBitmapBits(True)
        im = PIL.Image.frombuffer('RGB', self.size, bmpstr, 'raw', 'BGRX', 0, 1)
        try:
            im.save(location + 'test.png', 'PNG')
        except IOError:
            return


def main():
    handle = getWindowHandle("Blender")
    if not handle: return

    window = Window(handle)
    window.screenshot()

if __name__ == "__main__":
    main()

该剧本让我对某些应用,如搅拌机或DOSBox中的黑色屏幕截图。

有谁知道是什么原因导致这个问题的只有一些应用程序,我怎么能解决呢?

编辑 :看来我的问题可能与这虽然我不知道我必须做些什么来解决我的问题,职务。 我还想补充一点,我也曾尝试加入CAPTUREBLT标志没有任何差别。

Answer 1:

从MSDN

BitBlt的返回,如果源和目的地设备上下文表示不同的装置的错误。 为了针对不同设备的DC之间传输数据,通过调用的GetDIBits存储器位图转换为一个DIB。 要显示DIB到第二设备,呼叫SetDIBits或的StretchDIBits。

这是什么意思? 简而言之,混合DWM(即航空)和非GDI应用程序(OpenGL中,例如)使得BiBlt一个不可预知的/不可靠的。

再从MSDN :

桌面合成功能,在Windows Vista中引入,从根本上改变屏幕上的应用程序的方式显示像素。 当启用桌面组合,单个窗口不再像在以前的Windows版本中那样可直接绘制到屏幕或主要显示设备。 取而代之的是,它们的绘制被重定向到视频存储器离屏的表面,然后将其呈现为桌面图像并呈现在显示器上。

由于与DWM阻击器拥有这些知道的问题 ,您可以:

  1. 尝试使用替代技术; 你有一个很好的列表在这里

  2. 可以禁用DWM(即暂时)使用DwmEnableComposition(DWM_EC_DISABLECOMPOSITION);

试试,看看有没有适合你。

AFAIK然而,可靠地得到它采用3D渲染(DirectX或OpenGL的)应用程序的内容的唯一方法是为自己注入到进程,并复制出位(见这个答案的DirectX ,或钩wglSwapBuffers并做了回读glReadPixels支持OpenGL)



文章来源: Trouble capturing window with winAPI BitBlt for some applications only