This article shows how you can capture screen images including the mouse cursor.
Screen capturing is a very useful way of resource sharing as used in applications like Remote Desktop, Virtual Network Computing (VNC), where a user can access, view, and interact with a remote desktop as his own desktop. Also, it is used in non ethical applications like hacking applications, where a hacker can hack a computer using some malicious server application, and the server then frequently takes screenshots of the prey machine and sends them to the clients. You will see a lot of source code resources over the internet discussing how to take screenshots of the desktop or an area of the desktop but none of them discuss how to capture the mouse cursor bitmap with the screenshot. Sometimes it becomes necessary to capture the mouse to see the whole activity of the hacked machine. First, we will discuss here what the actual problem is.
Most of us think that the mouse cursor image is a part of the desktop display but actually it works on an upper layer over the desktop. Windows always tracks mouse with a “Hot Spot”, the actual position seen by the Windows.
Currently, there are two common ways to capture and manipulate the desktop image:
- Copy the desktop bitmap data from Video Memory to the System Memory. Do processing and then again blit it back to the Video Memory. This can be easily done using the
BitBlt() or the
StretchBlt() APIs provided by Win32.
- Another way is to directly manipulate the desktop bitmap in the Video Memory if enough memory is available as provided by DirectDraw.
Both of these don’t provide us the facility to capture the mouse cursor image with the desktop image.
The solution to the problem of capturing the mouse cursor image with the desktop image is quite simple.
- First, get the bitmap of the screen using
BitBlt(). I have provided a simple function named
CaptureDesktop() in the CaptureScreen.cs file that captures the screen bitmap as almost all the codes available over the internet do.
- Then capture the mouse cursor bitmap as:
Get Cursor Icon:
First, get the cursor information using the Win32
GetCursorInfo(). The function fills the
CURSORINFO structure provided as a parameter. Don't forget to initialize the
cbSize member of the structure before passing it as an argument. Then we check whether the cursor is visible or not, by checking for the equality of the
flags member of the filled structure with the
CURSOR_SHOWING constant. If they are equal then we get the handle to the cursor icon using the
() function that takes the
hCursor member of the above filled structure.
Get Cursor Position:
Now, we have to get the Icon information so that we can get the hotspot position. This information is easily retrieved using the
GetIconInfo() function. Here is the C# implementation of the mouse capturing function:
static Bitmap CaptureCursor(ref int x, ref int y)
Win32Stuff.CURSORINFO ci = new Win32Stuff.CURSORINFO();
ci.cbSize = Marshal.SizeOf(ci);
if (ci.flags == Win32Stuff.CURSOR_SHOWING)
hicon = Win32Stuff.CopyIcon(ci.hCursor);
if(Win32Stuff.GetIconInfo(hicon, out icInfo))
x = ci.ptScreenPos.x - ((int)icInfo.xHotspot);
y = ci.ptScreenPos.y - ((int)icInfo.yHotspot);
Icon ic = Icon.FromHandle(hicon);
bmp = ic.ToBitmap();
- We now have both the bitmaps, i.e., the desktop bitmap and the mouse cursor bitmap with its position on the screen. Now, it's time to place the mouse cursor bitmap on the desktop bitmap. I have provided the following function that places the mouse cursor image over the desktop bitmap at the proper position:
public static Bitmap CaptureDesktopWithCursor()
int cursorX = 0;
int cursorY = 0;
desktopBMP = CaptureDesktop();
cursorBMP = CaptureCursor(ref cursorX, ref cursorY);
if(desktopBMP != null)
if (cursorBMP != null)
r = new Rectangle(cursorX, cursorY,
g = Graphics.FromImage(desktopBMP);
- The bitmap with the cursor is now ready to be rendered over a viewer surface (a
PictureBox used here). Since the viewer's visible area is smaller than the desktop bitmap area, scaling has been used in the function that displays the cooked desktop image.
private void Display(Bitmap desktop)
if(desktop != null)
r = new Rectangle(0,0,ssWithMouseViewer.Width,
g = ssWithMouseViewer.CreateGraphics();
The binary image provided is compiled with Visual Studio .NET 2005 so you have to install .NET Framework 2.0.
I have tested the application on my machine with no known problems, so I expect the same behavior on your machine.