Search code examples
windowsscreenshot

How can I save a screenshot directly to a file in Windows?


Is there a one button way to save a screenshot directly to a file in Windows?


TheSoftwareJedi accurately answered above question for Windows 8 and 10. Below original extra material remains for posterity.

This is a very important question as the 316K views shows as of 2021. Asked in 2008, SO closed this question around 2015 as being off-topic, probably because of the last question below.

In Windows XP, one can press Alt-PrintScreen to copy an image of the active window, or Ctrl-PrintScreen to copy an image of the full desktop.

This can then be pasted into applications that accept images: Photoshop, Microsoft Word, etc.

I'm wondering: Is there a way to save the screenshot directly to a file? Do I really have to open an image program, like Paint.net or Photoshop, simply to paste an image, then save it?


Solution

  • You can code something pretty simple that will hook the PrintScreen and save the capture in a file.

    Here is something to start to capture and save to a file. You will just need to hook the key "Print screen".

    using System;
    using System.Drawing;
    using System.IO;
    using System.Drawing.Imaging;
    using System.Runtime.InteropServices;
    public class CaptureScreen
    {
    
        static public void Main(string[] args)
        {
    
            try
            {
                Bitmap capture = CaptureScreen.GetDesktopImage();
                string file = Path.Combine(Environment.CurrentDirectory, "screen.gif");
                ImageFormat format = ImageFormat.Gif;
                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);
    }
    

    Update Here is the code to hook the PrintScreen (and other key) from C#:

    Hook code