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);
else
{
HWND hWnd=(HWND)this->Handle.ToInt32();
hDC = GetWindowDC(hWnd);
}
HDC hMemDC = CreateCompatibleDC(hDC);
RECT r;
GetWindowRect((HWND)this->Handle.ToInt32(),&r);
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;
}
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