GDI 保存屏幕截图浅谈

截屏原理

利用GDI实现屏幕截图并不麻烦,简单来说就是通过将屏幕的DC获取到当前屏幕的兼容位图,之后转换成二进制文件保存进文件就可以了。

截屏代码

 

    int nWidth=GetSystemMetrics(SM_CXSCREEN);
    int nHeight=GetSystemMetrics(SM_CYSCREEN);
    HDC hDesktopDC = GetDC(GetDesktopWindow());
    HDC hBmpFileDC = CreateCompatibleDC(hDesktopDC);
    HBITMAP hBmpFileBitmap = CreateCompatibleBitmap(hDesktopDC,nWidth,nHeight);
    HBITMAP hOldBitmap = (HBITMAP) SelectObject(hBmpFileDC,hBmpFileBitmap);
    BitBlt(hBmpFileDC,0,0,nWidth,nHeight,hDesktopDC,0,0,SRCCOPY|CAPTUREBLT);
    SelectObject(hBmpFileDC,hOldBitmap);
    HDC hdc=NULL;
    FILE* fp=NULL;
    LPVOID pBuf=NULL;
    BITMAPINFO bmpInfo;
    BITMAPFILEHEADER bmpFileHeader;
    hdc=GetDC(NULL);
    ZeroMemory(&bmpInfo,sizeof(BITMAPINFO));
    bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
    GetDIBits(hdc,hBmpFileBitmap,0,0,NULL,&bmpInfo,DIB_RGB_COLORS); //获取bmp信息 
    
    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,_T("Unable to Allocate Bitmap Memory"),_T("Error"),MB_OK|MB_ICONERROR);
    }

    bmpInfo.bmiHeader.biCompression=BI_RGB;
    GetDIBits(hdc,hBmpFileBitmap,0,bmpInfo.bmiHeader.biHeight,pBuf,&bmpInfo,DIB_RGB_COLORS);    


    WIN32_FIND_DATA   wfd;
    HANDLE hFind = FindFirstFile(duiString, &wfd);
    if (!((hFind != INVALID_HANDLE_VALUE) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)))
    {
         CreateDirectory(duiString, NULL);
    }
    FindClose(hFind);
   TCHAR szFileName = {"test.bmp"};
    HANDLE hFile = CreateFile(szFileName,                // name of the write
        GENERIC_WRITE,          // open for writing
        0,                      // do not share
        NULL,                   // default security
        CREATE_ALWAYS,          // overwrite existing
        FILE_ATTRIBUTE_NORMAL,  // normal file
        NULL);                  // no attr. template
    bmpFileHeader.bfReserved1=0;
    bmpFileHeader.bfReserved2=0;    
    bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage;
    bmpFileHeader.bfType='MB';
    bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
    DWORD dwWriten;
    WriteFile(hFile, &bmpFileHeader,sizeof(BITMAPFILEHEADER), &dwWriten, NULL);
    WriteFile(hFile, &bmpInfo.bmiHeader,sizeof(BITMAPINFOHEADER), &dwWriten, NULL);
    WriteFile(hFile, pBuf,bmpInfo.bmiHeader.biSizeImage, &dwWriten, NULL);

    CloseHandle(hFile);
    free(pBuf);

代码风格可能略残,勿怪。

实际使用过程所遇问题

一般来说,BMP格式的图片保存时都是32色的,也即是说存在着控制透明的Alpha通道(具体解释见百度百科)。这个通道对于一般的bmp图片的使用以及打开没有太多的影响,所以一般情况下都不怎么关注它。但是目前手头的项目碰见了一个平台问题:在Win7X64平台下的截图打开以及使用一切正常,但是在XP下的截图使用就不正常了(项目内部使用)。利用UE仔细看了一下两者的不同,发现在XP下Alpha通道默认是00,即全透明;在Win7X64下Alpha通道为FF,即不透明。恰恰是这一点影响到了对截图的使用。

解决办法

强行修改Alpha通道实为不智之举,目前采用方式是将bmp文件改为24色,去除Alpha通道来进行实现,也即是在述代码获取到bmp信息之后,将其中的bmpInfo.bmiHeader.biBitCount 设置为24即可。

转载于:https://www.cnblogs.com/BlueDrop/p/3360888.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值