VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 178|回复: 3

[已解决]关于获取屏幕截图后在内存数据指针的问题

[复制链接]
98_avatar_middle
最佳答案
0 
在线会员 发表于 2020-8-19 21:46:34 | 显示全部楼层 |阅读模式
本人想利用如下代码进行截屏,然后在内存中直接获取位图数据区域指针,总是不成功(n总是为0),望高人解答,不胜感激!
        HDC hScreen = ::GetDC(NULL);
        HDC        hCompDC = CreateCompatibleDC(hScreen);
        HBITMAP        hBmp,hOld;
        BITMAPINFOHEADER bih;
        //取屏幕宽度和高度
        int                nWidth = GetSystemMetrics(SM_CXSCREEN);
        int                nHeight = GetSystemMetrics(SM_CYSCREEN);
        //创建Bitmap对象
        hBmp = CreateCompatibleBitmap(hScreen, nWidth, nHeight);
        hOld = (HBITMAP)SelectObject(hCompDC, hBmp);
        BitBlt(hCompDC, 0, 0, nWidth, nHeight, hScreen, 0, 0, SRCCOPY);

        char* pData ;
        int n = ::GetDIBits(hCompDC, hBmp, 0, nHeight, pData, (BITMAPINFO*)&bih, DIB_RGB_COLORS);

最佳答案
77_avatar_small
2020-8-20 11:41:59
从微软拿过来的地址
  1. int CaptureAnImage(HWND hWnd)
  2. {
  3.     HDC hdcScreen;
  4.     HDC hdcWindow;
  5.     HDC hdcMemDC = NULL;
  6.     HBITMAP hbmScreen = NULL;
  7.     BITMAP bmpScreen;

  8.     // Retrieve the handle to a display device context for the client
  9.     // area of the window.
  10.     hdcScreen = GetDC(NULL);
  11.     hdcWindow = GetDC(hWnd);

  12.     // Create a compatible DC which is used in a BitBlt from the window DC
  13.     hdcMemDC = CreateCompatibleDC(hdcWindow);

  14.     if(!hdcMemDC)
  15.     {
  16.         MessageBox(hWnd, L"CreateCompatibleDC has failed",L"Failed", MB_OK);
  17.         goto done;
  18.     }

  19.     // Get the client area for size calculation
  20.     RECT rcClient;
  21.     GetClientRect(hWnd, &rcClient);

  22.     //This is the best stretch mode
  23.     SetStretchBltMode(hdcWindow,HALFTONE);

  24.     //The source DC is the entire screen and the destination DC is the current window (HWND)
  25.     if(!StretchBlt(hdcWindow,
  26.                0,0,
  27.                rcClient.right, rcClient.bottom,
  28.                hdcScreen,
  29.                0,0,
  30.                GetSystemMetrics (SM_CXSCREEN),
  31.                GetSystemMetrics (SM_CYSCREEN),
  32.                SRCCOPY))
  33.     {
  34.         MessageBox(hWnd, L"StretchBlt has failed",L"Failed", MB_OK);
  35.         goto done;
  36.     }
  37.    
  38.     // Create a compatible bitmap from the Window DC
  39.     hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);
  40.    
  41.     if(!hbmScreen)
  42.     {
  43.         MessageBox(hWnd, L"CreateCompatibleBitmap Failed",L"Failed", MB_OK);
  44.         goto done;
  45.     }

  46.     // Select the compatible bitmap into the compatible memory DC.
  47.     SelectObject(hdcMemDC,hbmScreen);
  48.    
  49.     // Bit block transfer into our compatible memory DC.
  50.     if(!BitBlt(hdcMemDC,
  51.                0,0,
  52.                rcClient.right-rcClient.left, rcClient.bottom-rcClient.top,
  53.                hdcWindow,
  54.                0,0,
  55.                SRCCOPY))
  56.     {
  57.         MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
  58.         goto done;
  59.     }

  60.     // Get the BITMAP from the HBITMAP
  61.     GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);
  62.      
  63.     BITMAPFILEHEADER   bmfHeader;   
  64.     BITMAPINFOHEADER   bi;
  65.      
  66.     bi.biSize = sizeof(BITMAPINFOHEADER);   
  67.     bi.biWidth = bmpScreen.bmWidth;   
  68.     bi.biHeight = bmpScreen.bmHeight;  
  69.     bi.biPlanes = 1;   
  70.     bi.biBitCount = 32;   
  71.     bi.biCompression = BI_RGB;   
  72.     bi.biSizeImage = 0;  
  73.     bi.biXPelsPerMeter = 0;   
  74.     bi.biYPelsPerMeter = 0;   
  75.     bi.biClrUsed = 0;   
  76.     bi.biClrImportant = 0;

  77.     DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;

  78.     // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that
  79.     // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc
  80.     // have greater overhead than HeapAlloc.
  81.     HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize);
  82.     char *lpbitmap = (char *)GlobalLock(hDIB);   

  83.     // Gets the "bits" from the bitmap and copies them into a buffer
  84.     // which is pointed to by lpbitmap.
  85.     GetDIBits(hdcWindow, hbmScreen, 0,
  86.         (UINT)bmpScreen.bmHeight,
  87.         lpbitmap,
  88.         (BITMAPINFO *)&bi, DIB_RGB_COLORS);

  89.     // A file is created, this is where we will save the screen capture.
  90.     HANDLE hFile = CreateFile(L"captureqwsx.bmp",
  91.         GENERIC_WRITE,
  92.         0,
  93.         NULL,
  94.         CREATE_ALWAYS,
  95.         FILE_ATTRIBUTE_NORMAL, NULL);   
  96.    
  97.     // Add the size of the headers to the size of the bitmap to get the total file size
  98.     DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

  99.     //Offset to where the actual bitmap bits start.
  100.     bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
  101.    
  102.     //Size of the file
  103.     bmfHeader.bfSize = dwSizeofDIB;
  104.    
  105.     //bfType must always be BM for Bitmaps
  106.     bmfHeader.bfType = 0x4D42; //BM   

  107.     DWORD dwBytesWritten = 0;
  108.     WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
  109.     WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
  110.     WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
  111.    
  112.     //Unlock and Free the DIB from the heap
  113.     GlobalUnlock(hDIB);   
  114.     GlobalFree(hDIB);

  115.     //Close the handle for the file that was created
  116.     CloseHandle(hFile);
  117.       
  118.     //Clean up
  119. done:
  120.     DeleteObject(hbmScreen);
  121.     DeleteObject(hdcMemDC);
  122.     ReleaseDC(NULL,hdcScreen);
  123.     ReleaseDC(hWnd,hdcWindow);

  124.     return 0;
  125. }
