Frawley

Ok, it took me forever to piece this code together and have it almost work but now I've run into a problem I can't figure out. I am trying to take a snapshot of the desktop and then save it to a file called "test.bmp". Everything works fine and I get the file to be saved but when I open it with notepad, it shows the normal BMP header but all of the bits are just spaces. If I open the file in ms paint its just a black background. If you can provide any help it would be greatly appreciated.

I think the problem is when I use BitBlt to get the screenshot. How do I extract the image from the hdcCompatible

The code:

Code Block

#include <windows.h>

#include <gdiplus.h>

#include <fstream>

#include <iostream>

#pragma comment(lib, "gdiplus.lib")

using namespace std;

PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp);

void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);

int CaptureScreen(HWND hWindow, int hideWindow)

{

HDC hdcScreen = CreateDCA("DISPLAY", NULL, NULL, NULL);

HDC hdcCompatible = CreateCompatibleDC(hdcScreen);

HBITMAP hbmScreen = CreateCompatibleBitmap(hdcCompatible, GetDeviceCaps(hdcScreen, HORZRES), GetDeviceCaps(hdcScreen, VERTRES));

if(hbmScreen == 0)

{

return 0;

}

if(!SelectObject(hdcCompatible, hbmScreen))

{

return 0;

}

if(hideWindow == true)

{

ShowWindow(hWindow, SW_HIDE);

}

if(!BitBlt(hdcCompatible, 0, 0, GetDeviceCaps(hdcScreen, HORZRES), GetDeviceCaps(hdcScreen, VERTRES), hdcScreen, 0, 0, SRCCOPY))

{

return 0;

}

if(hideWindow == true)

{

ShowWindow(hWindow, SW_SHOW);

}

PBITMAPINFO bmpInfo = CreateBitmapInfoStruct(hWindow, hbmScreen);

CreateBMPFile(hWindow, L"test.bmp", bmpInfo, hbmScreen, hdcScreen);

}

PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)

{

BITMAP bmp;

PBITMAPINFO pbmi;

WORD cClrBits;

// Retrieve the bitmap color format, width, and height.

if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))

return 0;

// Convert the color format to a count of bits.

cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);

if (cClrBits == 1)

cClrBits = 1;

else if (cClrBits <= 4)

cClrBits = 4;

else if (cClrBits <= 8)

cClrBits = 8;

else if (cClrBits <= 16)

cClrBits = 16;

else if (cClrBits <= 24)

cClrBits = 24;

else cClrBits = 32;

// Allocate memory for the BITMAPINFO structure. (This structure

// contains a BITMAPINFOHEADER structure and an array of RGBQUAD

// data structures.)

if (cClrBits != 24)

pbmi = (PBITMAPINFO) LocalAlloc(LPTR,

sizeof(BITMAPINFOHEADER) +

sizeof(RGBQUAD) * (1<< cClrBits));

// There is no RGBQUAD array for the 24-bit-per-pixel format.

else

pbmi = (PBITMAPINFO) LocalAlloc(LPTR,

sizeof(BITMAPINFOHEADER));

// Initialize the fields in the BITMAPINFO structure.

pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

pbmi->bmiHeader.biWidth = bmp.bmWidth;

pbmi->bmiHeader.biHeight = bmp.bmHeight;

pbmi->bmiHeader.biPlanes = bmp.bmPlanes;

pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;

if (cClrBits < 24)

pbmi->bmiHeader.biClrUsed = (1<<cClrBits);

// If the bitmap is not compressed, set the BI_RGB flag.

pbmi->bmiHeader.biCompression = BI_RGB;

// Compute the number of bytes in the array of color

// indices and store the result in biSizeImage.

// For Windows NT, the width must be DWORD aligned unless

// the bitmap is RLE compressed. This example shows this.

// For Windows 95/98/Me, the width must be WORD aligned unless the

// bitmap is RLE compressed.

pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8

* pbmi->bmiHeader.biHeight;

// Set biClrImportant to 0, indicating that all of the

// device colors are important.

pbmi->bmiHeader.biClrImportant = 0;

return pbmi;

}

void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)

{

HANDLE hf; // file handle

BITMAPFILEHEADER hdr; // bitmap file-header

PBITMAPINFOHEADER pbih; // bitmap info-header

LPBYTE lpBits; // memory pointer

DWORD dwTotal; // total count of bytes

DWORD cb; // incremental count of bytes

BYTE *hp; // byte pointer

DWORD dwTmp;

pbih = (PBITMAPINFOHEADER) pbi;

lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

if (!lpBits)

return;

// Retrieve the color table (RGBQUAD array) and the bits

// (array of palette indices) from the DIB.

if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi,

DIB_RGB_COLORS))

{

return;

}

// Create the .BMP file.

hf = CreateFile(pszFile,

GENERIC_READ | GENERIC_WRITE,

(DWORD) 0,

NULL,

CREATE_ALWAYS,

FILE_ATTRIBUTE_NORMAL,

(HANDLE) NULL);

if (hf == INVALID_HANDLE_VALUE)

return;

hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"

// Compute the size of the entire file.

hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +

pbih->biSize + pbih->biClrUsed

* sizeof(RGBQUAD) + pbih->biSizeImage);

hdr.bfReserved1 = 0;

hdr.bfReserved2 = 0;

// Compute the offset to the array of color indices.

hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +

pbih->biSize + pbih->biClrUsed

* sizeof (RGBQUAD);

// Copy the BITMAPFILEHEADER into the .BMP file.

if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),

(LPDWORD) &dwTmp, NULL))

{

return;

}

// Copy the BITMAPINFOHEADER and RGBQUAD array into the file.

if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)

+ pbih->biClrUsed * sizeof (RGBQUAD),

(LPDWORD) &dwTmp, ( NULL)))

return;

// Copy the array of color indices into the .BMP file.

dwTotal = cb = pbih->biSizeImage;

hp = lpBits;

if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL))

return;

// Close the .BMP file.

if (!CloseHandle(hf))

return;

// Free memory.

GlobalFree((HGLOBAL)lpBits);

}



Re: Visual C++ General Trouble with bitmaps

Viorel.

Frawley wrote:

Code Block

[...]

CreateBMPFile(hWindow, L"test.bmp", bmpInfo, hbmScreen, hdcScreen);

[...]

Maybe you have to change the last argument

CreateBMPFile(. . ., hdcCompatible);





Re: Visual C++ General Trouble with bitmaps

Frawley

I tried that. I realized that the problem is the bitmap image never gets the data from the screenshot. the hdcCompatible variable actually holds the value from the BitBlt function. Now how do I get the data from there x_X





Re: Visual C++ General Trouble with bitmaps

Viorel.

I hope one more adjustment will help:

HBITMAP hbmScreen = CreateCompatibleBitmap(hdcScreen, . . .);





Re: Visual C++ General Trouble with bitmaps

Frawley

No, I realized that the problem is changing the data from hdcCompatible to a bitmap. I don't understand this concept at all X_X





Re: Visual C++ General Trouble with bitmaps

Bite Qiu - MSFT

Frawley wrote:
No, I realized that the problem is changing the data from hdcCompatible to a bitmap. I don't understand this concept at all X_X

Hello, is the problem persist Combine both adjustments suggested by Viorel, the code works fine for me, so I am marking his posts as answer, If the problem persist, please follow up with further information, thanks.