Screenshot in 2 Clicks using .NET

Posted by: Shoban Kumar , on 4/17/2009, in Category WinForms & WinRT
Views: 131820
Abstract: As a developer, I take lot of screenshots and its time consuming to press the screenshot button, paste it in MSPaint or any other Image editing software and then save it. The pain is even more when we need to use two Buttons (Fn + PrintScreen) in most Laptops ;-). So I thought I will develop my own screenshot capturing tool which will allow me to take screenshots as well as save it in just two clicks. In this article I am going to show you how easy it is to develop your own tool using .NET.
Screenshot in 2 Clicks using .NET
 
As a developer, I take lot of screenshots and its time consuming to press the screenshot button, paste it in MSPaint or any other Image editing software and then save it. The pain is even more when I need to use two Buttons for a screenshot (Fn + PrintScreen) in my Laptop ;-). So I thought I will develop my own screenshot capturing tool which will allow me to take screenshots as well as save it in just two clicks. In this article I am going to show you how easy it is to develop your own tool using .NET. Let’s get started.
Step 1: Fire up Visual Studio 2008 and Create a new Windows Application.
Step 2: From the toolbox, add a ‘ContextMenuStrip’ and a ‘NotifyIcon’ to the form.
Step 3: Choose an icon for the’ NotifyIcon’ using the Icon property. Change the ‘ContextMenuStrip’ property of the NotifyIcon to ‘contextMenuStrip1’ (which we added in Step 2)
Step 4: Add a new menu item to ContextMenuStrip1 control named “Grab Screenshot” as shown in the screen below:
ContextMenu
Now double click this MenuItem and add the following code to its click event:
C#
private void grabScreenShotToolStripMenuItem_Click(object sender, EventArgs e)
{
    Bitmap bmpSS = null;
    Graphics gfxSS = null;
 
    try
    {
        bmpSS = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
               Screen.PrimaryScreen.Bounds.Height,
               PixelFormat.Format32bppArgb);
 
        gfxSS = Graphics.FromImage(bmpSS);
 
        gfxSS.CopyFromScreen(
            Screen.PrimaryScreen.Bounds.X,
            Screen.PrimaryScreen.Bounds.Y,
            0,
            0,
            Screen.PrimaryScreen.Bounds.Size,
            CopyPixelOperation.SourceCopy);
 
        SaveFileDialog saveDialog = new SaveFileDialog();
        saveDialog.Filter = "JPeg Image|*.jpg";
        saveDialog.Title = "Save Image as";
        saveDialog.ShowDialog();
        if (saveDialog.FileName != string.Empty)
            bmpSS.Save(saveDialog.FileName, ImageFormat.Jpeg);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
 
}
VB.NET
Private Sub GrabScreenshotToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GrabScreenshotToolStripMenuItem.Click
        Dim bmpSS As Bitmap
        Dim gfxSS As Graphics
 
        bmpSS = New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb)
        gfxSS = Graphics.FromImage(bmpSS)
        gfxSS.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy)
 
        Dim saveDialog As New SaveFileDialog
        saveDialog.Filter = "JPeg Image|*.jpg"
        saveDialog.Title = "Save Image as"
        saveDialog.ShowDialog()
        If saveDialog.FileName <> "" Then
            bmpSS.Save(saveDialog.FileName, ImageFormat.Jpeg)
        End If
 
    End Sub
Note: Make sure you import System.Drawing and System.Drawing.Imaging namespaces.
In the code above, we create a new Bitmap which is equal to the width and height of the primary screen and then we create a new graphics using the Bitmap. We then use the CopyFromScreen() to capture the screen. Once this step is done, we create an object of SaveFileDialog and display it to the user to choose the location and save the file as an .jpeg image.
Step 5: Add the following code to the Form load event which will hide the form and remove it from taskbar.
C#
private void Form1_Load(object sender, EventArgs e)
{
    this.ShowInTaskbar = false;
    this.WindowState = FormWindowState.Minimized;
    this.Hide();
}
VB.NET
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.ShowInTaskbar = False
        Me.WindowState = FormWindowState.Minimized
        Me.Hide()
    End Sub
