没有框架的C / C ++ Capture窗口(有时工作,调试)

时间:2014-01-30 10:00:45

标签: c++ c windows frame printscreen

我一直关注: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183402%28v=vs.85%29.aspx

捕获一个Windows绘图区域,也就是打印它。

重要的功能是“int CaptureAnImage(HWND hWnd)” 当我直接复制并向其发送合法的内容时,每一件工作都很好。

但是我需要能够将它存储在该函数之外(将其作为位图返回),所以我创建了自己的“printscreen”结构。

struct PrintScreen {
    BITMAP * bmpScreen;
    BITMAPFILEHEADER  * bmfHeader;
    BITMAPINFOHEADER  * bi;
    char * data;
    DWORD len;
};

并更改,因此它分配内存,而我在函数中使用指针。

(使用分配的内存和指针的新代码)

    struct PrintScreen * CaptureAnImage(HWND hWnd)
    {
            HDC hdcScreen;
            HDC hdcWindow;
            HDC hdcMemDC = NULL;
            HBITMAP hbmScreen = NULL;


    BITMAP * bmpScreen = GlobalAlloc(GMEM_FIXED,sizeof(BITMAP));
    BITMAPFILEHEADER  * bmfHeader = GlobalAlloc(GMEM_FIXED,sizeof(BITMAPFILEHEADER));
    BITMAPINFOHEADER  * bi = GlobalAlloc(GMEM_FIXED,sizeof(BITMAPINFOHEADER));
    struct PrintScreen * printScreen = GlobalAlloc(GMEM_FIXED,sizeof(struct PrintScreen));

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

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

    if(!hdcMemDC)
    {
        printf("Bajs");
        MessageBox(hWnd, _T("CreateCompatibleDC has failed"),_T("Failed"), MB_OK);
        goto done;
    }

    // Get the client area for size calculation
    RECT rcClient;
    if(!GetClientRect(hWnd, &rcClient)) {
        printf("Treash");
    }
    printf("Rect:%d,%d,%d,%d\n",rcClient.right,rcClient.top, rcClient.left,rcClient.bottom);
    //This is the best stretch mode
    SetStretchBltMode(hdcWindow,HALFTONE);
    SetBrushOrgEx(hdcWindow,0,0,NULL);
    //The source DC is the entire screen and the destination DC is the current window (HWND)
    if(!StretchBlt(hdcWindow,
               0,0,
               rcClient.right, rcClient.bottom,
               hdcScreen,
               0,0,
               GetSystemMetrics (SM_CXSCREEN),
               GetSystemMetrics (SM_CYSCREEN),
               SRCCOPY))
    {
            printf("Bajs");
        MessageBox(hWnd, _T("StretchBlt has failed"),_T("Failed"), MB_OK);
        goto done;
    }

    // Create a compatible bitmap from the Window DC
    hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);
    printf("\n%ld\n",rcClient.right);
    if(!hbmScreen)
    {
        MessageBox(hWnd, _T("CreateCompatibleBitmap Failed"),_T("Failed"), MB_OK);
        goto done;
    }

    // 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,
               rcClient.right-rcClient.left, rcClient.bottom-rcClient.top,
               hdcWindow,
               0,0,
               SRCCOPY))
    {
        MessageBox(hWnd, _T("BitBlt has failed"), _T("Failed"), MB_OK);
        goto done;
    }

    // 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;

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





    char *lpbitmap = (char *)GlobalAlloc(GMEM_FIXED,dwBmpSize);

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


    //findInvWindow(bmpScreen, lpbitmap);

    // A file is created, this is where we will save the screen capture.
    HANDLE hFile = CreateFile(_T("C:\\Users\\Hugo\\Dropbox\\Code blocks\\Test\\Poe Test\\bin\\Debug\\captureqwsx.bmp"),
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL, NULL);

    if(hFile ==  INVALID_HANDLE_VALUE) {
        printf("Error creating file");
    }
    printf("Done");

    // Add the size of the headers to the size of the bitmap to get the total file size
    DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    printf("Size:%d\n",dwBmpSize);
    //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

    DWORD dwBytesWritten = 0;
    WriteFile(hFile, (LPSTR)bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);



    //Close the handle for the file that was created
    CloseHandle(hFile);


    printScreen->bmpScreen = bmpScreen;
    printScreen->bmfHeader = bmfHeader;
    printScreen->bi = bi;
    printScreen->data = lpbitmap;
    printScreen->len = dwSizeofDIB;

    //Clean up
done:
    DeleteObject(hbmScreen);
    DeleteObject(hdcMemDC);
    ReleaseDC(NULL,hdcScreen);
    ReleaseDC(hWnd,hdcWindow);

    return printScreen;
}

我的问题是,有时它工作正常,我得到一个没有框架的合法版画屏幕,但我经常得到框架,图像的大小不会改变,但它压缩它所以窗口的框架是里面也是。

我试过调试什么功能可能会这样,等等,但有点新的C,从我的观点来看,所有功能都表示他们已经成功了。

编辑: 带框架 http://i62.tinypic.com/2uifyj4.jpg

没有,因为它应该是:(编辑链接)  http://i.stack.imgur.com/iMxhM.jpg

抱歉没有直接链接,但必须为此点亮代表。并且显然不能发布超过2个链接。

EDIT2: 显然,错误不是帧被添加,而是捕获窗口数据,它捕获整个窗口的“上/下”,包括帧。

仍然不知道是什么原因导致它有时获得正确的数据,有时却没有。所有功能都返回成功...(更新“帧”图片以显示错误)

0 个答案:

没有答案