WIN32截屏特定窗口的特定区域

该代码示例展示了如何在WIN32环境下进行屏幕截取,可以指定目标窗口,截取后的图像可以显示在自定义窗口控件或屏幕上。函数CaptureImage接收参数如窗口句柄、坐标和尺寸,完成截屏并保存为BMP文件。
摘要由CSDN通过智能技术生成

以下记录WIN32进行截屏的要点。可截取特定目标窗口,截取结果可显示到自定窗口的控件,或显示在屏幕。本示例为显示在屏幕右上角。

string mp_ws2s(const wstring& ws)
{
    std::string curLocale = setlocale(LC_ALL, NULL);        // curLocale = "C";
    setlocale(LC_ALL, "chs");
    const wchar_t* _Source = ws.c_str();
    size_t _Dsize = 2 * ws.size() + 1;
    char *_Dest = new char[_Dsize];
    memset(_Dest,0,_Dsize);
    wcstombs(_Dest,_Source,_Dsize);
    std::string result = _Dest;
    delete []_Dest;
    setlocale(LC_ALL, curLocale.c_str());
    return result;
}

wstring mp_s2ws(const string& s)
{
    setlocale(LC_ALL, "chs"); 
    const char* _Source = s.c_str();
    size_t _Dsize = s.size() + 1;
    wchar_t *_Dest = new wchar_t[_Dsize];
    wmemset(_Dest, 0, _Dsize);
    mbstowcs(_Dest,_Source,_Dsize);
    std::wstring result = _Dest;
    delete []_Dest;
    setlocale(LC_ALL, "C");
    return result;
}
 

