/* * $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 } }