Introduction
Most of you who work with 'OneNote' might have experienced the screen capturing future added to the Office 2010 package. Unlike the conventional print screen feature, this facility provides an option to freeze the screen and crop the image on the active desktop.
I found this really helpful when creating Office 2010 like Ribbon for our application to get the minute details of the Office 2010 visuals. Here is a utility that gives you the same experience to capture the screen and crop.
Background
Here is how it works:
- The main app runs in the background and listens to the HOT KEY (Win Key + S) to capture the screen.
- As soon as the Main app receives the WM_HOTKEY message, the main app captures the desktop and passes it onto an adorner window.
- The adorner window presents the opaque image on top of all the other windows for you to crop with the mouse.
- The cropped image is then made to the clipboard and that's it!
Using the Code
Listening to the HOTKEY
HOTKEY is the option the users can bring this application alive. To make this work, this application user native pinvokes to register and unregister HOTKEY.
RegisterHotKey
This function requires a handle to the calling window to which the WM_HOTKEY message will be posted when the key combination is pressed, and an ID as a reference to the HOTKEY, (there exists a range for this value, take a look at the Remarks section of the documentation) and a modifier value specifying the modifier key with which the key parameter is to be registered.
Win key along with 'S' is used as a HOTKEY for this application and the code for function is as in the following code block.
[DllImport("user32.dll", SetLastError = true)]
private static extern int RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, Keys vk);
RegisterHotKey(this.Handle, hotKeyId,0x0008, Keys.S);
UnregisterHotKey
Un-registering a HOTKEY is relatively simple, it requires a handle to the calling window and the id used while registering the HOTKEY.
UnregisterHotKey(this.Handle, hotKeyId);
The next big thing is to get the bitmap of the desktop window, there exists a native function GetDesktopWindow to get the desktop handle with which you can copy the graphics context to a bitmap. Alternatively, this can be done with the Graphics.CopyFromScreen method as follows later this bitmap is projected as a opaque image, providing a frozen desktop appearance.
public static Bitmap GenerateScreenBitmap()
{
Rectangle scrBounds = Screen.PrimaryScreen.Bounds;
Bitmap bmp = new Bitmap(scrBounds.Width, scrBounds.Height);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen(Point.Empty, Point.Empty,
scrBounds.Size, CopyPixelOperation.SourceCopy);
bitmapCache = bmp;
return bmp;
}
The resultant bitmap image is set as the background of an adorner window and the window is shown, this adorner window overrides its OnPaint
method to fill the region with a alpha blend to give an opaque look. he adorner processes the mouse events to determine the cropped region. dragStart
dragStop
determines the upper left and bottom right points of the cropped image.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Region clip = e.Graphics.Clip;
if (mousePressed && dragStart!= Point.Empty && dragStart != dragStop)
{
Rectangle rect = Rectangle.FromLTRB
(dragStart.X, dragStart.Y, dragStop.X, dragStop.Y);
using (Pen pen = new Pen(Color.Black))
{
e.Graphics.DrawRectangle(pen, Rectangle.Inflate(rect,-1,-1));
}
e.Graphics.SetClip(rect, CombineMode.Exclude);
}
using (Brush brush = new SolidBrush(Color.FromArgb(210,Color.WhiteSmoke)))
{
e.Graphics.FillRectangle(brush, this.ClientRectangle);
}
e.Graphics.SetClip(clip, CombineMode.Replace);
}
The adorner will be closed when a mouse button is pressed or when a key is pressed, and the dragStart
and dragStop
points are passed to the main window, which copies the target cropped image to the clipboard.
Rectangle rect = Rectangle.FromLTRB(adornerWindow.DragStart.X,
adornerWindow.DragStart.Y, adornerWindow.DragStop.X, adornerWindow.DragStop.Y);
Bitmap result = new Bitmap(rect.Width, rect.Height);
Graphics g = Graphics.FromImage(result);
g.DrawImage(bitmapCache,new Rectangle(Point.Empty,result.Size), rect, GraphicsUnit.Pixel);
Clipboard.SetImage(result);
And that's it, the image is now copied to the clipboard, you can paste it wherever required.
Points of Interest
This utility provides an option to start this application when windows starts and here is how you can make it, it just requires to place the application start up path and application name in a registry key at the following location:
string RegKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
RegistryKey startUpKey = Registry.CurrentUser.OpenSubKey(RegKey, true);
ToolStripMenuItem menuItem = (sender as ToolStripMenuItem);
menuItem.Checked = !menuItem.Checked;
if (menuItem.Checked)
startUpKey.SetValue(APP_NAME, Application.ExecutablePath);
else
startUpKey.DeleteValue(APP_NAME, false);
Hope this helps in your day to day work. Leave your valuable comments and suggestions. Happy coding!