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

偏执的太偏执、 2022-09-18 10:00 307阅读 0赞

#

  1. 分类: [ Graph\_Image][Graph_Image]

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

[cpp] view plain copy print ?

  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. }

    void CScreenShotDlg::OnBtnScreenshot()
    {

    1. RECT rect = {0, 0, 1900, 1000};
    2. HBITMAP hbmp = CopyScreenToBitmap(&rect);
    3. SaveBitmapToFile(hbmp, "a.bmp");
    4. MessageBox("Save bmp file Successful");

    }

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

[cpp] view plain copy print ?

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

发表评论

表情:
评论列表 (有 0 条评论,307人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Selenium 屏幕

    在自动化测试程序运行时,有些地方出现了 bug,此时,我们希望可以将当前运行的屏幕的截图保存下来,方便开发者后续进行调试与修复。 Selenium 提供的屏幕截屏方法: !

    相关 C++保存文件

    调用WindowsApi,使用Com组件,我也是借鉴加修改的,因为网上直接复制下来的并不能直接调用(HBITMAP这种东西就比较奇怪),以后当成工具调用就可以了,写了部分注释,

    相关 BMP文件结构及VC操作

    \---- 用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重,在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数显示BMP位图,可以消除以