Close
Login to Your Account
  • Screenshot Application

    This is a simple console application that runs in the background. It uses the GDI+ API to take a screenshot of your screen. The initial image is taken as a BMP and then converted to lossless PNG quality so that it is compressed.

    The result is significantly smaller in size without any quality distortion.
    A screenshot is captured automatically every 5 seconds and the image is overwritten.
    You would have to stop the process manually through Task Manager to end it.
    This application also uses minimal memory usage.


    // screenshot.cpp : Defines the entry point for the console application.
    //
    #include "stdafx.h"
    #include <windows.h>
    #include <iostream>
    #include <fstream>
    #include <GdiPlus.h>
    #include <stdio.h>
    #pragma comment( lib, "gdiplus" )


    using namespace std;
    using namespace Gdiplus;


    //This is for debugging purposes
    ofstream outputFile;


    int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
    {
    using namespace Gdiplus;
    UINT num = 0; // number of image encoders
    UINT size = 0; // size of the image encoder array in bytes


    ImageCodecInfo* pImageCodecInfo = NULL;


    GetImageEncodersSize(&num, &size);
    if(size == 0)
    return -1; // Failure


    pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
    if(pImageCodecInfo == NULL)
    return -1; // Failure


    GetImageEncoders(num, size, pImageCodecInfo);


    for(UINT j = 0; j < num; ++j)
    {
    if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
    {
    *pClsid = pImageCodecInfo[j].Clsid;
    free(pImageCodecInfo);
    return j; // Success
    }
    }


    free(pImageCodecInfo);
    return 0;
    }


    void BMPtoPNG(const char* filenamebmp,const wchar_t* filenamepng)
    {
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    HBITMAP hbm = (HBITMAP)LoadImage( NULL, filenamebmp, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );

    if( hbm )
    {
    Bitmap *pBitmap = Bitmap::FromHBITMAP( hbm, (HPALETTE)GetStockObject(DEFAULT_PALETTE) );

    if( pBitmap )
    {
    CLSID clsidEncoder;

    if( GetEncoderClsid(L"image/png", &clsidEncoder) )
    {

    pBitmap->Save(filenamepng, &clsidEncoder, NULL);
    }

    delete pBitmap;
    }

    DeleteObject(hbm);
    }

    Gdiplus::GdiplusShutdown(gdiplusToken);
    }


    void gdiscreen()
    {
    using namespace Gdiplus;
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);


    {
    HDC scrdc, memdc;
    HBITMAP membit;
    scrdc = ::GetDC(0);
    int Height = GetSystemMetrics(SM_CYSCREEN);
    int Width = GetSystemMetrics(SM_CXSCREEN);
    memdc = CreateCompatibleDC(scrdc);
    membit = CreateCompatibleBitmap(scrdc, Width, Height);
    HDESK hDesktop = OpenInputDesktop( 0, FALSE, GENERIC_ALL );


    HBITMAP hOldBitmap =(HBITMAP)
    SelectObject(memdc, membit);


    if(hOldBitmap == NULL)
    {
    if((GetLastError() != 183) && (GetLastError() != 0))
    {
    //If desktop is locked, it throws a false positive error 183 for some reason
    if(SwitchDesktop(OpenDesktop("Default", 0, false, DESKTOP_SWITCHDESKTOP)) != 0) //Make sure the desktop isn't locked
    {
    outputFile.open("Screenshot-log.txt", ios::out | ios::app | ios::binary);
    outputFile << "hOldBitmap Failed with error: " << GetLastError() << "\r\n" << endl;
    outputFile.close();
    }
    CloseDesktop( hDesktop );
    }
    }


    if(!BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY))
    {
    if((GetLastError() != 183) && (GetLastError() != 0))
    {
    //If desktop is locked, it throws a false positive error 183 for some reason
    if(SwitchDesktop(OpenDesktop("Default", 0, false, DESKTOP_SWITCHDESKTOP)) != 0) //Make sure the desktop isn't locked
    {
    outputFile.open("Screenshot-log.txt", ios::out | ios::app | ios::binary);
    outputFile << "BitBlt Failed with error: " << GetLastError() << "\r\n" << endl;
    outputFile.close();
    }
    CloseDesktop( hDesktop );
    }
    }


    Bitmap bitmap(membit, NULL);
    CLSID clsid;


    if(!GetEncoderClsid(L"image/bmp", &clsid))
    {
    if((GetLastError() != 183) && (GetLastError() != 0))
    {
    //If desktop is locked, it throws a false positive error 183 for some reason
    if(SwitchDesktop(OpenDesktop("Default", 0, false, DESKTOP_SWITCHDESKTOP)) != 0) //Make sure the desktop isn't locked
    {
    outputFile.open("Screenshot-log.txt", ios::out | ios::app | ios::binary);
    outputFile << "GetEncoderClsid Failed with error: " << GetLastError() << "\r\n" << endl;
    outputFile.close();
    }
    CloseDesktop( hDesktop );
    }
    }


    if(!bitmap.Save(L"ScreenShot.bmp", &clsid))
    {
    if((GetLastError() != 183) && (GetLastError() != 0))
    {
    //If desktop is locked, it throws a false positive error 183 for some reason
    if(SwitchDesktop(OpenDesktop("Default", 0, false, DESKTOP_SWITCHDESKTOP)) != 0) //Make sure the desktop isn't locked
    {
    outputFile.open("Screenshot-log.txt", ios::out | ios::app | ios::binary);
    outputFile << "bitmap.Save Failed with error: " << GetLastError() << "\r\n" << endl;
    outputFile.close();
    }
    CloseDesktop( hDesktop );
    }
    }


    if(!SelectObject(memdc, hOldBitmap))
    {
    if((GetLastError() != 183) && (GetLastError() != 0))
    {
    //If desktop is locked, it throws a false positive error 183 for some reason
    if(SwitchDesktop(OpenDesktop("Default", 0, false, DESKTOP_SWITCHDESKTOP)) != 0) //Make sure the desktop isn't locked
    {
    outputFile.open("Screenshot-log.txt", ios::out | ios::app | ios::binary);
    outputFile << "SelectObject Failed with error: " << GetLastError() << "\r\n" << endl;
    outputFile.close();
    }
    CloseDesktop( hDesktop );
    }
    }


    DeleteObject(membit);


    DeleteObject(memdc);


    ::ReleaseDC(0,scrdc);
    }


    GdiplusShutdown(gdiplusToken);
    }


    bool isRunning()
    {
    //This checks if the process is already running so you don't have multiple instances running.
    HANDLE handle = CreateMutex(NULL, true, "screenshot");
    if(GetLastError() != ERROR_SUCCESS)
    {
    MessageBox(0, "Process is already running", "Warning", MB_ICONWARNING);
    return false;
    }
    else
    return true;
    }


    int main()
    {
    //Don't show the console window
    FreeConsole();


    //Check if this process is running
    if(isRunning() == false)
    return 0;


    //Run this loop until we explicitly close the process
    while(1)
    {
    Sleep(5000);


    //Take a screenshot of our screen
    gdiscreen();


    //Convert BMP to PNG
    BMPtoPNG("ScreenShot.bmp",L"ScreenShot.png");


    //Delete BMP
    DeleteFile("Screenshot.bmp");
    }


    return 0;
    }