I would like to take a screenshot of a region of my screen programmatically (so I can do it every time through a loop, for example.) Does anyone know how to do this? I guess it would involve the win32api - I've not used this before so any hints would be great!

Thanks,

Dave

Recommended Answers

All 14 Replies

I would like to take a screenshot of a region of my screen programmatically (so I can do it every time through a loop, for example.) Does anyone know how to do this? I guess it would involve the win32api - I've not used this before so any hints would be great!

Thanks,

Dave

You can use the windows GDI functions. You'll need to include the GDI library, and windows.h.

GetDC(0) returns the device context of the screen. You can copy the screen to a bitmap you create with CreateBitmap, or CreateCompatibleBitmap using BitBlt.

Here's an example of copying the screen onto itself (very simplistic, but shows it's working)

BitBlt(GetDC(0), 300, 300, 300, 300, GetDC(0), 0, 0, SRCCOPY);

here's a link with an example

dougy83, thanks, i'll take a look

niek_e - that example seems to use a sendkeys printscreen type of thing - i was thinking more along the lines of selecting a region to capture

i'll report back on the GDI stuff - dougy83, how would I save that to a file?

dougy83 - how do i save it to a file? I have the simple example of just writing it back to the screen working so far!

Thanks,

Dave

You can do something like try to give the computer coordinates and then take a whole screenshot of your computer After that cut of all other parts except the selected coordinates.

OOPS LATE ANSWER

dougy83, thanks, i'll take a look

niek_e - that example seems to use a sendkeys printscreen type of thing - i was thinking more along the lines of selecting a region to capture

i'll report back on the GDI stuff - dougy83, how would I save that to a file?

Sorry david for not writing, i's busy.

While that example might use the clipboard, the bmp saving part is still relevant for what you want to do. You would just have to copy the screen to a memory bitmap you create.

Here's a working example for you to use; hope it's of use.

#include <windows.h>

bool SaveBMPFile(char *filename, HBITMAP bitmap, HDC bitmapDC, int width, int height);

bool ScreenCapture(int x, int y, int width, int height, char *filename){
   // get a DC compat. w/ the screen
   HDC hDc = CreateCompatibleDC(0);    
   
   // make a bmp in memory to store the capture in
   HBITMAP hBmp = CreateCompatibleBitmap(GetDC(0), width, height);   
   
   // join em up
   SelectObject(hDc, hBmp);   
   
   // copy from the screen to my bitmap
   BitBlt(hDc, 0, 0, width, height, GetDC(0), x, y, SRCCOPY);  
   
   // save my bitmap
   bool ret = SaveBMPFile(filename, hBmp, hDc, width, height); 
   
   // free the bitmap memory
   DeleteObject(hBmp);  
   
   return ret;
   }
   
main(){
   ScreenCapture(500, 200, 300, 300, "c:\\testScreenCap.bmp");
   system("pause");
   }

