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

OneNote Style Screen Capture Utility - with Preview and Auto Save Options

By , 2 Dec 2011
 
Preview_Media_updated.png

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.

// Definition of Native Method.
[DllImport("user32.dll", SetLastError = true)]
private static extern int RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, Keys vk);

//Param : A handle to the window, an id for the hotkey ,id of modifer key and the key.
RegisterHotKey(this.Handle, hotKeyId,/*MOD_WIN*/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.

// A handle to the calling window and the id used while registering.
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));
        }

        // Excludes the cropped region and paints the remaining surface.
        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!

License

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

About the Author

VallarasuS
Software Developer
India India
Member
I code, learn, listen, and some day in a near future be a proud farmer.

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

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionAutoSaving the File ?memberFerozshaikh1 Dec '11 - 19:15 
Hello VallarasuS,
This application is excellent and almost similar to OneNote.
I wonder if you have included the feature of Auto Save Options with Preview as mentioned in the title.
I did not find any option for autosave, it just puts the screenshot to the clipboard and i have to manually paste it in some other application.
Appreciate your response.
Thank you,
Feroz.
AnswerRe: AutoSaving the File ?memberVallarasuS1 Dec '11 - 19:20 
Thanks Feroz,
 
Yes it does, the source file has all the features as said in the article, demo and setup files does not reflect it as it was added in a later day. You can compile the source to get it work. I will update the setup and demo shortly.
 
Thumbs Up | :thumbsup:
Regards Vallarasu S | BreakingDotNet.blogspot.com

GeneralRe: AutoSaving the File ?memberFerozshaikh1 Dec '11 - 19:26 
Thanks for the prompt reply, Let me know once you update the main setup file... it is really a very Handy tool and your efforts are appreciated !
GeneralRe: AutoSaving the File ?memberVallarasuS1 Dec '11 - 20:17 
Seems it would take two or more days for the reviewers to make the update available publicly.
 
I have placed the setup in my SkyDrive, check out and let me know if you can access them .
 
https://skydrive.live.com/?cid=83f9739f23c283e9&id=83F9739F23C283E9%21137[^]
 
Thumbs Up | :thumbsup:
Regards Vallarasu S | BreakingDotNet.blogspot.com

GeneralRe: AutoSaving the File ?memberFerozshaikh3 Dec '11 - 2:21 
Works Perfectly as designed !! thanks !
AnswerRe: AutoSaving the File ?memberVallarasuS1 Dec '11 - 19:22 
By the way you can access them by right clicking on the tray Icon, images will be stored in MyPictures folder of the user account.
Regards Vallarasu S | BreakingDotNet.blogspot.com

QuestionNice utilitymemberGuyThiebaut3 Jul '11 - 1:06 
Nice utility - similar to one I created back in 2007:
 
TeboScreen: Basic C# Screen Capture Application[^]
 
You may want to allow the user the ability to move and resize the selection area once they have selected it - I need to publish the full updated code however in the meantime you can download the app from here to see what I mean
 
clickety[^]
Continuous effort - not strength or intelligence - is the key to unlocking our potential.(Winston Churchill)

AnswerRe: Nice utilitymembervallarasus3 Jul '11 - 1:17 
Thanks for the suggestions, and the app was just awesome! Thumbs Up | :thumbsup:
 
Vallarasu S.
GeneralRe: Nice utilitymemberGuyThiebaut4 Jul '11 - 1:52 
Hi Vallarasu,
 
I have uploaded the new source code, to codeproject, for TeboScreen which includes the ability to move and resize the selection area.
You may be able to make use of the code - I find your code much more elegant than mine Smile | :) so you may need to make a few changes to get it working with your app.
 
TeboScreen: Basic C# Screen Capture Application[^]
 
Kind regards
 
Guy
Cambridge UK
Continuous effort - not strength or intelligence - is the key to unlocking our potential.(Winston Churchill)

QuestionInteresting...memberdave.dolan2 Jul '11 - 19:05 
Nice tutorial about registering the hotkey... but you know... for screenshots the MS Snipping Tool is built in Smile | :) Still a 5 though, because it's not bad to do something someone else has done before, especially for educational purposes. (It's just bad to do it on someone else's dime!)
AnswerRe: Interesting...membervallarasus2 Jul '11 - 19:27 
OMG | :OMG: You were right! Guess it is not available in XP and earlier version!! Unsure | :~ Thanks though! (ting)!!
GeneralMy vote of 4memberjayantbramhankar2 Jul '11 - 18:40 
Good Article!
Questionproposal [modified]memberMarkDoubson2 Jul '11 - 9:12 
Make sense to cover all screens (like Print Screen keyboard button)
 
in GenerateScreenBitmap()
//Rectangle scrBounds = Screen.PrimaryScreen.Bounds;
Rectangle scrBounds = SystemInformation.VirtualScreen;
 
in AdornerWindow InitializeComponent():
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;//.Font;
//Rectangle scrBounds = Screen.PrimaryScreen.Bounds;
Rectangle scrBounds = SystemInformation.VirtualScreen;...
//this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
//Rectangle scrBounds = Screen.PrimaryScreen.Bounds;
 
Make sense to have option autosave to store all selected clips (e.g. using filename in form "clip" + YYYYMMddHHMMss):
g.DrawImage(bitmapCache,new Rectangle(Point.Empty, result.Size), rect, GraphicsUnit.Pixel);
result.Save(@"c:\\Clips\Clip" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + ".jpg",
System.Drawing.Imaging.ImageFormat.Jpeg);

modified on Sunday, July 3, 2011 12:38 PM

AnswerRe: proposalmembervallarasus2 Jul '11 - 18:37 
Thanks bro! i just have concerned about the primary screen, will add the ability to capture images all over the screen shortly as time permits. I let saving the images to the users choice! Saving every images captured may not be required! Thumbs Up | :thumbsup:
 
Vallarasu S.
AnswerRe: proposalmembervallarasus2 Jul '11 - 21:36 
Hi Mark,
 
suggestion been added to the app, BW: SystemInformation.VirtualScreen has the necessary info. Thumbs Up | :thumbsup:
 
Thanks
Vallarasu S.
SuggestionImagementorDaveAuld2 Jul '11 - 7:11 
The image you are using as the intro has a lot of dead space. It could easily be trimmed down without losing any meaning. The article guidelines recommend a maximum 640x480 for images, and this one exceed that.
 
Cheers,
Dave
Find Me On: Web|Facebook|Twitter|LinkedIn

Folding Stats: Team CodeProject

GeneralRe: Imagemembervallarasus2 Jul '11 - 7:27 
Thanks for alerting.!! Thumbs Up | :thumbsup:
 
-Vallarasu S

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.130523.1 | Last Updated 2 Dec 2011
Article Copyright 2011 by VallarasuS
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid