1

I have been following: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183402%28v=vs.85%29.aspx

To capture a windows drawing area aka printscreen it.

The important function is "int CaptureAnImage(HWND hWnd)" and everyting works fine when I copy it straight of and sends a legit hWnd to it.

However I need to be able to store it outside of that function (return it as a bitmap) so I have created my own "printscreen" struct.

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

and changed so it allocates memory and I use pointers in the function instead.

(New code using allocated memory and pointers)

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

My problem is, sometimes it works fine and I get a legit printscreen without frames, but every so often I get the frames also, the size of the image doesn't change but it compresses it so the frame of the window is inside too.

I tried debugging what function might couse this and so on, but kinda new to C and from my point all functions say they succed.

EDIT: With frame http://i62.tinypic.com/2uifyj4.jpg

Without, as it should be: (edit to link) https://i.stack.imgur.com/iMxhM.jpg

sorry for not direct linking but have to litle rep for that. AND cannot post more then 2 links apparently.

EDIT2: Apperently the error isn't that the frame gets added, instead of capturing the window data, it captures whatever is "over/inside" of the whole window, including the frames.

Still no idea what causes it to sometimes get right data and sometimes not. All functions return success... (Updated "frame" picture to show the error)

user3252497
  • 121
  • 4

0 Answers0