复制代码




上一篇:关于socket释放和断开链接
下一篇:RESTful API怎么使用?
77_avatar_middle
最佳答案
1 
在线会员 发表于 2020-8-20 11:41:59 | 显示全部楼层    本楼为最佳答案   
bestAnswer
从微软拿过来的地址
  1. int CaptureAnImage(HWND hWnd)
  2. {
  3.     HDC hdcScreen;
  4.     HDC hdcWindow;
  5.     HDC hdcMemDC = NULL;
  6.     HBITMAP hbmScreen = NULL;
  7.     BITMAP bmpScreen;

  8.     // Retrieve the handle to a display device context for the client
  9.     // area of the window.
  10.     hdcScreen = GetDC(NULL);
  11.     hdcWindow = GetDC(hWnd);

  12.     // Create a compatible DC which is used in a BitBlt from the window DC
  13.     hdcMemDC = CreateCompatibleDC(hdcWindow);

  14.     if(!hdcMemDC)
  15.     {
  16.         MessageBox(hWnd, L"CreateCompatibleDC has failed",L"Failed", MB_OK);
  17.         goto done;
  18.     }

  19.     // Get the client area for size calculation
  20.     RECT rcClient;
  21.     GetClientRect(hWnd, &rcClient);

  22.     //This is the best stretch mode
  23.     SetStretchBltMode(hdcWindow,HALFTONE);

  24.     //The source DC is the entire screen and the destination DC is the current window (HWND)
  25.     if(!StretchBlt(hdcWindow,
  26.                0,0,
  27.                rcClient.right, rcClient.bottom,
  28.                hdcScreen,
  29.                0,0,
  30.                GetSystemMetrics (SM_CXSCREEN),
  31.                GetSystemMetrics (SM_CYSCREEN),
  32.                SRCCOPY))
  33.     {
  34.         MessageBox(hWnd, L"StretchBlt has failed",L"Failed", MB_OK);
  35.         goto done;
  36.     }
  37.    
  38.     // Create a compatible bitmap from the Window DC
  39.     hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);
  40.    
  41.     if(!hbmScreen)
  42.     {
  43.         MessageBox(hWnd, L"CreateCompatibleBitmap Failed",L"Failed", MB_OK);
  44.         goto done;
  45.     }

  46.     // Select the compatible bitmap into the compatible memory DC.
  47.     SelectObject(hdcMemDC,hbmScreen);
  48.    
  49.     // Bit block transfer into our compatible memory DC.
  50.     if(!BitBlt(hdcMemDC,
  51.                0,0,
  52.                rcClient.right-rcClient.left, rcClient.bottom-rcClient.top,
  53.                hdcWindow,
  54.                0,0,
  55.                SRCCOPY))
  56.     {
  57.         MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
  58.         goto done;
  59.     }

  60.     // Get the BITMAP from the HBITMAP
  61.     GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);
  62.      
  63.     BITMAPFILEHEADER   bmfHeader;   
  64.     BITMAPINFOHEADER   bi;
  65.      
  66.     bi.biSize = sizeof(BITMAPINFOHEADER);   
  67.     bi.biWidth = bmpScreen.bmWidth;   
  68.     bi.biHeight = bmpScreen.bmHeight;  
  69.     bi.biPlanes = 1;   
  70.     bi.biBitCount = 32;   
  71.     bi.biCompression = BI_RGB;   
  72.     bi.biSizeImage = 0;  
  73.     bi.biXPelsPerMeter = 0;   
  74.     bi.biYPelsPerMeter = 0;   
  75.     bi.biClrUsed = 0;   
  76.     bi.biClrImportant = 0;

  77.     DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;

  78.     // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that
  79.     // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc
  80.     // have greater overhead than HeapAlloc.
  81.     HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize);
  82.     char *lpbitmap = (char *)GlobalLock(hDIB);   

  83.     // Gets the "bits" from the bitmap and copies them into a buffer
  84.     // which is pointed to by lpbitmap.
  85.     GetDIBits(hdcWindow, hbmScreen, 0,
  86.         (UINT)bmpScreen.bmHeight,
  87.         lpbitmap,
  88.         (BITMAPINFO *)&bi, DIB_RGB_COLORS);

  89.     // A file is created, this is where we will save the screen capture.
  90.     HANDLE hFile = CreateFile(L"captureqwsx.bmp",
  91.         GENERIC_WRITE,
  92.         0,
  93.         NULL,
  94.         CREATE_ALWAYS,
  95.         FILE_ATTRIBUTE_NORMAL, NULL);   
  96.    
  97.     // Add the size of the headers to the size of the bitmap to get the total file size
  98.     DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

  99.     //Offset to where the actual bitmap bits start.
  100.     bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
  101.    
  102.     //Size of the file
  103.     bmfHeader.bfSize = dwSizeofDIB;
  104.    
  105.     //bfType must always be BM for Bitmaps
  106.     bmfHeader.bfType = 0x4D42; //BM   

  107.     DWORD dwBytesWritten = 0;
  108.     WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
  109.     WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
  110.     WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
  111.    
  112.     //Unlock and Free the DIB from the heap
  113.     GlobalUnlock(hDIB);   
  114.     GlobalFree(hDIB);

  115.     //Close the handle for the file that was created
  116.     CloseHandle(hFile);
  117.       
  118.     //Clean up
  119. done:
  120.     DeleteObject(hbmScreen);
  121.     DeleteObject(hdcMemDC);
  122.     ReleaseDC(NULL,hdcScreen);
  123.     ReleaseDC(hWnd,hdcWindow);

  124.     return 0;
  125. }
复制代码
98_avatar_middle
最佳答案
0 
ico_lz  楼主| 发表于 2020-8-20 18:40:45 | 显示全部楼层
谢谢!虽然还是不太明白我的代码貌似也没少什么关键的地方吧?
77_avatar_middle
最佳答案
1 
在线会员 发表于 2020-8-21 12:29:09 | 显示全部楼层
试试动态申请内存
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

×【发帖 友情提示】
1、请回复有意义的内容,请勿恶意灌水;
2、纯数字、字母、表情等无意义的内容系统将自动删除;
3、若正常回复后帖子被自动删除,为系统误删的情况,请重新回复其他正常内容或等待管理员审核通过后会自动发布;
4、感谢您对VC驿站一如既往的支持,谢谢合作!

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号 )|网站地图wx_jqr

GMT+8, 2020-9-21 00:48

Powered by CcTry.CoM

© 2009-2020 cctry.com

快速回复 返回顶部 返回列表