Now run the program and right click the Icon that appears in your status bar. Click on the ‘Grab ScreenShot’ and save the screenshot to the desired location.
Status Screenshot
The next time you want a screenshot, remember it’s just two clicks away!
The entire source code of this article can be downloaded from here.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
ShobanKumar is an ex-Microsoft MVP in SharePoint who currently works as a SharePoint Consultant. You can read more about his projects at http://shobankumar.com. You can also follow him on twitter @shobankr


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by billy on Friday, April 17, 2009 6:04 AM
it sux to have a password on a code example download.

really sux... no one else does it.
Comment posted by johny on Friday, April 17, 2009 6:06 AM
So I thought I will develop my own screenshot capturing tool which will allow me to take screenshots in a single click.

and then:

The next time you want a screenshot, remember it’s just two clicks away!

one or two clicks?
Comment posted by Shoban Kumar on Friday, April 17, 2009 10:08 AM
Hi Johny,
Sorry about that :) I meant 2 clicks. One right and one left.
Comment posted by Carol Nadarwalla on Friday, April 17, 2009 10:49 AM
Billy: I am Carol, the Site Editor. Thanks for your comment.

We have introduced the password on the download recently. Reason? Users not only copy articles but also the download link. The end result is plagiarism as well as unnecessary bandwidth issues. We could have stopped that through the webserver but that option is not given to us.

Most websites before downloading ask you register on the site before downloading. You also have to be LoggedIn before downloading. However we do not have any such requirements. All you have to do is subscribe to the site once or be a registered member to get the password to all downloads. If the password is changed, users are informed via email.

I understand your concerns but it is just a one time registration or subscription and its worth it!

Thanks.
Comment posted by Carol Nadarwalla on Friday, April 17, 2009 10:57 AM
Johny: Thanks so much for pointing out that. The text has been rectified.
Comment posted by Jason Pickard on Friday, April 17, 2009 11:26 AM
Have you tried using a HTTP Handler to do the protection? I do agree to Carol Nadarwalla's comment that other sites like CodeProject require you to be a registered member and yes, signed in to download!

Coming back, fantastic stuff Shiban Kumar and I am sure it will save me a lot of frustration.
Comment posted by Jason Pickard on Friday, April 17, 2009 11:30 AM
Have you tried using a HTTP Handler to do the protection? I do agree to Carol Nadarwalla's comment that other sites like CodeProject require you to be a registered member and yes, signed in to download!

Coming back, fantastic stuff Shiban Kumar and I am sure it will save me a lot of frustration.
Comment posted by Shoban Kumar on Friday, April 17, 2009 11:54 AM
Thanks Jason
Comment posted by Yogesh on Saturday, April 18, 2009 9:51 AM
Thanks,

This is useful tip...
Definately i will do implement in my next project.
Comment posted by vaibhav on Saturday, April 18, 2009 1:45 PM
please send the gridview example in vb.net 2005.
Comment posted by Jerome St-Pierre on Saturday, April 18, 2009 3:28 PM
In Ubuntu we get a prompt when we hit the print screen key and we get the option to change the file path before to save the image. So it takes a key hit and a button click.

Nice educational example thought, I didn't even know about the Screen class in .NET.

The only thing that bothered me (yes I know it has nothing to do with the purpose of the post) is the Hungarian notation (bmpSS, gfxSS) using the type as the prefix with acronyms which is not standard nomenclature in .NET. You may find it easier to read for yourself because you are used to it. But anyone who doesn't won't.

Yes I know it doesn't make a difference in a tiny snippet like that. But it irritates me when I come across variable names like that at work. I automatically hit R twice to rename them with Resharper while I read the code to help me to understand what it does. When I see it in books or blogs it irritates me even more as I think we should use standard nomenclature to show the right way to rookies.

Thanks for the post.
Comment posted by Shoban Kumar on Saturday, April 18, 2009 4:40 PM
@Vaibhav
What gridview exmaple you are looking for?

