Click here to Skip to main content
Click here to Skip to main content

Screen and Form capture with Managed C++

By , 3 Jul 2002
 

Introduction

I was continuing to play around with IJW. And when I realized that there was no direct Screen Capture method in .NET, I thought I might as well try to make a simple Screen Capturing program. Of course since I knew as much about GDI programming as some of these Canadians seem to know about Cricket, you might as well have guessed that I found things more than a little difficult. Luckily Tom Archer, James Johnson and Neil Van Note promptly answered my questions.

The sample program allows you to capture the entire screen or only the current form and also allows you to save the image, though here I have hard coded the filename and path, as I was too lazy to show a save dialog. If you repeatedly click on the capture buttons, you get a weird effect of cascading screen captures, one on top of the other as shown in the screenshot of the sample program.

Quick Rundown

Using GetDC or GetWindowDC depending on whether we are capturing the screen or the current window, we get our HDC using which we call CreateCompatibleDC to create our memory DC. Using a call to GetSystemMetrics we get the size of the screen and then call CreateCompatibleBitmap to create a bitmap. Then we select this bitmap into the memory DC using a call to SelectObject and save the old bitmap. Using BitBlt we copy the screen or window contents into this bitmap which is now selected into the memory DC. Then we select the original bitmap back into the DC, delete the memory DC, release the DC, and delete the bitmap. To be frank, there is not much .NET stuff involved in the code, but imagine if you had to write all this using C#. Think of all the P/Invoke stuff you'd have to do and the ugly declarations you'd have had to write for the API calls. With MC++ you are saved all that bother.

Full Source Listing

The source code is self-explanatory. Notice how I have written my WinMain. This is because I am including windows.h where WinMain is already prototyped in that fashion.

#include "stdafx.h"

#using <mscorlib.dll>
#using <System.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>

#include <tchar.h>
#include <windows.h>

using namespace System;
using namespace System::ComponentModel;
using namespace System::Drawing;
using namespace System::Windows::Forms;

public __gc class NForm : public Form
{
public:
    Button *btn;
    Button *btn2;
    Button *btn3;
    PictureBox *pbox;
    void btn_Click(Object *sender, System::EventArgs* e); 
    void CaptureScreen(bool FullScreen);

    NForm()
    {
        this->StartPosition = FormStartPosition::CenterScreen;
        this->Text = "Capture screen - Nish for CodeProject -IJW";
        this->Size = Drawing::Size(750,550);
        this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedDialog; 

        btn=new Button();
        btn->Text="Capture Screen";
        btn->Location=Point(5,5);
        btn->Size=Drawing::Size(100,30);
        btn->add_Click(new EventHandler(this,&NForm::btn_Click)); 
        this->Controls->Add(btn);

        btn2=new Button();
        btn2->Text="Capture Form";
        btn2->Location=Point(125,5);
        btn2->Size=Drawing::Size(100,30);
        btn2->add_Click(new EventHandler(this,&NForm::btn_Click)); 
        this->Controls->Add(btn2);

        btn3=new Button();
        btn3->Text="Save C:\\Z.Jpg";
        btn3->Location=Point(250,5);
        btn3->Size=Drawing::Size(100,30);
        btn3->add_Click(new EventHandler(this,&NForm::btn_Click)); 
        this->Controls->Add(btn3);

        pbox = new PictureBox();
        pbox->Location=Point(5,45);
        pbox->Size=Drawing::Size(730,470);
        pbox->BorderStyle = BorderStyle::Fixed3D;
        pbox->SizeMode = PictureBoxSizeMode::StretchImage;


        this->Controls->Add(pbox);
    }
};

int __stdcall WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
    Application::Run(new NForm());
    return 0;
}

void NForm::btn_Click(Object *sender, System::EventArgs *e)
{
    if(sender->Equals(btn))
        CaptureScreen(true);
    else
    {
        if(sender->Equals(btn2))
            CaptureScreen(false);
        else
            pbox->Image->Save("C:\\Z.Jpg",
                Drawing::Imaging::ImageFormat::Jpeg);
    }
}

