Click here to Skip to main content
15,868,016 members
Articles / General Programming / Tools

ScreenCap: C# Screen Capture Application (branched from TeboScreen by GuyThiebaut)

Rate me:
Please Sign up or sign in to vote.
4.87/5 (24 votes)
24 Feb 2012CPOL2 min read 80.1K   7.7K   74   21
A C# screen capture application based on TeboScreen by GuyThiebaut

Introduction

This application runs in the background and takes over the Print Screen button allowing for capture of the screen in two different ways:

  • Capture Screen: This does what it says; it basically captures the whole of the screen.
  • Capture Area: Holding down the left mouse button, users draw a rectangle specifying which part of the screen they wish to capture. The user can then select one of three methods to send the area behind the drawn rectangle (clipboard, printer, email). Once drawn, the rectangle can be resized and moved around the screen before sending the image to the desired destination.

Background

My employer recently migrated from a legacy Telnet application, to a Windows application. The legacy app allowed users to hit the Print Screen button and send their session screen to a printer. Many of our users are not experienced Windows users and it was necessary for them to be able to easily capture a screen and send it to a printer without having to hack around the Windows environment.

After doing some searches on the internet for a good screen capture program to accomplish this, most of what we found was weak and costly. I knew this project shouldn't be much trouble for me to write; So, I set out to find some open source to help me accomplish the task quickly and came across the "TeboScreen" Application by GuyThiebaut here on Code Project: TeboScreen

Using the Code

There were a few things I focused on to enhance the original TeboScreen:

  • Run in the background and become activated when the Print Screen button is pressed
  • Support for dual monitors, regardless whether there is a size difference in monitors
  • Automatically send screen capture to three devices: Clipboard, Printer, and EMail
  • Ease of use for the end user

With this in mind, I won't go into redundant details covered in the original project.

Running in Background

All we need to do is add a handler for the Shown event of the main form:

C#
private void ControlPanel_Shown(object sender, EventArgs e)
{
 this.Hide();
}

Handling Print Screen Button

This required writing an assembly, per this discussion KeyHook.

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Reflection;

namespace KeyHook
{
    public class KeyHooker
    {
        public static event EventHandler PrintScreenBtnEvent = null;

        [StructLayout(LayoutKind.Sequential)]
        public struct KBDLLHOOKSTRUCT
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;

            public int extraInfo;
        }

        public delegate int HookProc(int nCode, int wParam, IntPtr ptrKBDLLHOOKSTRUCT);

