0

I'm trying to capture a screenshot and then saving it as bmp file.

Why does my program not work when I save the file ?

I put the information into the file and save it where the project is, but when I open the file then nothing appears.

I would appreciate the help.

EDIT: I have updated my code, but still not work, when I open the file then nothing again appears.

#include <iostream>
#include <Windows.h>
#include <fstream>

using namespace std;

int width = GetSystemMetrics(SM_CXSCREEN);
int height = GetSystemMetrics(SM_CYSCREEN);

string deskdir = "C:\\Users\\roile\\Desktop\\";

void screenshot()
{
    HDC     hScreen = GetDC(GetDesktopWindow());
    HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, width, height);

    ofstream image;
    image.open(deskdir + "Image.bmp", ios::binary);
    image << hBitmap;
    image.close();
}

int main()
{
    screenshot();

    return 0;
}
  • 3
    you need to open your stream in binary mode. `image << hBitmap` will just write the bitmap handle to the file. you need to retrieve the bitmap data and write that – Alan Birtles Nov 29 '19 at 08:15
  • 3
    Possible duplicate of [Save HBITMAP to \*.bmp file using only Win32](https://stackoverflow.com/questions/24720451/save-hbitmap-to-bmp-file-using-only-win32) – arsdever Nov 29 '19 at 08:17
  • @AlanBirtles Thanks, I have added `ios::binary ` but still when i open the file nothing appears. –  Nov 29 '19 at 08:17
  • Is there any content in the file or not? – arsdever Nov 29 '19 at 08:18
  • @arsdever Thanks, but i want to do it with a simple way, I don't understand nothing [there](https://stackoverflow.com/questions/24720451/save-hbitmap-to-bmp-file-using-only-win32) –  Nov 29 '19 at 08:18
  • @arsdever No, the file is empty. –  Nov 29 '19 at 08:19
  • There is no simple way I'm afraid, you need to get your hands dirty or find a library that does the work for you. Also note that you don't currently have a screenshot just a bitmap in the same format as your desktop – Alan Birtles Nov 29 '19 at 08:21
  • @AlanBirtles Maybe should i use `BitBlt` ? –  Nov 29 '19 at 08:22
  • 1
    Yes https://stackoverflow.com/questions/16425695/createcompatiblebitmap-returns-black-hbitmap – Alan Birtles Nov 29 '19 at 08:23
  • _No, the file is empty._ Shouldn't it contain at least 4 or 8 bytes? If your file is really empty, then even the writing of the bitmap handle fails. (Two problems: It _fails_ to write the _wrong_ contents, you know?) ;-) – Scheff's Cat Nov 29 '19 at 09:03

1 Answers1

0

HBITMAP is a handle. It is similar to a pointer, it's basically a single integer value which points to a memory location managed by OS, where the bitmap information is stored. This handle is only available to your own process, it is destroyed immediately after process exists.

You have to extract the bitmap information and bits from this HBITMAP handle.

Note that you have to release GDI handles when finished, otherwise your program causes resource leak.

void screenshot()
{
    SetProcessDPIAware();//for DPI awreness
    RECT rc; GetClientRect(GetDesktopWindow(), &rc);
    int width = rc.right;
    int height = rc.bottom;
    auto hdc = GetDC(0);
    auto memdc = CreateCompatibleDC(hdc);
    auto hbitmap = CreateCompatibleBitmap(hdc, width, height);
    auto oldbmp = SelectObject(memdc, hbitmap);
    BitBlt(memdc, 0, 0, width, height, hdc, 0, 0, SRCCOPY);

    WORD bpp = 24; //save as 24bit image
    int size = ((width * bpp + 31) / 32) * 4 * height; //adjust for padding
    BYTE *bits = new BYTE[size]; //you can use std::vector instead of new to prevent leaks

    BITMAPFILEHEADER bf = { 0 };
    bf.bfType = (WORD)'MB';
    bf.bfOffBits = 54;
    bf.bfSize = bf.bfOffBits + size;
    BITMAPINFOHEADER bi = { sizeof(bi), width, height, 1, bpp };
    GetDIBits(hdc, hbitmap, 0, height, bits, (BITMAPINFO*)&bi, 0);

    std::ofstream image("Image.bmp", ios::binary);
    image.write((char*)&bf, sizeof(bf));
    image.write((char*)&bi, sizeof(bi));
    image.write((char*)bits, size);

    delete[] bits;
    SelectObject(memdc, oldbmp);
    DeleteObject(hbitmap);
    DeleteDC(memdc);
    ReleaseDC(0, hdc);
}
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77