void NForm::CaptureScreen(bool FullScreen)
{
    HDC hDC;
    if(FullScreen)
        hDC = GetDC(NULL); //Get full screen
    else
    {
        HWND hWnd=(HWND)this->Handle.ToInt32(); //Get HWND of form
        hDC = GetWindowDC(hWnd); //Now get it's DC handle 
    }
    HDC hMemDC = CreateCompatibleDC(hDC);
    RECT r;
    GetWindowRect((HWND)this->Handle.ToInt32(),&r); //need this for Form
    SIZE size;
    if(FullScreen)
    { 
        size.cx = GetSystemMetrics(SM_CXSCREEN);
        size.cy = GetSystemMetrics(SM_CYSCREEN);
    } 
    else
    {
        size.cx = r.right-r.left;
        size.cy = r.bottom-r.top;
    }

    //most of the remaining code is normal GDI stuff

    HBITMAP hBitmap = CreateCompatibleBitmap(hDC, size.cx, size.cy);
    if (hBitmap)
    {
        HBITMAP hOld = (HBITMAP) SelectObject(hMemDC, hBitmap);
        BitBlt(hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, SRCCOPY);
        SelectObject(hMemDC, hOld);
        DeleteDC(hMemDC);
        ReleaseDC(NULL, hDC);
        pbox->Image = Image::FromHbitmap(hBitmap); 
        DeleteObject(hBitmap);
    }
}

History

  • May 7 02 - Posted the article
  • Jul 4 02 - Added sample VC++ project

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Nish Sivakumar
United States United States
Member
Nish is a real nice guy who has been writing code since 1990 when he first got his hands on an 8088 with 640 KB RAM. Originally from sunny Trivandrum in India, he has been living in various places over the past few years and often thinks it’s time he settled down somewhere.
 
Nish has been a Microsoft Visual C++ MVP since October, 2002 - awfully nice of Microsoft, he thinks. He maintains an MVP tips and tricks web site - www.voidnish.com where you can find a consolidated list of his articles, writings and ideas on VC++, MFC, .NET and C++/CLI. Oh, and you might want to check out his blog on C++/CLI, MFC, .NET and a lot of other stuff - blog.voidnish.com.
 
Nish loves reading Science Fiction, P G Wodehouse and Agatha Christie, and also fancies himself to be a decent writer of sorts. He has authored a romantic comedy Summer Love and Some more Cricket as well as a programming book – Extending MFC applications with the .NET Framework.
 
Nish's latest book C++/CLI in Action published by Manning Publications is now available for purchase. You can read more about the book on his blog.
 
Despite his wife's attempts to get him into cooking, his best effort so far has been a badly done omelette. Some day, he hopes to be a good cook, and to cook a tasty dinner for his wife.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberAziz Yosofi6 Feb '13 - 22:25 
Questionexcuse me, i have a problem in capturing when i play the videomemberzhmx_love21 Aug '12 - 22:47 
GeneralMy vote of 5memberMember 923867912 Jul '12 - 22:27 
QuestionQuestions regarding your articlememberOlariu Bogdan25 May '10 - 1:23 
Hi,
 
I have 2 questions:
 
1) I have tried to use your code to enhance my application to save the current frame to bitmap but I encounter the following error:
 
>d:\visual studio 2005\projects\windowsformscpp\windowsformscpp\Form1.h(292) : error C2665: 'System::Drawing::Image::FromHbitmap' : none of the 2 overloads could convert all the argument types
1> c:\winnt\microsoft.net\framework\v2.0.50727\system.drawing.dll: could be 'System::Drawing::Bitmap ^System::Drawing::Image::FromHbitmap(System::IntPtr)'
1> while trying to match the argument list '(HBITMAP)'
 
2) Can I avoid to use pictureBox1 object and save the bitmap to file directly from hMemDC
 
Below you have a listing with my code:
 
HDC hDC;
 
HWND hWnd=(HWND)this->Handle.ToInt32(); //Get HWND of form

hDC = GetWindowDC(hWnd); //Now get it's DC handle
 
HDC hMemDC = CreateCompatibleDC(hDC);
RECT r;
GetWindowRect((HWND)this->Handle.ToInt32(),&r); //need this for Form
 
SIZE size;
 
size.cx = r.right-r.left;
size.cy = r.bottom-r.top;
 
HBITMAP hBitmap = CreateCompatibleBitmap(hDC, size.cx, size.cy);
 
if (hBitmap)
{
HBITMAP hOld = (HBITMAP) SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hOld);
 
