Printscreen / alt+Printscreen including Cursor , in C++

dynamic_sysop

Well-known member
Joined
Oct 1, 2002
Messages
1,039
Location
Ashby, Leicestershire.
An example of taking a screenshot of either the entire desktop , or a window by its handle. included in the screenshot is the Cursor at its position at the time of the shot ( unlike windows , which doesnt show the Cursor )
This for me has proved to be the most challenging of projects, ive built it all in C++ ( .NET win forms , but using standard C++ api calls etc... )
C#:
#pragma once 
#include <windows.h> 
#include "Winuser.h" 

// then to use the sample ( ive used a button and 2 radio buttons in this case ) ...
private: void button1_Click(System::Object *  sender, System::EventArgs *  e) 
{ 
IntPtr handle = IntPtr::Zero; 
int width = NULL; 
int height = NULL; 
int x = NULL; 
int y = NULL; 

if(radioButton1->Checked == true) 
    { 
    // 
    // specify the handle of the Form 
    // and the forms sizes / positions
    handle = this->get_Handle(); 
    width = this->get_Width(); 
    height = this]->get_Height(); 
    x = this->get_Location().get_X(); 
    y = this->get_Location().get_Y(); 
    } 
    else 
    { 
    // 
    // specify the handle of the Desktop 
    // and the Desktops sizes / positions. 
    handle =  GetDesktopWindow(); 
    Screen *r = Screen::PrimaryScreen; 
    width = r->Bounds.get_Width(); 
    height = r->Bounds.get_Height(); 
    x = 0; 
    y = 0; 
    } 
    // 
    // now lets try to make a Screenshot which includes the Cursor ( unlike the Screenshot that Windows takes ) 
    Snapshot(handle , width , height , x , y); 
} 

private: void Snapshot(IntPtr hHandle , int width , int height , int x , int y) 
{ 
/// 
//The GetWindowDC function retrieves the device context (DC) for the entire window, including title bar, menus, and scroll bars. 
///See Msdn Article for more info ... [url]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_0hcz.asp[/url] 
HDC srcHDC = GetWindowDC((HWND)hHandle.ToInt32()); 
/// 
//The CreateCompatibleDC function creates a memory device context (DC) compatible with the specified device. 
///See Msdn Article for more info ... [url]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/devcons_499f.asp[/url] 
HDC destHDC = CreateCompatibleDC(srcHDC); 
/// 
//The CreateCompatibleBitmap function creates a bitmap compatible with the device that is associated with the specified device context. 
///See Msdn Article for more info ... [url]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_1cxc.asp[/url] 
HBITMAP bmpDC = CreateCompatibleBitmap(srcHDC , width , height); 
/// 
//The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type. 
///See Msdn Article for more info ... [url]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/devcons_9v3o.asp[/url] 
HGDIOBJ objHDC = SelectObject(destHDC, bmpDC); 
/// 
//The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context. 
///See Msdn Article for more info ... [url]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_0fzo.asp[/url] 
BitBlt(destHDC, 0, 0, width, height, srcHDC, 0, 0, SRCCOPY); 
SelectObject(destHDC, objHDC); 
/// 
// here i cast a Bitmap ( .NET / C# type Bitmap ) from the C++ style HBITMAP 
/// for this i use " dynamic_cast " , which is seen in .NET as DirectCast.  
Bitmap *bmp = dynamic_cast<Bitmap*>(Bitmap::FromHbitmap(bmpDC)); 
/// 
//now i create a Graphics object , to enable the Cursor to be Drawn in its Correct Position. 
Graphics *g = dynamic_cast<Graphics*>(Graphics::FromImage(bmp)); 
System::Windows::Forms::Cursor *csr=Cursor::get_Current(); 
System::Drawing::Point pnt = (System::Drawing::Point)csr->get_Position(); 
/// 
// this was quite tricky as creating a new Rectangle threw alsorts of problems, until i found the FromLTRB property. 
System::Drawing::Rectangle r= System::Drawing::Rectangle::FromLTRB((int)(pnt.get_X() - 10) - x,(int)(pnt.get_Y() - 10) - y,(int)csr->get_Size().get_Width() ,(int)csr->get_Size().get_Width()); 
/// 
// now i draw the Cursor on to the Graphics object of the bitmap. 
csr->Draw( g , r); 
/// 
//next i clean up any Resources used by the above calls. 
ReleaseDC((HWND)hHandle.ToInt32(), srcHDC); 
DeleteDC(destHDC); 
DeleteObject(bmpDC); 
/// 
// finally i save the Bitmap ( this was the Reason for using a .NET Bitmap , makes saving alot simpler ) . 
bmp->Save("C:\\test123.bmp" , System::Drawing::Imaging::ImageFormat::Bmp ); 
MessageBox(NULL , "ScreenShot Complete","Dynamics C++ ScreenShot App",MB_ICONINFORMATION); 
}
ive included a sample project ( its VS2003 , so VS2002 users would need to convert the project or copy the code in to their version )
 

Attachments

Last edited by a moderator:
Back
Top