1. 程式人生 > >C# 影象處理(二)(螢幕擷取、截圖外掛)

C# 影象處理(二)(螢幕擷取、截圖外掛)

雙擊執行截圖外掛,工具預設延時5秒後截圖



可擷取全屏


擷取到快捷選單和滑鼠





也可通過cmd命令執行工具,呼叫示例引數如下:

REM 呼叫截圖工具進行截圖
call "%~dp0getScreen.exe"

REM 儲存到指定目錄(D:\tmp\截圖.png)
call "%~dp0getScreen.exe" "D:\tmp\截圖1.png"

REM 延時1秒執行(1000ms)
call "%~dp0getScreen.exe" "D:\tmp\截圖2.png" 1000

REM 截圖指定區域 (0 0 100 100)
call "%~dp0getScreen.exe" "D:\tmp\截圖3.png" 1000 0 0 100 100

REM 截圖時不要滑鼠
call "%~dp0getScreen.exe" "D:\tmp\截圖4.png" 1000 0 0 100 100 false
工具原始碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace getScreen
{
    static class Program
    {
        /// <summary>
        /// 應用程式的主入口點。
        /// 通過引數呼叫截圖外掛,call "%~dp0getScreen.exe" "D:\tmp\截圖4.png" 1000 0 0 -1 -1 true
        /// </summary>
        [STAThread]
        static void Main(String[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            //Application.Run(new Form1());

            // 設定截圖控制資訊
            ScreenParam param = new ScreenParam();
            param.programExit = true;               // 截圖執行完成後退出程式
            param.delay_ms = 5000;                  // 預設延時5秒截圖

            if (args.Length > 0)
            {
                if (args.Length > 0) param.savePath = args[0];                      // 儲存路徑
                if (args.Length > 1) param.delay_ms = Int32.Parse(args[1]);         // 延時(ms)
                if (args.Length > 5)
                {
                    param.x = Int32.Parse(args[2]);                                 // 擷取區域
                    param.y = Int32.Parse(args[3]);
                    param.width = Int32.Parse(args[4]);
                    param.height = Int32.Parse(args[5]);
                }
                if (args.Length > 6) param.haveCursor = !args[5].Equals("false");   // 是否包含滑鼠

                //MessageBox.Show(param.savePath + ", " + param.delay_ms + ", " + param.x + ", " + param.y + ", " + param.width + ", " + param.height + ", " + param.haveCursor); 
            }


            ScreenShot.getScreen(param);    // 截圖
            Application.Run();              // 在當前執行緒上執行應用程式訊息迴圈
        }

        /// <summary>
        /// 呼叫系統退出
        /// </summary>
        public static void exit()
        {
            //Application.Exit();
            //Application.ExitThread();
            System.Environment.Exit(0);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace getScreen
{
    /// <summary>
    /// 截圖控制引數
    /// </summary>
    class ScreenParam
    {
        public int x = 0, y = 0, width = -1, height = -1;   // 擷取區域,當前設定值會替換為全屏
        public String savePath = "";                        // 截圖影象儲存完整路徑
        public bool haveCursor = true;                      // 是否包含滑鼠
        public int delay_ms = 0;                            // 延時ms

        public bool programExit = false;    // 標識截圖完成後是否退出

        /// <summary>
        /// 截圖控制引數
        /// </summary>
        public ScreenParam(int x = 0, int y = 0, int width = -1, int height = -1, String savePath = "", bool haveCursor = true, int delay_ms = 0) 
        { 
            this.x = x;
            this.y = y;
            this.width =width;
            this.height = height;
            this.savePath = savePath;
            this.haveCursor = haveCursor;
            this.delay_ms = delay_ms;
        }
    }

    class ScreenShot
    {
        # region 影象處理功能函式

        /// <summary>
        /// 按指定尺寸對影象pic進行非拉伸縮放
        /// </summary>
        public static Bitmap shrinkTo(Image pic, Size S, Boolean cutting)
        {
            //建立影象
            Bitmap tmp = new Bitmap(S.Width, S.Height);     //按指定大小建立點陣圖

            //繪製
            Graphics g = Graphics.FromImage(tmp);           //從點陣圖建立Graphics物件
            g.Clear(Color.FromArgb(0, 0, 0, 0));            //清空

            Boolean mode = (float)pic.Width / S.Width > (float)pic.Height / S.Height;   //zoom縮放
            if (cutting) mode = !mode;                      //裁切縮放

            //計算Zoom繪製區域             
            if (mode)
                S.Height = (int)((float)pic.Height * S.Width / pic.Width);
            else
                S.Width = (int)((float)pic.Width * S.Height / pic.Height);
            Point P = new Point((tmp.Width - S.Width) / 2, (tmp.Height - S.Height) / 2);

            g.DrawImage(pic, new Rectangle(P, S));

            return tmp;     //返回構建的新影象
        }


        //儲存影象pic到檔案fileName中,指定影象儲存格式
        public static void SaveToFile(Image pic, string fileName, bool replace, ImageFormat format)    //ImageFormat.Jpeg
        {
            // 建立儲存目錄
            confirmDir(fileName);

            //若影象已存在,則刪除
            if (System.IO.File.Exists(fileName) && replace)
                System.IO.File.Delete(fileName);

            //若不存在則建立
            if (!System.IO.File.Exists(fileName))
            {
                if (format == null) format = getFormat(fileName);   //根據拓展名獲取影象的對應儲存型別

                if (format == ImageFormat.MemoryBmp) pic.Save(fileName);
                else pic.Save(fileName, format);                    //按給定格式儲存影象
            }
        }

        //根據檔案拓展名,獲取對應的儲存型別
        public static ImageFormat getFormat(string filePath)
        {
            ImageFormat format = ImageFormat.MemoryBmp;
            String Ext = System.IO.Path.GetExtension(filePath).ToLower();

            if (Ext.Equals(".png")) format = ImageFormat.Png;
            else if (Ext.Equals(".jpg") || Ext.Equals(".jpeg")) format = ImageFormat.Jpeg;
            else if (Ext.Equals(".bmp")) format = ImageFormat.Bmp;
            else if (Ext.Equals(".gif")) format = ImageFormat.Gif;
            else if (Ext.Equals(".ico")) format = ImageFormat.Icon;
            else if (Ext.Equals(".emf")) format = ImageFormat.Emf;
            else if (Ext.Equals(".exif")) format = ImageFormat.Exif;
            else if (Ext.Equals(".tiff")) format = ImageFormat.Tiff;
            else if (Ext.Equals(".wmf")) format = ImageFormat.Wmf;
            else if (Ext.Equals(".memorybmp")) format = ImageFormat.MemoryBmp;

            return format;
        }

        [DllImport("user32.dll")]
        static extern bool GetCursorInfo(out CURSORINFO pci);

        private const Int32 CURSOR_SHOWING = 0x00000001;
        [StructLayout(LayoutKind.Sequential)]
        struct POINT
        {
            public Int32 x;
            public Int32 y;
        }

        [StructLayout(LayoutKind.Sequential)]
        struct CURSORINFO
        {
            public Int32 cbSize;
            public Int32 flags;
            public IntPtr hCursor;
            public POINT ptScreenPos;
        }

        private static ScreenParam paramI = null;
        /// <summary>
        /// 延時截圖處理邏輯
        /// </summary>
        private static void ScreenShot_Tick(object sender, EventArgs e)
        {
            ((Timer)sender).Stop(); // 停止計時
            getScreen(paramI);       // 執行截圖
            paramI = null;
        }

        /// <summary>
        /// 根據param中的引數控制截圖
        /// </summary>
        public static void getScreen(ScreenParam param)
        {
            if (param == null) return;

            if (param.delay_ms > 0)
            {
                Timer timer = new Timer();
                timer.Interval = param.delay_ms;
                timer.Tick += ScreenShot_Tick;
                
                paramI = param;
                paramI.delay_ms = 0;

                timer.Enabled = true;
            }
            else getScreen(param.x, param.y, param.width, param.height, param.savePath, param.haveCursor, param.delay_ms, param.programExit);
        }

        /// <summary>
        /// 擷取螢幕指定區域為Image,儲存到路徑savePath下,haveCursor是否包含滑鼠
        /// </summary>
        public static Image getScreen(int x = 0, int y = 0, int width = -1, int height = -1, String savePath = "", bool haveCursor = true, int delay_ms = 0, bool exit = false)
        {
            // 延時截圖時無返回值
            if (delay_ms > 0)
            {
                getScreen(new ScreenParam(x, y, width, height, savePath, haveCursor, delay_ms));
                return null;
            }

            if (width == -1) width = SystemInformation.VirtualScreen.Width;
            if (height == -1) height = SystemInformation.VirtualScreen.Height;

            Bitmap tmp = new Bitmap(width, height);                 //按指定大小建立點陣圖
            Graphics g = Graphics.FromImage(tmp);                   //從點陣圖建立Graphics物件
            g.CopyFromScreen(x, y, 0, 0, new Size(width, height));  //繪製

            // 繪製滑鼠
            if (haveCursor)
            {
                try
                {
                    CURSORINFO pci;
                    pci.cbSize = Marshal.SizeOf(typeof(CURSORINFO));
                    GetCursorInfo(out pci);
                    System.Windows.Forms.Cursor cur = new System.Windows.Forms.Cursor(pci.hCursor);
                    cur.Draw(g, new Rectangle(pci.ptScreenPos.x, pci.ptScreenPos.y, cur.Size.Width, cur.Size.Height));
                }
                catch (Exception ex) { }            // 若獲取滑鼠異常則不顯示
            }

            if (savePath.Equals("")) savePath = JpgTmpPath();                   // 設定預設儲存路徑
            //Size halfSize = new Size((int)(tmp.Size.Width * 0.8), (int)(tmp.Size.Height * 0.8));  // 按一半尺寸儲存影象
            if (!savePath.Equals("")) saveImage(tmp, tmp.Size, savePath);       // 儲存到指定的路徑下

            if (exit) System.Environment.Exit(0);   // 退出當前應用程式
            return tmp;     //返回構建的新影象
        }

        /// <summary>
        /// 縮放icon為指定的尺寸,並儲存到路徑PathName
        /// </summary>
        public static void saveImage(Image image, Size size, String PathName)
        {
            Image tmp = shrinkTo(image, size, false);
            SaveToFile(tmp, PathName, true, null);
        }


        // 生成jpg的臨時儲存路徑
        public static String JpgTmpPath()
        {
            string dateTime = DateTime.Now.ToString("yyyy-MM-dd_hh.mm.ss");
            string screenDir = System.AppDomain.CurrentDomain.BaseDirectory + @"screens";  // 截圖儲存路徑
            String pathName = screenDir + @"\" + dateTime + ".png";

            return pathName;
        }

        /// <summary>
        /// 檢測目錄是否存在,若不存在則建立
        /// </summary>
        public static void confirmDir(string path)
        {
            String rootDir = System.IO.Path.GetDirectoryName(path);             //獲取path所在的目錄
            if (!Directory.Exists(rootDir)) Directory.CreateDirectory(rootDir); //若目錄不存在則建立
        }

        # endregion

    }
}

開源地址