        [DllImport("user32.dll", CharSet = CharSet.Auto, 
         CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        public static extern IntPtr SetWindowsHookEx
        (int idHook, HookProc callBack, IntPtr hMod, int threadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, 
         CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        public static extern int CallNextHookEx(IntPtr hhk, int nCode, int wParam, IntPtr lParam);

        private static IntPtr kbh_Handle;
        private static HookProc kbh_HookProc;

        private const int VK_SNAPSHOT = 0x2C;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_SYSKEYDOWN = 0x0104;
        private const int WH_KEYBOARD_LL = 13;

        private static int LowLevelKeyboardProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode < 0)
            {
                CallNextHookEx(kbh_Handle, nCode, wParam, lParam);
                return 0;
            }

            if (wParam == WM_KEYDOWN)
            {
                IntPtr kbdll = lParam;
                KBDLLHOOKSTRUCT kbdllstruct = 
                    (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(kbdll, typeof(KBDLLHOOKSTRUCT));

                if (kbdllstruct.vkCode == VK_SNAPSHOT)
                {
                    if (PrintScreenBtnEvent != null)
                        PrintScreenBtnEvent(null, new EventArgs());

                    return -1;
                }
            }

            return CallNextHookEx(kbh_Handle, nCode, wParam, lParam);
        }

        public static void HookKeyboard()
        {
            try
            {
                kbh_HookProc = LowLevelKeyboardProc;

                kbh_Handle = SetWindowsHookEx(WH_KEYBOARD_LL, kbh_HookProc, 
                   Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);

                if (kbh_Handle == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(String.Format("ERROR: {0}", ex.Message));
            }
        }
    }
}

To implement this, I added a delegate to the KeyHooker class:

C#
public static event EventHandler PrintScreenBtnEvent = null;

Dual Monitor Support

To do this, I had to look at the System.Windows.Forms.Screen class. Below is a snippet of code used to store the index of the main monitor. The main monitor is what the TeboScreen application is based on, so any code in this project for the main monitor will be the same. I had to make adjustments to the code if monitor being processed is not the main monitor.

C#
private int GetPrimaryMonIdx()
{
    Screen[] sc;
        sc = Screen.AllScreens;
        int idx = 0;

        foreach (Screen s in sc)
        {
            if (s.Bounds.Left == System.Windows.Forms.Screen.PrimaryScreen.Bounds.Left)
                    break;
                else
                    idx++;
        }

    return (idx <= sc.Length) ? idx : 0;
}

Exiting the Program

When the main screen (from the screen shot above) is showing and has focus, hit Ctrl-Alt-S and then X.

License

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


Written By
Software Developer (Senior)
United States United States
I've been a software developer for over 25 years. Worked on commercial grade Point of Sale and Order Entry software applications.

Worked with Symbol Technology Handheld bar code scanners quite a bit. Written Sqllite libraries that run on these devices.

Develop client/server solutions in ASP.NET. MVC, and MVVM design patterns.

Comments and Discussions

 
QuestionJust what I was looking for Pin
MarkNZed24-Sep-14 3:11
MarkNZed24-Sep-14 3:11 
AnswerRe: Just what I was looking for Pin
MarkNZed24-Sep-14 4:56
MarkNZed24-Sep-14 4:56 
QuestionVery useful, thank you. Pin
Edward Piccoli20-Mar-14 1:57
Edward Piccoli20-Mar-14 1:57 
Very useful, thank you. Is there by any chance a VB.Net version available? I actually do many projects using MS VS 2013 LightSwitch in VB.Net. Thank you again for all your time and effort.

Ed
AnswerRe: Very useful, thank you. Pin
Patrick Harris20-Mar-14 23:54
Patrick Harris20-Mar-14 23:54 
SuggestionScreen Shots Pin
Joezer BH21-Jul-13 4:20
professionalJoezer BH21-Jul-13 4:20 
GeneralMy vote of 5 Pin
Kanasz Robert27-Sep-12 10:48
professionalKanasz Robert27-Sep-12 10:48 
GeneralRe: My vote of 5 Pin
Patrick Harris30-Sep-12 14:35
Patrick Harris30-Sep-12 14:35 
QuestionResolution and exact position Pin
bavarian_guy16-Aug-12 21:16
bavarian_guy16-Aug-12 21:16 
AnswerRe: Resolution and exact position Pin
Patrick Harris17-Aug-12 7:12
Patrick Harris17-Aug-12 7:12 
GeneralMy vote of 5 Pin
@k@ ?28-Feb-12 4:53
professional@k@ ?28-Feb-12 4:53 
GeneralRe: My vote of 5 Pin
Patrick Harris29-Feb-12 2:36
Patrick Harris29-Feb-12 2:36 
NewsAnother Update Pin
Patrick Harris24-Feb-12 12:45
Patrick Harris24-Feb-12 12:45 
QuestionNice tool Pin
Ganesan Senthilvel19-Feb-12 14:56
Ganesan Senthilvel19-Feb-12 14:56 
GeneralRe: Nice tool Pin
Patrick Harris19-Feb-12 15:22
Patrick Harris19-Feb-12 15:22 
NewsNew Feature Pin
Patrick Harris19-Feb-12 9:25
Patrick Harris19-Feb-12 9:25 
NewsLatest Bug Fix Pin
Patrick Harris19-Feb-12 5:22
Patrick Harris19-Feb-12 5:22 
NewsBugs Fixed Today Pin
Patrick Harris17-Feb-12 13:02
Patrick Harris17-Feb-12 13:02 
BugGreat tool Pin
lordofm16-Feb-12 23:19
lordofm16-Feb-12 23:19 
AnswerRe: Great tool Pin
Patrick Harris17-Feb-12 3:05
Patrick Harris17-Feb-12 3:05 
GeneralMy vote of 5 Pin
GuyThiebaut16-Feb-12 7:44
professionalGuyThiebaut16-Feb-12 7:44 
GeneralRe: My vote of 5 Pin
Patrick Harris16-Feb-12 11:07
Patrick Harris16-Feb-12 11:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.