截屏原理
利用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即可。