//参数说明:
//  hWndDisplay:截屏图片显示的窗口,可为自己窗口内的一个控件的窗口句柄,若为NULL,则在屏幕上进行显示
//  hWndTarget:截屏目标窗口句柄
//  iOriginX:截屏区域X坐标
//  iOriginY:截屏区域Y坐标
//  iWidth:截屏区域宽度
//  iHeight:截屏区域高度
//  strBmpFileName:截取后图片保存的文件名
//  strMsg:错误信息
bool CaptureImage(HWND hWndDisplay,
    HWND hWndTarget,
    int iOriginX,
    int iOriginY,
    int iWidth,
    int iHeight,
    string strBmpFileName,
    string& strMsg)
{
    RECT    rect;
    HDC     hdcScreen = NULL;
    HDC     hdcWindow = NULL;
    HDC     hdcMemDC = NULL;
    HBITMAP hbmScreen = NULL;
    BITMAP  bmpScreen;
    DWORD   dwBytesWritten = 0;
    DWORD   dwSizeofDIB = 0;
    HANDLE  hFile = INVALID_HANDLE_VALUE;
    char*   lpbitmap = NULL;
    HANDLE  hDIB = NULL;
    DWORD   dwBmpSize = 0;
    string  strCaptureBmp = strBmpFileName;
    wstring wsCaptureBmp = mp_s2ws(strCaptureBmp);
    BITMAPFILEHEADER   bmfHeader;
    BITMAPINFOHEADER   bi;

    int capX;
    int capY;

    bool bRet = false;
    strMsg = "";
    do
    {
        //获取屏幕宽度和高度
        hdcScreen = GetDC(NULL);
        capX = GetDeviceCaps(hdcScreen, HORZRES);
        capY = GetDeviceCaps(hdcScreen, VERTRES);
        ReleaseDC(NULL,hdcScreen);

        if(cMyUtility::mp_isFileExists((char*)strCaptureBmp.c_str()))
        {
            DeleteFile(wsCaptureBmp.c_str());
        }

        GetWindowRect(hWndTarget,&rect);

        // Retrieve the handle to a display device context for the client 
        // area of the window. 
        hdcScreen = GetDC(hWndTarget);
        if(hdcScreen == NULL)
        {
            strMsg = "GetDC(NULL) fail";
            break;
        }
        //hwndDisplay = GetDlgItem(pTabWndInfo->hDlg,IDC_BUTTON_CAPTURE_IMG);
        hWndDisplay = NULL;
        hdcWindow = GetDC(hWndDisplay);
        if(hdcWindow == NULL)
        {
            strMsg = "GetDC(hwndDisplay) fail";
            break;
        }

        // Create a compatible DC, which is used in a BitBlt from the window DC.
        hdcMemDC = CreateCompatibleDC(hdcWindow);
        if (!hdcMemDC)
        {
            strMsg = "CreateCompatibleDC fail";
            break;
        }

        // 显示位置为屏幕右上角
        RECT rcClient;
        rcClient.left = capX-10-iWidth;
        rcClient.top = 10;
        rcClient.right = capX-10;
        rcClient.bottom = iHeight+10;

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

        if (!StretchBlt(hdcWindow,
            rcClient.left, 
            rcClient.top,
            iWidth,
            iHeight,
            hdcScreen,
            iOriginX, 
            iOriginY,
            iWidth,
            iHeight,
            SRCCOPY))
        {
            strMsg = "StretchBlt fail";
            break;
        }

        // Create a compatible bitmap from the Window DC.
        hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
        if (!hbmScreen)
        {
            strMsg = "CreateCompatibleBitmap fail";
            break;
        }

        // Select the compatible bitmap into the compatible memory DC.
        SelectObject(hdcMemDC, hbmScreen);

        // Bit block transfer into our compatible memory DC.
        if (!BitBlt(hdcMemDC,
            0, 
            0,
            iWidth, 
            iHeight,
            hdcWindow,
            rcClient.left,
            rcClient.top,
            SRCCOPY))
        {
            strMsg = "BitBlt fail";
            break;
        }

        // Get the BITMAP from the HBITMAP.
        GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen);

        bi.biSize = sizeof(BITMAPINFOHEADER);
        bi.biWidth = bmpScreen.bmWidth;
        bi.biHeight = bmpScreen.bmHeight;
        bi.biPlanes = 1;
        bi.biBitCount = 32;
        bi.biCompression = BI_RGB;
        bi.biSizeImage = 0;
        bi.biXPelsPerMeter = 0;
        bi.biYPelsPerMeter = 0;
        bi.biClrUsed = 0;
        bi.biClrImportant = 0;

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

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

        // Gets the "bits" from the bitmap, and copies them into a buffer 
        // that's pointed to by lpbitmap.
        GetDIBits(hdcWindow, hbmScreen, 0,
            (UINT)bmpScreen.bmHeight,
            lpbitmap,
            (BITMAPINFO*)&bi, DIB_RGB_COLORS);

        // A file is created, this is where we will save the screen capture.
        hFile = CreateFile(wsCaptureBmp.c_str(),
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL, NULL);
        if(hFile != INVALID_HANDLE_VALUE)
        {
            // Add the size of the headers to the size of the bitmap to get the total file size.
            dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

            // Offset to where the actual bitmap bits start.
            bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);

            // Size of the file.
            bmfHeader.bfSize = dwSizeofDIB;

            // bfType must always be BM for Bitmaps.
            bmfHeader.bfType = 0x4D42; // BM.

            WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
            WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
            WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
        }
        // Unlock and Free the DIB from the heap.
        GlobalUnlock(hDIB);
        GlobalFree(hDIB);

        bRet = true;
    }while(0);

    if(hFile != INVALID_HANDLE_VALUE)
    {
        CloseHandle(hFile);
        hFile = INVALID_HANDLE_VALUE;
    }

    // Clean up.
    if(hbmScreen)
    {
        DeleteObject(hbmScreen);
        hbmScreen = NULL;
    }
    if(hdcMemDC)
    {
        DeleteObject(hdcMemDC);
        hdcMemDC = NULL;
    }
    if(hdcScreen)
    {
        ReleaseDC(NULL,hdcScreen);
        hdcScreen = NULL;
    }
    if(hdcWindow)
    {
        ReleaseDC(hWndDisplay,hdcWindow);
        hdcWindow = NULL;
    }

    return bRet;
}
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值