屏幕保存为位图

    技术2022-05-20  37

    可分为两个步骤:

    一 将屏幕保存为位图句柄

    HBITMAP CopyScreenToBitmap(LPRECT lpRect){ HDC hScrDC,hMemDC; HBITMAP hBitmap,hOldBitmap; int nX1,nX2,nY1,nY2; int nWidth,nHeight; if (IsRectEmpty(lpRect)) {  return FALSE; } //为屏幕创建设备描述表 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); return hBitmap;}二 将位图句柄另存为bmp图片

    int SaveBitmapToFile(HBITMAP hBitmap, LPSTR lpFileName) //hBitmap 为刚才的屏幕位图句柄{ //lpFileName 为位图文件名HDC hDC; //设备描述表int iBits; //当前显示分辨率下每个像素所占字节数WORD wBitCount; //位图中每个像素所占字节数//定义调色板大小, 位图中像素字节大小 , 位图文件大小 , 写入文件字节数DWORD dwPaletteSize=0,dwBmBitsSize,dwDIBSize, dwWritten;BITMAP Bitmap; //位图属性结构BITMAPFILEHEADER bmfHdr; //位图文件头结构BITMAPINFOHEADER bi; //位图信息头结构 LPBITMAPINFOHEADER lpbi; //指向位图信息头结构HANDLE fh, hDib, hPal;HPALETTE hOldPal=NULL;//定义文件,分配内存句柄,调色板句柄

    //计算位图文件每个像素所占字节数hDC = CreateDC("DISPLAY",NULL,NULL,NULL);iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);DeleteDC(hDC);if (iBits <= 1)wBitCount = 1;else if (iBits <= 4)wBitCount = 4;else if (iBits <= 8)wBitCount = 8;else if (iBits <= 24)wBitCount = 24;elsewBitCount = 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的整数倍,具体算法为:int biWidth = (Bitmap.bmWidth*wBitCount) / 32;if((Bitmap.bmWidth*wBitCount) % 32)biWidth++; //不是整数倍的加1biWidth *= 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)return FALSE;// 设置位图文件头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);return TRUE;}

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

       HBITMAP g_screenBmp=NULL;

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

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

       RECT g_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): 


    最新回复(0)