VC屏幕截图,保存为Bmp文件

来源:互联网 发布:深圳西乡淘宝培训 编辑:程序博客网 时间:2024/04/28 04:52

 

        分类:            Graph_Image         

新建一个MFC基于对话框的应用程序,在界面上放一个Button,为其实现点击事件,代码如下:

[cpp] view plaincopyprint?
  1. void CScreenShotDlg::OnBtnScreenshot()  
  2. {  
  3.     RECT rect = {0, 0, 1900, 1000};  
  4.     HBITMAP hbmp = CopyScreenToBitmap(&rect);  
  5.     SaveBitmapToFile(hbmp, "a.bmp");  
  6.     MessageBox("Save bmp file Successful");  
  7. }  

被调用的这两个函数实现如下:

[cpp] view plaincopyprint?
  1. HBITMAP CopyScreenToBitmap(LPRECT lpRect)  
  2. {  
  3.     HDC hScrDC, hMemDC;             // 屏幕和内存设备描述表  
  4.     HBITMAP hBitmap, hOldBitmap;    // 位图句柄  
  5.     int nX, nY, nX2, nY2;           // 选定区域坐标  
  6.     int nWidth, nHeight;            // 位图宽度和高度  
  7.     int xScrn, yScrn;               // 屏幕分辨率  
  8.   
  9.     if (IsRectEmpty(lpRect))  
  10.         return NULL;  
  11.   
  12.     hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);     // 为屏幕创建设备描述表  
  13.       
  14.     hMemDC = CreateCompatibleDC(hScrDC);                // 为屏幕设备描述表创建兼容的内存设备描述表  
  15.   
  16.     nX = lpRect->left;  
  17.     nY = lpRect->top;  
  18.     nX2 = lpRect->right;  
  19.     nY2 = lpRect->bottom;  
  20.       
  21.     xScrn = GetDeviceCaps(hScrDC, HORZRES); // 获得屏幕水平分辨率  
  22.     yScrn = GetDeviceCaps(hScrDC, VERTRES);  
  23.   
  24.     if (nX < 0)  
  25.         nX = 0;  
  26.     if (nY < 0)  
  27.         nY = 0;  
  28.     if (nX2 > xScrn)  
  29.         nX2 = xScrn;  
  30.     if (nY2 > yScrn)  
  31.         nY2 = yScrn;  
  32.     nWidth = nX2 - nX;  
  33.     nHeight = nY2 - nY;  
  34.   
  35.     hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);      // 创建一个与屏幕设备描述表兼容的位图  
  36.     hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);            // 把新位图选到内存设备描述表中  
  37.     BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY); // 把屏幕设备描述表拷贝到内存设备描述表中  
  38.     hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);            // 得到屏幕位图的句柄  
  39.   
  40.     DeleteDC(hScrDC);  
  41.     DeleteDC(hMemDC);  
  42.   
  43.     return hBitmap;  
  44. }  
  45.   
  46. /* 
  47.     lpFileName: 位图文件名 
  48. */  
  49. BOOL SaveBitmapToFile(HBITMAP hBitmap, LPSTR lpFileName)  
  50. {  
  51.     HDC hDC;                        // 设备描述表  
  52.       
  53.     int iBits;                      // 当前显示分辨率下每个像素所占字节数  
  54.     WORD wBitCount;                 // 位图中每个像素所占字节数  
  55.     DWORD dwPaletteSize = 0, dwBmBitsSize, dwDIBSize, dwWritten;    // 调色板大小,位图数据大小,位图文件大小,写入文件字节数  
  56.     BITMAP Bitmap;                  //位图属性结构  
  57.     BITMAPFILEHEADER bmfHdr;        // 位图文件头  
  58.     BITMAPINFOHEADER bi;            // 位图信息头  
  59.     LPBITMAPINFOHEADER lpbi;        // 指向位图信息头结构  
  60.       
  61.     HANDLE fh, hDib;                // 定义文件,分配内存句柄  
  62.     HPALETTE hPal, hOldPal=NULL;    // 调色板句柄  
  63.   
  64.     // 计算位图文件每个像素所占字节数  
  65.     hDC = CreateDC("DISPLAY", NULL, NULL, NULL);  
  66.     iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);  
  67.     DeleteDC(hDC);  
  68.     if (iBits <= 1)  
  69.         wBitCount = 1;  
  70.     else if (iBits <= 4)  
  71.         wBitCount = 4;  
  72.     else if (iBits <= 8)  
  73.         wBitCount = 8;  
  74.     else if (iBits <= 24)  
  75.         wBitCount = 24;  
  76.     else  
  77.         wBitCount = 32;  
  78.     if (wBitCount <= 8)  
  79.         dwPaletteSize = (1 << wBitCount) * sizeof(RGBQUAD);       // 计算调色板大小  
  80.   
  81.     // 设置位图信息头结构  
  82.     GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);  
  83.     bi.biSize = sizeof(BITMAPINFOHEADER);  
  84.     bi.biWidth = Bitmap.bmWidth;  
  85.     bi.biHeight = Bitmap.bmHeight;  
  86.     bi.biPlanes = 1;  
  87.     bi.biBitCount = wBitCount;  
  88.     bi.biCompression = BI_RGB;  
  89.     bi.biSizeImage = 0;  
  90.     bi.biXPelsPerMeter = 0;  
  91.     bi.biYPelsPerMeter = 0;  
  92.     bi.biClrUsed = 0;  
  93.     bi.biClrImportant = 0;  
  94.     dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;  
  95.   
  96.     hDib = GlobalAlloc(GHND, dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));  // 为位图内容分配内存  
  97.     lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);  
  98.     *lpbi = bi;  
  99.     // 处理调色板  
  100.     hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);  
  101.     if (hPal)  
  102.     {  
  103.         hDC = GetDC(NULL);  
  104.         hOldPal = SelectPalette(hDC, hPal, FALSE);  
  105.         RealizePalette(hDC);  
  106.     }  
  107.     // 获取该调色板下新的像素值  
  108.     GetDIBits(hDC, hBitmap, 0, (UINT)Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) + dwPaletteSize, (BITMAPINFO*)lpbi, DIB_RGB_COLORS);  
  109.       
  110.     if (hOldPal)                // 恢复调色板  
  111.     {  
  112.         SelectPalette(hDC, hOldPal, TRUE);  
  113.         RealizePalette(hDC);  
  114.         ReleaseDC(NULL, hDC);  
  115.     }  
  116.     // 创建位图文件   
  117.     fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);  
  118.     if (fh == INVALID_HANDLE_VALUE)  
  119.         return FALSE;  
  120.   
  121.     // 设置位图文件头  
  122.     bmfHdr.bfType = 0x4D42;     // 文件类型: "BM"  
  123.     dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;   
  124.     bmfHdr.bfSize = dwDIBSize;  // 位图文件大小  
  125.     bmfHdr.bfReserved1 = 0;  
  126.     bmfHdr.bfReserved2 = 0;  
  127.     bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize;  
  128.       
  129.     WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);  // 写入位图文件头  
  130.     WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);                    // 写入位图文件其余内容  
  131.   
  132.     GlobalUnlock(hDib);  
  133.     GlobalFree(hDib);  
  134.     CloseHandle(fh);  
  135.   
  136.     return TRUE;  
  137. }  

原创粉丝点击