/*
* $RCSfile: ScreenCapture.cs,v $
* Copyright (C) 2006 Rob Loach (http://robloach.net)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ScreenCap
{
class ScreenCapture
{
public enum CaptureArea
{
Fullscreen, Window, ClientArea
}
public static void Capture(CaptureArea area)
{
try
{
if (Config.SnapshotSound)
SoundManager.PlayWav("click.wav");
}
catch
{
Config.SnapshotSound = false;
}
Image image;
switch(area)
{
case CaptureArea.ClientArea:
IntPtr clientHandle = User32.GetForegroundWindow();
image = Capture(clientHandle, User32.GetDC(clientHandle), area);
break;
case CaptureArea.Fullscreen:
IntPtr fullscreenHandle = User32.GetDesktopWindow();
image = Capture(fullscreenHandle, User32.GetWindowDC(fullscreenHandle), area);
break;
case CaptureArea.Window:
IntPtr windowHandle = User32.GetForegroundWindow();
image = Capture(windowHandle, User32.GetWindowDC(windowHandle), area);
break;
default:
image = null;
break;
}
int index = CaptureIndex++;
DateTime now = DateTime.Now;
ImageFormat format = GetFormat(Config.FileFormat);
string filename = FormatFilename(Config.FilenameFormat, Config.FileFormat, now, index);
image.Save(Config.SaveDirectory + "\\" + filename, format);
if (Config.GenerateThumbnails)
{
Image thumb = GenerateThumbnail(image);
thumb.Save(Config.SaveDirectory + "\\" + FormatFilename(Config.ThumbnailFileFormat, Config.ThumbnailImageFormat, now, index), GetFormat(Config.ThumbnailImageFormat));
}
DataObject dobj = new DataObject();
dobj.SetData(DataFormats.Bitmap, true, image);
Clipboard.SetDataObject(dobj, true);
image.Dispose();
if (Config.NotifySnapshot)
ScreenCap.NotifyIcon.ShowBalloonTip(1200, "ScreenCap", "Screenshot taken (" + area.ToString() + ") and saved as:\n\n" + filename, ToolTipIcon.Info);
}
private static ImageFormat GetFormat(Config.ImageFormat format)
{
switch (format)
{
case Config.ImageFormat.BMP: return ImageFormat.Bmp;
case Config.ImageFormat.GIF: return ImageFormat.Gif;
case Config.ImageFormat.JPEG: return ImageFormat.Jpeg;
case Config.ImageFormat.PNG: return ImageFormat.Png;
case Config.ImageFormat.TIFF: return ImageFormat.Tiff;
default: return ImageFormat.Png;
}
}
private static string FormatFilename(string format, Config.ImageFormat imageFormat, DateTime time, int index)
{
string final = string.Format(format, imageFormat.ToString(), index, time);
final = final.Replace("/", "");
final = final.Replace("\\", "");
final = final.Replace("\"", "");
final = final.Replace("<", "");
final = final.Replace(">", "");
final = final.Replace("|", "");
final = final.Replace("?", "");
return final;
}
private static int m_CaptureIndex = 1;
public static int CaptureIndex
{
get
{
return m_CaptureIndex;
}
set
{
m_CaptureIndex = value;
}
}
public static Image Capture(IntPtr handle, IntPtr hdcSrc, CaptureArea area)
{
// get the size
User32.RECT windowRect = new User32.RECT();
if(area == CaptureArea.ClientArea)
User32.GetClientRect(handle, ref windowRect);
else
User32.GetWindowRect(handle, ref windowRect); // GetWindowRect
int width = windowRect.right - windowRect.left;
int height = windowRect.bottom - windowRect.top;
// create a device context we can copy to
IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
// create a bitmap we can copy it to
IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
// select the bitmap object
IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
// bitblt over
GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY);
// restore selection
GDI32.SelectObject(hdcDest, hOld);
// clean up
GDI32.DeleteDC(hdcDest);
User32.ReleaseDC(handle, hdcSrc);
// get a .NET image object for it
Image img = Image.FromHbitmap(hBitmap);
// free up the Bitmap object
GDI32.DeleteObject(hBitmap);
return img;
}
///
/// Generates a thumbnail of the given image.
///
/// The source image.
/// The new thumbnail.
private static Image GenerateThumbnail(Image img)
{
Size thumbnailSize = GetThumbnailSize(img);
Image thumb = new Bitmap(thumbnailSize.Width, thumbnailSize.Height, img.PixelFormat);
Graphics gfx = Graphics.FromImage(thumb);
gfx.CompositingQuality = CompositingQuality.HighQuality;
gfx.SmoothingMode = SmoothingMode.HighQuality;
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
gfx.DrawImage(img, 0, 0, thumbnailSize.Width, thumbnailSize.Height);
return thumb;
}
///
/// Gets the thumbnail size of the given image.
///
/// The desired image you would like to get the thumbnail size of.
/// The size based on the image's current width and height.
private static Size GetThumbnailSize(Image img)
{
int thumbWidth, thumbHeight;
if (Config.SetMaxHeight)
{
if (Config.SetMaxWidth)
{
// Check both
if (img.Height / (img.Width / Config.MaxWidth) < img.Width / (img.Height / Config.MaxHeight))
{
thumbWidth = Config.MaxWidth;
thumbHeight = img.Height / (img.Width / Config.MaxWidth);
}
else
{
thumbHeight = Config.MaxHeight;
thumbWidth = img.Width / (img.Height / Config.MaxHeight);
}
}
else // Just change Height
{
thumbHeight = Config.MaxHeight;
thumbWidth = img.Width / (img.Height / Config.MaxHeight);
}
}
else // Don't change height
{
if (Config.SetMaxWidth)
{
// Just check width
thumbWidth = Config.MaxWidth;
thumbHeight = img.Height / (img.Width / Config.MaxWidth);
}
else // Nothing... Default to both sizes.
{
thumbHeight = Config.MaxWidth;
thumbWidth = Config.MaxHeight;
}
}
return new Size(thumbWidth, thumbHeight);
}
#region API Function Calls
///
/// Helper class containing Gdi32 API functions
///
private class GDI32
{
public const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter
[DllImport("gdi32.dll")]
public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest,
int nWidth, int nHeight, IntPtr hObjectSource,
int nXSrc, int nYSrc, int dwRop);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth,
int nHeight);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("gdi32.dll")]
public static extern bool DeleteDC(IntPtr hDC);
[DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
}
///
/// Helper class containing User32 API functions
///
private class User32
{
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
[DllImport("user32.dll")]
public static extern IntPtr GetClientRect(IntPtr hWnd, ref RECT rect);
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);
}
#endregion API Function Calls
}
}