pictureBox1->Image = Image::FromHbitmap(hBitmap);
//pbox->Image->Save("C:\\Z.Jpg", Drawing::Imaging::ImageFormat::Jpeg);
 
DeleteDC(hMemDC);
ReleaseDC(NULL, hDC);

DeleteObject(hBitmap);
}
AnswerRe: Questions regarding your articlemvpNishant Sivakumar25 May '10 - 1:29 
GeneralRe: Questions regarding your articlememberOlariu Bogdan25 May '10 - 23:39 
Questionhow to get the image containing total content of entire form in .net windows applicationmemberm.raghu18 Jun '07 - 19:13 
QuestionHow CreateDIBSection Work???memberjavad_200524 Sep '06 - 9:32 
QuestionC++/CLI Image::FromHBitmapmemberCoder2k25 Jun '06 - 8:35 
QuestionRe: C++/CLI Image::FromHBitmapmemberCoder2k25 Jun '06 - 10:01 
AnswerRe: C++/CLI Image::FromHBitmapmemberCoder2k25 Jun '06 - 10:15 
Generalproblemmembermr_ander5on6 Jun '05 - 10:58 
Questionhow SetDIBitsToDevice work???memberjags_vc17 Mar '05 - 18:23 
GeneralBlack Screenmembersomeone3214824 Apr '04 - 14:10 
AnswerRe: Black Screen [modified]memberdamn_tiby27 Apr '07 - 6:39 
Generala questionsussyediyildiz1 Aug '02 - 23:02 
GeneralRe: a questioneditorNishant S1 Aug '02 - 23:11 
GeneralRe: a questionsussyediyildiz2 Aug '02 - 1:24 
Generaldohmemberem4 Jul '02 - 15:07 
GeneralGood work but..memberRama Krishna8 May '02 - 4:09 
GeneralRe: Good work but..memberNish [BusterBoy]8 May '02 - 8:56 
GeneralRe: Good work but..memberRama Krishna8 May '02 - 8:57 
GeneralRe: Good work but..memberNish [BusterBoy]8 May '02 - 9:08 
GeneralRe: Good work but..subeditorJames T. Johnson8 May '02 - 9:38 
GeneralRe: Good work but..memberNish [BusterBoy]8 May '02 - 9:42 
GeneralRe: Good work but..subeditorJames T. Johnson8 May '02 - 9:47 
GeneralRe: Good work but..memberNish [BusterBoy]8 May '02 - 9:49 
GeneralRe: Good work but..subeditorJames T. Johnson8 May '02 - 10:05 
GeneralRe: Good work but..memberRama Krishna8 May '02 - 9:43 
GeneralRe: Good work but..memberNish [BusterBoy]8 May '02 - 9:47 
GeneralRe: Good work but..subeditorJames T. Johnson8 May '02 - 9:48 
GeneralRe: Good work but..memberNish [BusterBoy]8 May '02 - 9:53 
GeneralRe: Good work but..subeditorJames T. Johnson8 May '02 - 10:06 
GeneralRe: Good work but..memberNish [BusterBoy]8 May '02 - 10:11 
GeneralRe: Good work but..subeditorJames T. Johnson8 May '02 - 10:18 
GeneralRe: Good work but..memberNish [BusterBoy]8 May '02 - 10:22 
GeneralRe: Good work but..memberRama Krishna8 May '02 - 10:30 
GeneralRe: Good work but..memberNish [BusterBoy]8 May '02 - 10:35 
General*poke*memberJames T. Johnson7 May '02 - 23:26 
GeneralRe: *poke*memberNish [BusterBoy]8 May '02 - 3:43 
QuestionWhat's wrong with "Print Scrn"?memberGeorge7 May '02 - 22:14 
AnswerRe: What's wrong with "Print Scrn"?memberJames T. Johnson7 May '02 - 23:30 
GeneralRe: What's wrong with "Print Scrn"?memberNish [BusterBoy]8 May '02 - 3:48 
GeneralRe: What's wrong with "Print Scrn"?memberGeorge9 May '02 - 1:27 
GeneralRe: What's wrong with "Print Scrn"?memberNish [BusterBoy]9 May '02 - 1:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 4 Jul 2002
Article Copyright 2002 by Nish Sivakumar
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid