Reputation: 101
First up, sorry for the long question but I want to make sure I include everything that I have come across and done so far.
I want to make a C# Windows Application for the tutorials team that will serve as an alternative for the boring manual task they perform of pressing Alt+PrtSc for each window that appears while performing the steps of a tutorial and paste it in ms paint to save the image to a folder so that it can be later inserted in the tutorial document.
There are different ways to capture the snapshot of the desktop or only a part of it. I could even manage to take snapshots of the controls in my WinForms app however; capturing the screenshot of any window (along with the mouse pointer) as soon as you click and saving it turned out to be a little tricky.
I came across this post that has details of capturing and saving the screenshot using Win32 API. This and this post talk about using saving a part of the desktop by using only .NET Framework and it works well but it's not exactly what I need. I did come across some freeware and other commercial software that do a lot more and a little bit of this too but I'd prefer to make something simple and customized.
Right now, my form has a browse button to select a folder (to save images to) and another button named START. Its name changes to STOP when clicked and remains depressed (until clicked again to stop).
Say, the team has to put together a setup and install tutorial of a software and the welcome screen of the wizard is up. With the app started, an image of each window of the install wizard should be saved (along with the mouse pointer) as you keep clicking buttons like Continue, I Accept, Next ... Next and Finish.
I hope I could explain clearly. Any help will be appreciated. Thanks in advance.
Upvotes: 2
Views: 5702
Reputation: 109
Try typing this to save a screenshot:
int screenWidth = Screen.PrimaryScreen.Bounds.Width;
int screenHeight = Screen.PrimaryScreen.Bounds.Height;
Graphics Graphics1;
Bitmap Bitmap1 = new Bitmap(screenWidth, screenHeight);
Graphics1 = Graphics.FromImage(Bitmap1);
Graphics1.CopyFromScreen(Point.Empty, Point.Empty, Screen.PrimaryScreen.Bounds.Size);
Bitmap1.Save(@"c:\ScreenShot1.bmp); //Place that you want to save screenshot
Upvotes: 2
Reputation: 1089
I solved a similar problem using an autohotkey script to trigger GadWin (http://www.gadwin.com/printscreen/) Note Gadwin is free for personal use only. A commercial license may be purchased ($25)
I also have some C# code you might like, that is free.
The AutoHotKey script: #SingleInstance Force ; click screen - every click is a new screen shot ; records a screen shot for each click of the mouse ; For use with Gadwin or other screen capture that is triggered by a keystroke, e.g. {PRINTSCREEN} ; ~ means pass through the click ; key toggle capture on and off
; open destination folder
destinationFolder:=GadWinDestinationFolder()
ifExist %destinationFolder%
{
Run explorer.exe %destinationFolder%
sleep 1000
}
;; shows an opening message
; TBD could be on a message box to let user choose/acknowledge
ShowStatus("Capture is Enabled.`n<Pause/Break> to toggle on/off", 10000)
; *** ,% <space> func() is autohotkey magic for interpolate a function here ***
RunWait,% GadWinExe()
sleep 5000
capturing:=true
Return
; ~ means pass the click & position through to the system
; This allows drag screens to work, while Send LButton does not
; TBS look at MouseGetPos + MouseClickDrag
~LButton::
Capture()
;Send {LButton}
return
~RButton::
Capture()
;Send {RButton}
Return
Capture()
{
global capturing
if (capturing)
{
;ClipSaved:=ClipboardAll ; Save the entire clipboard to a variable
; this may be whacking the clipboard
; alt -prt scrn
Send {PRINTSCREEN}
ShowStatus("Captured to " GadWinDestinationFolder() "`nPress <Pause/Break> to toggle.", 3000)
;Clipboard:=ClipSaved ; Restore the original clipboard. Note the use of Clipboard (not ClipboardAll).
;ClipSaved:= ; Free the memory in case the clipboard was very large.
}
Else
{
dp("Capture is off`nPress <Pause/Break> to toggle.")
}
Return
}
PAUSE:: CaptureToggle(2000)
CaptureToggle(delay)
{
global capturing
Suspend OFF
capturing:=!capturing
If (capturing)
{
ShowStatus("Capture Enabled.", delay)
}
Else
{
ShowStatus("Capture Disabled.", delay)
;Suspend
}
Return
}
GadWinExe()
{
RegRead, exeFolder, HKLM, SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Gadwin PrintScreen, InstallLocation
Return exeFolder "\PrintScreen.exe"
}
GadWinDestinationFolder()
{
; Gadwin specific
RegRead, CaptureDir, HKEY_CURRENT_USER, Software\Gadwin Systems\PrintScreen\Destination, CaptureDir
Return CaptureDir
}
ShowStatus(msg, time)
{
ShowTrayTip("ClickScreen", msg, time)
}
; Generic Show and Remove Tray Tip
ShowTrayTip(title, msg, time)
{
; 7/7/2011 Win Server 2008 - 30 seems to have no effect
TrayTip, %title%, %msg%, 30, 1
SetTimer, RemoveTrayTip, %time% ; used to ensure tip is taken down
dp(msg)
Return
; The Traytip does not disappear quickly without this
; 7/7/2011 Win Server 2008 - tip disappears after 4 seconds anyway if the script continues to run
RemoveTrayTip:
SetTimer, RemoveTrayTip, Off
TrayTip
dp("TrayTip off")
Return
}
FindAndRun(exeName)
{
; Here I get to define the folders to search
ProgramFolders:="P:\Program Files,C:\Program Files,C:\Program Files (x86)"
Loop, parse, ProgramFolders, `,
{
IfExist, %A_LoopField%\%exeName%
{
Run %A_LoopField%\%exeName%
Return
}
}
MsgBox File %exeName% not found
}
dp(Msg)
{
OutputDebug %A_ScriptName% %Msg%
}
The C#
using System;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
//Based on code of Agha Ali Raza (http://www.csharphelp.com/archives2/archive393.html)
namespace Script
{
public class CaptureScreen
{
const string usage = "Usage: printScreen.cs [filename]\n"+
"Captures screen image and saves it to a file (default file: screen.gif)\n";
static public void Main(string[] args)
{
if (args.Length == 1 && (args[0] == "?" || args[0] == "/?" || args[0] == "-?" || args[0].ToLower() == "help"))
{
Console.WriteLine(usage);
}
else
{
try
{
Bitmap capture = CaptureScreen.GetDesktopImage();
string file = Path.Combine(Environment.CurrentDirectory, "screen.gif");
ImageFormat format = ImageFormat.Gif;
if (args.Length == 1)
{
file = args[0];
if (args[0].ToUpper().EndsWith(".GIF"))
format = ImageFormat.Gif;
else if (args[0].ToUpper().EndsWith(".BMP"))
format = ImageFormat.Bmp;
else if (args[0].ToUpper().EndsWith(".JPEG"))
format = ImageFormat.Jpeg;
else if (args[0].ToUpper().EndsWith(".PNG"))
format = ImageFormat.Png;
}
capture.Save(file, format);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
public static Bitmap GetDesktopImage()
{
WIN32_API.SIZE size;
IntPtr hDC = WIN32_API.GetDC(WIN32_API.GetDesktopWindow());
IntPtr hMemDC = WIN32_API.CreateCompatibleDC(hDC);
size.cx = WIN32_API.GetSystemMetrics(WIN32_API.SM_CXSCREEN);
size.cy = WIN32_API.GetSystemMetrics(WIN32_API.SM_CYSCREEN);
m_HBitmap = WIN32_API.CreateCompatibleBitmap(hDC, size.cx, size.cy);
if (m_HBitmap!=IntPtr.Zero)
{
IntPtr hOld = (IntPtr) WIN32_API.SelectObject(hMemDC, m_HBitmap);
WIN32_API.BitBlt(hMemDC, 0, 0,size.cx,size.cy, hDC, 0, 0, WIN32_API.SRCCOPY);
WIN32_API.SelectObject(hMemDC, hOld);
WIN32_API.DeleteDC(hMemDC);
WIN32_API.ReleaseDC(WIN32_API.GetDesktopWindow(), hDC);
return System.Drawing.Image.FromHbitmap(m_HBitmap);
}
return null;
}
protected static IntPtr m_HBitmap;
}
public class WIN32_API
{
public struct SIZE
{
public int cx;
public int cy;
}
public const int SRCCOPY = 13369376;
public const int SM_CXSCREEN=0;
public const int SM_CYSCREEN=1;
[DllImport("gdi32.dll",EntryPoint="DeleteDC")]
public static extern IntPtr DeleteDC(IntPtr hDc);
[DllImport("gdi32.dll",EntryPoint="DeleteObject")]
public static extern IntPtr DeleteObject(IntPtr hDc);
[DllImport("gdi32.dll",EntryPoint="BitBlt")]
public static extern bool BitBlt(IntPtr hdcDest,int xDest,int yDest,int wDest,int hDest,IntPtr hdcSource,int xSrc,int ySrc,int RasterOp);
[DllImport ("gdi32.dll",EntryPoint="CreateCompatibleBitmap")]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
[DllImport ("gdi32.dll",EntryPoint="CreateCompatibleDC")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport ("gdi32.dll",EntryPoint="SelectObject")]
public static extern IntPtr SelectObject(IntPtr hdc,IntPtr bmp);
[DllImport("user32.dll", EntryPoint="GetDesktopWindow")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll",EntryPoint="GetDC")]
public static extern IntPtr GetDC(IntPtr ptr);
[DllImport("user32.dll",EntryPoint="GetSystemMetrics")]
public static extern int GetSystemMetrics(int abc);
[DllImport("user32.dll",EntryPoint="GetWindowDC")]
public static extern IntPtr GetWindowDC(Int32 ptr);
[DllImport("user32.dll",EntryPoint="ReleaseDC")]
public static extern IntPtr ReleaseDC(IntPtr hWnd,IntPtr hDc);
}
}
Hopefully that will get you started
Upvotes: 0