尝试使用ctypes保存屏幕截图时,GetDIBits失败了吗?

时间:2013-09-01 05:31:33

标签: python ctypes

我尝试仅使用ctypes拍摄并保存屏幕截图。我并不十分熟悉Windows API,因此我一直非常依赖Microsoft Developer Network中的各种示例。

我一直在使用MSDN中的以下代码作为模板尝试使用ctypes重新创建。

void  SaveBitmap(char *szFilename,HBITMAP hBitmap)
{

    HDC        hdc=NULL;
    FILE*      fp=NULL;
    LPVOID     pBuf=NULL;
    BITMAPINFO      bmpInfo;
    BITMAPFILEHEADER  bmpFileHeader;

    do{
        hdc=GetDC(NULL);
        ZeroMemory(&bmpInfo,sizeof(BITMAPINFO));
        bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
        GetDIBits(hdc,hBitmap,0,0,NULL,&bmpInfo,DIB_RGB_COLORS);

        if(bmpInfo.bmiHeader.biSizeImage<=0)
            bmpInfo.bmiHeader.biSizeImage=bmpInfo.bmiHeader.biWidth*abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8;
        if((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage))==NULL)
            {
            //MessageBox( NULL, "Unable to Allocate Bitmap Memory",
            break;
            }

        bmpInfo.bmiHeader.biCompression=BI_RGB;
        GetDIBits(hdc,hBitmap,0,bmpInfo.bmiHeader.biHeight,pBuf, &bmpInfo,
        DIB_RGB_COLORS);
        if((fp = fopen(szFilename,"wb"))==NULL)
            {
            //MessageBox( NULL, "Unable to Create Bitmap File", "Error",
            MB_OK|MB_ICONERROR);
            break;
            }
        bmpFileHeader.bfReserved1=0;
        bmpFileHeader.bfReserved2=0;

        bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage;
        bmpFileHeader.bfType='MB';

        bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);

        fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);
        fwrite(&bmpInfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
        fwrite(pBuf,bmpInfo.bmiHeader.biSizeImage,1,fp);
    }while(false);

    if(hdc)     ReleaseDC(NULL,hdc);

    if(pBuf)    free(pBuf);

    if(fp)      fclose(fp);

但是,我很幸运能够让GetDIBits功能获得成功。我有点确信我已经获得了正确的屏幕代码,但保存代码给了我很多麻烦。令人沮丧的是,我不确定为什么这些功能都失败了。

我的Python代码:

libc = ctypes.cdll.msvcrt

# handle to the entire desktop Window
hdc = windll.user32.GetDC(None)

# DC for the entire window
h_dest = windll.gdi32.CreateCompatibleDC(hdc)

width = windll.user32.GetSystemMetrics(SM_CXSCREEN)
height = windll.user32.GetSystemMetrics(SM_CYSCREEN)

hb_desktop = windll.gdi32.CreateCompatibleBitmap(hdc, width, height)
windll.gdi32.SelectObject(h_dest, hb_desktop)

print windll.gdi32.BitBlt(h_dest, 0,0, width, height, hdc, 0, 0, 'SRCCOPY')

# Save Section
# ==============
bmp_info = BITMAPINFO()
bmp_header = BITMAPFILEHEADER()
hdc = windll.user32.GetDC(None)

bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER)
DIB_RGB_COLORS = 0
print windll.gdi32.GetDIBits(hdc, hCaptureBitmap, 0,0, None, byref(bmp_info), DIB_RGB_COLORS)

bmp_info.bmiHeader.biSizeImage = bmp_info.bmiHeader.biWidth *abs(bmp_info.bmiHeader.biHeight) * (bmp_info.bmiHeader.biBitCount+7)/8;

pBuf = (c_char * bmp_info.bmiHeader.biSizeImage)()

BI_RGB = 0
bmp_info.bmiHeader.biCompression = BI_RGB
print windll.gdi32.GetDIBits(hdc, hCaptureBitmap, 0, bmp_info.bmiHeader.biHeight, pBuf, byref(bmp_info), 0x00)

bmp_header.bfReserved1 = 0
bmp_header.bfReserved2 = 0

bmp_header.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmp_info.bmiHeader.biSizeImage
bmp_header.bfType = 0x4D42

bmp_header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)

fp = libc.fopen('test.bmp',"wb")

libc.fwrite(byref(bmp_header), sizeof(BITMAPFILEHEADER), 1, fp)

libc.fwrite(byref(bmp_info.bmiHeader), 
    sizeof(BITMAPFILEHEADER), 1, fp)

libc.fwrite(pBuf, bmp_info.bmiHeader.biSizeImage, 1, fp)

我已经为每个print电话添加了GetDIBits个语句,果然,他们都返回了失败的代码。我完全被这里难住了。

0 个答案:

没有答案