@Jermome
I can understand you. I should blame my teachers in college ;-) I will change it in my next article.
Thanks
Shoban
http://www.codegeeks.net
Comment posted by Jimbo on Sunday, April 19, 2009 10:01 PM
Need to call Dispose() and/or using{} (C#) statements with Bitmap and Graphics.  If you are using something that is IDisposable, you should call Dispose() when you are finished with it (if buggy/sloppy code is your goal, then never call dispose and you'll be about 75% there).  Run a memory profiler on your code, and after a few screen captures...you'll see what I mean.

Something such as:

using (Graphics memoryGraphics =
                            Graphics.FromImage(memoryImage))
                    {
                        memoryGraphics.CopyFromScreen(rc.X, rc.Y,
                           0, 0, rc.Size, CopyPixelOperation.SourceCopy);
                    }


Comment posted by Grant on Tuesday, April 21, 2009 2:32 AM
Have you tried Cropper (http://www.codeplex.com/cropper)? Same idea but with more features - sits in your tray and intercepts Print Screen button clicks to enable saving captures straight to disk (or to clipboard) in a choice of formats. Also enables capturing just the active window using Alt + Print Screen. A real time saver and it also supports plugins...
Comment posted by Suprotim Agarwal on Tuesday, April 21, 2009 8:48 AM
Shoban: A good article! Keep it up.

Jimbo: That's a great tip and I fully acknowledge what you say.

Grant: Thanks for letting the viewers know about Cropper.
Comment posted by Charlie on Tuesday, April 21, 2009 9:18 AM
Sure enough Jimbo is right. Not ever using Dispose(), I looked up info on it and now I am totally confused. Other than that I really liked the app. Would like to see some enhancements: capture a section of screen by drawing box around it, capture directly to printer, close option on icon.
Comment posted by Shoban Kumar on Wednesday, April 22, 2009 1:02 AM
Grant : I have heard about cropper but I have not used it. Here is a skype plugin for cropper (http://kidoos.net/media/p/386.aspx) developed by my friend. if you are interested ;-)

Charlie : My next article is a continuation of this one which with few exnhancements. It will show how you can use the form's size to capture part of the screen. Thanks for your tips abour close and printer.
Comment posted by asdf on Wednesday, May 27, 2009 1:48 PM
Crappy resolution, any fix for it?
PrintScreen, WinKey + R, mspaint, Ctrl+V, Ctrl+S, File, Enter, Alt+F4
Is worth the 6 extra commads to get the original resolution.
Comment posted by xoorn on Friday, July 3, 2009 1:20 PM
Isn`t this total Overkill?? You could just use a script. that would need far less code...
Comment posted by Dave Black on Tuesday, May 25, 2010 5:19 PM
Here is a version of this code *without* any memory leaks!  ...and YES .NET can "leak" memory...

    try
    {
        using ( Bitmap bmpSS = new Bitmap( Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb ) )
        {
            using ( Graphics gfxSS = Graphics.FromImage( bmpSS ) )
            {
                gfxSS.CopyFromScreen( Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy );
                using ( SaveFileDialog saveDialog = new SaveFileDialog() )
                {
                    saveDialog.Filter = "JPeg Image|*.jpg";
                    saveDialog.Title = "Save Image as";
                    saveDialog.ShowDialog();
                    if ( !String.IsNullOrEmpty( saveDialog.FileName ) )
                    {
                        bmpSS.Save( saveDialog.FileName, ImageFormat.Jpeg );
                    }
                }
            }
        }
    }
    catch ( Exception ex )
    {
        MessageBox.Show( ex.Message );
    }
Comment posted by benkaci on Wednesday, September 29, 2010 7:08 AM
vip quiz agent xfile would like installizing test your screen shot alerte
Comment posted by mike wheaton on Wednesday, June 6, 2012 8:44 AM
sweet.
Comment posted by Arvin on Sunday, June 24, 2012 9:01 PM
thanx for sharing. i've been searching for a screen capture source using only managed code.