屏幕保存为位图

可分为两个步骤:

一将屏幕保存为位图句柄

HBITMAPCopyScreenToBitmap(LPRECTlpRect)
{
HDChScrDC,hMemDC;
HBITMAPhBitmap,hOldBitmap;
intnX1,nX2,nY1,nY2;
intnWidth,nHeight;
if(IsRectEmpty(lpRect))
{
returnFALSE;
}
//为屏幕创建设备描述表
hScrDC=CreateDC("DISPLAY",NULL,NULL,NULL);
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC=CreateCompatibleDC(hScrDC);
//获得选定区域坐标
nX1=lpRect->left;
nY1=lpRect->top;
nX2=lpRect->right;
nY2=lpRect->bottom;

//确保选定区域是可见的
if(nX1<0)
nX1=0;
if(nY1<0)
nY1=0;
if(nX2>m_xScreen)
nX2=m_xScreen;
if(nY2>m_yScreen)
nY2=m_yScreen;
nWidth=nX2-nX1;
nHeight=nY2-nY1;
//创建一个与屏幕设备描述表兼容的位图
hBitmap=CreateCompatibleBitmap(hScrDC,nWidth,nHeight);
//把新位图选到内存设备描述表中
hOldBitmap=(HBITMAP)SelectObject(hMemDC,hBitmap);
//把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC,0,0,nWidth,nHeight,hScrDC,nX1,nY1,SRCCOPY);
//得到屏幕位图的句柄
hBitmap=(HBITMAP)SelectObject(hMemDC,hOldBitmap);
//清除
DeleteDC(hScrDC);
DeleteDC(hMemDC);
returnhBitmap;
}
二将位图句柄另存为bmp图片

intSaveBitmapToFile(HBITMAPhBitmap,LPSTRlpFileName)//hBitmap为刚才的屏幕位图句柄
{//lpFileName为位图文件名
HDChDC;
//设备描述表
intiBits;
//当前显示分辨率下每个像素所占字节数
WORDwBitCount;
//位图中每个像素所占字节数
//定义调色板大小,位图中像素字节大小,位图文件大小,写入文件字节数
DWORDdwPaletteSize=0,dwBmBitsSize,dwDIBSize,dwWritten;
BITMAPBitmap;
//位图属性结构
BITMAPFILEHEADERbmfHdr;
//位图文件头结构
BITMAPINFOHEADERbi;
//位图信息头结构
LPBITMAPINFOHEADERlpbi;
//指向位图信息头结构
HANDLEfh,hDib,hPal;
HPALETTEhOldPal=NULL;
//定义文件,分配内存句柄,调色板句柄

//计算位图文件每个像素所占字节数
hDC=CreateDC("DISPLAY",NULL,NULL,NULL);
iBits=GetDeviceCaps(hDC,BITSPIXEL)*
GetDeviceCaps(hDC,PLANES);
DeleteDC(hDC);
if(iBits<=1)
wBitCount=1;
elseif(iBits<=4)
wBitCount=4;
elseif(iBits<=8)
wBitCount=8;
elseif(iBits<=24)
wBitCount=24;
else
wBitCount=32;
//计算调色板大小
if(wBitCount<=8)
dwPaletteSize=(1<<wBitCount)*sizeof(RGBQUAD);

//设置位图信息头结构
GetObject(hBitmap,sizeof(BITMAP),(LPSTR)&Bitmap);
bi.biSize=sizeof(BITMAPINFOHEADER);
bi.biWidth=Bitmap.bmWidth;
bi.biHeight=Bitmap.bmHeight;
bi.biPlanes=1;
bi.biBitCount=wBitCount;
bi.biCompression=BI_RGB;
bi.biSizeImage=0;
bi.biXPelsPerMeter=0;
bi.biYPelsPerMeter=0;
bi.biClrUsed=0;
bi.biClrImportant=0;

dwBmBitsSize=((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;
//为位图内容分配内存

/*xxxxxxxx计算位图大小分解一下(解释一下上面的语句)xxxxxxxxxxxxxxxxxxxx
//每个扫描行所占的字节数应该为4的整数倍,具体算法为:
intbiWidth=(Bitmap.bmWidth*wBitCount)/32;
if((Bitmap.bmWidth*wBitCount)%32)
biWidth++;//不是整数倍的加1
biWidth*=4;//到这里,计算得到的为每个扫描行的字节数。
dwBmBitsSize=biWidth*Bitmap.bmHeight;//得到大小
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/


hDib=GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
lpbi=(LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi=bi;
//处理调色板
hPal=GetStockObject(DEFAULT_PALETTE);
if(hPal)
{
hDC=::GetDC(NULL);
hOldPal=SelectPalette(hDC,(HPALETTE)hPal,FALSE);
RealizePalette(hDC);
}
//获取该调色板下新的像素值
GetDIBits(hDC,hBitmap,0,(UINT)Bitmap.bmHeight,(LPSTR)lpbi+sizeof(BITMAPINFOHEADER)+dwPaletteSize,(BITMAPINFO*)lpbi,DIB_RGB_COLORS);
//恢复调色板
if(hOldPal)
{
SelectPalette(hDC,hOldPal,TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL,hDC);
}
//创建位图文件
fh=CreateFile(lpFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if(fh==INVALID_HANDLE_VALUE)
returnFALSE;
//设置位图文件头
bmfHdr.bfType=0x4D42;//"BM"
dwDIBSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize;
bmfHdr.bfSize=dwDIBSize;
bmfHdr.bfReserved1=0;
bmfHdr.bfReserved2=0;
bmfHdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+dwPaletteSize;
//写入位图文件头
WriteFile(fh,(LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER),&dwWritten,NULL);
//写入位图文件其余内容
WriteFile(fh,(LPSTR)lpbi,sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize,&dwWritten,NULL);
//清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
returnTRUE;
}

在程序中可以通过下列调用即可:

HBITMAPg_screenBmp=NULL;

//获取x方向屏幕像素()
intm_xScreen=GetSystemMetrics(SM_CXSCREEN);

//获取y方向屏幕像素()
intm_yScreen=GetSystemMetrics(SM_CYSCREEN);

RECTg_qq_DlgRt;

g_qq_DlgRt.left=0;
g_qq_DlgRt.top=0;
g_qq_DlgRt.right=m_xScreen;
g_qq_DlgRt.bottom=m_yScreen;
g_screenBmp=CopyScreenToBitmap(&g_qq_DlgRt);
SaveBitmapToFile(g_screenBmp,"e://025.bmp");最后的结果25.bmp):

你可能感兴趣的:(屏幕)