The SaveBMPFile function referenced above is attached (I didn't write it), or you could cut-and-paste from the 'printscreen'-type example code.

is it possible to write a program in C(only C) for windows to capture the screen and save it as a picture. if yes please share your work such that i can enhance my knowledge..

See above. There aren't many differences.

i tried it but no use

What did you try, and what errors did you get?

i changed cpp code to C... in that process i did few changes like changing "new" keyword with malloc(saveBMP.cpp) but no use...

#include <windows.h>
#include <stdio.h>

#define GetPixel(Bmp, X, Y) (((Bmp)->Pixels[(Y) * (Bmp)->Width + (X)]) & 0x00FFFFFF)
#define PixelToColour(Pixel) (COLORREF)(((Pixel) & 0xFF00FF00) | (((Pixel) & 0xFF0000) >> 16) | (((Pixel) & 0xFF) << 16))

typedef struct
{
    HBITMAP hBmp;
    int Width, Height;
    unsigned int* Pixels;
    unsigned short BitsPerPixel;
} BmpData;

typedef enum {false = 0, true = 1} bool;

bool ScreenShot(BmpData* Data)
{
    bool Result = false;
    memset(Data, 0, sizeof(BmpData));
    HDC hdcScreen = GetDC(NULL);
    HDC hdcMem = CreateCompatibleDC(NULL);
    Data->Width = GetDeviceCaps(hdcScreen, HORZRES);
    Data->Height = GetDeviceCaps(hdcScreen, VERTRES);

    unsigned char* Pixels = NULL;
    unsigned short BitsPerPixel = 32;
    BITMAPINFO Info = {{sizeof(BITMAPINFOHEADER), Data->Width, -Data->Height, 1, BitsPerPixel, BI_RGB, 0, 0, 0, 0, 0}};

    Data->hBmp = CreateDIBSection(hdcScreen, &Info, DIB_RGB_COLORS, (void**)&Pixels, NULL, 0);
    if(Data->hBmp)
    {
        HBITMAP hOld = (HBITMAP)SelectObject(hdcMem, Data->hBmp);
        BitBlt(hdcMem, 0, 0, Data->Width, Data->Height, hdcScreen, 0, 0, SRCCOPY);
        SelectObject(hdcMem, hOld);
        Data->Height *= -1;
        Data->BitsPerPixel = BitsPerPixel;
        Data->Pixels = (unsigned int*)Pixels;
        Result = true;
    }

    DeleteDC(hdcMem);
    DeleteDC(hdcScreen);
    return Result;
}

void SaveBitmap(const char* FilePath, const BmpData* Data)
{
    FILE* hFile = fopen(FilePath, "wb+");
    if (!hFile)
    {
        printf("%s", "Error. Cannot Create Bitmap.");
        return;
    }

    unsigned int Trash = 0;
    unsigned short Planes = 1;
    unsigned int biSize = 40;
    unsigned short Type = 0x4D42;
    unsigned int compression = 0;
    unsigned int PixelsOffsetBits = 54;
    int Width = Data->Width;
    int Height = -Data->Height;
    unsigned short BitsPerPixel = Data->BitsPerPixel;
    unsigned int size = ((Width * BitsPerPixel + 31) / 32) * 4 * Height;
    unsigned int bfSize = 54 + size;
    Height *= -1;

    fwrite(&Type, sizeof(char), sizeof(Type), hFile);
    fwrite(&bfSize, sizeof(char), sizeof(bfSize), hFile);
    fwrite(&Trash, sizeof(char), sizeof(Trash), hFile);
    fwrite(&PixelsOffsetBits, sizeof(char), sizeof(PixelsOffsetBits), hFile);
    fwrite(&biSize, sizeof(char), sizeof(biSize), hFile);
    fwrite(&Width, sizeof(char), sizeof(Width), hFile);
    fwrite(&Height, sizeof(char), sizeof(Height), hFile);
    fwrite(&Planes, sizeof(char), sizeof(Planes), hFile);
    fwrite(&BitsPerPixel, sizeof(char), sizeof(BitsPerPixel), hFile);
    fwrite(&compression, sizeof(char), sizeof(compression), hFile);
    fwrite(&size, sizeof(char), sizeof(size), hFile);
    fwrite(&Trash, sizeof(char), sizeof(Trash), hFile);
    fwrite(&Trash, sizeof(char), sizeof(Trash), hFile);
    fwrite(&Trash, sizeof(char), sizeof(Trash), hFile);
    fwrite(&Trash, sizeof(char), sizeof(Trash), hFile);
    fwrite(&Data->Pixels, sizeof(char), size, hFile);
    fclose(hFile);
}

int main()
{
    int X = 15, Y = 16;
    BmpData Data = {0};
    ScreenShot(&Data);
    printf("The colour at: (%i, %i) is: %lu\n\n", X, Y, PixelToColour(GetPixel(&Data, X, Y)));
    SaveBitmap("C:/Users/Brandon/Desktop/Foo.bmp", &Data);
    DeleteObject(Data.hBmp);
    return 0;
}

Everything works except the stupid SaveBitmap. I'm not sure why it won't save properly but I translated it from my C++ code below which works

void SaveBitmap(const char* FilePath, const BmpData* Data)
{
    std::fstream hFile(FilePath, std::ios::out | std::ios::binary);
    if (!hFile.is_open())
    {
        printf("%s", "Error. Cannot Create Bitmap.");
        return;
    }

    unsigned int Trash = 0;
    unsigned short Planes = 1;
    unsigned int biSize = 40;
    unsigned short Type = 0x4D42;
    unsigned int compression = 0;
    unsigned int PixelsOffsetBits = 54;
    int Width = Data->Width;
    int Height = -Data->Height;
    unsigned short BitsPerPixel = Data->BitsPerPixel;
    unsigned int size = ((Width * BitsPerPixel + 31) / 32) * 4 * Height;
    unsigned int bfSize = 54 + size;
    Height *= -1;

    hFile.write(reinterpret_cast<char*>(&Type), sizeof(Type));
    hFile.write(reinterpret_cast<char*>(&bfSize), sizeof(bfSize));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(Trash));
    hFile.write(reinterpret_cast<char*>(&PixelsOffsetBits), sizeof(PixelsOffsetBits));
    hFile.write(reinterpret_cast<char*>(&biSize), sizeof(biSize));
    hFile.write(reinterpret_cast<char*>(&Width), sizeof(Width));
    hFile.write(reinterpret_cast<char*>(&Height), sizeof(Height));
    hFile.write(reinterpret_cast<char*>(&Planes), sizeof(Planes));
    hFile.write(reinterpret_cast<char*>(&BitsPerPixel), sizeof(BitsPerPixel));
    hFile.write(reinterpret_cast<char*>(&compression), sizeof(compression));
    hFile.write(reinterpret_cast<char*>(&size), sizeof(size));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(Trash));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(Trash));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(Trash));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(Trash));
    hFile.write(reinterpret_cast<char*>(Data->Pixels), size);
    hFile.close();
}

Everything works except the stupid SaveBitmap. I'm not sure why it won't save properly but I translated it from my C++ code below which works

Are you using a 64-bit OS and compiler? If so, all of your int types will be 8 bytes rather than 4. So try #including <cstdint>, and use the size-specific types, e.g. uint32_t, int32_t, etc. if this is the issue.

I just downloaded the original code and after defining {bool, true, false} and replacing new with malloc it compiled and ran fine, creating the bmp on my desktop (note I had to change the save directory from "c:\" to a directory I have write access to). This was on a Win-7 32-bit system.

Note that the original savebitmap function doesn't free the allocated memory.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.