在好例子网,分享、交流、成长!
您当前所在位置:首页C# 开发实例C#图形和图像处理 → C# 实现图片截取

C# 实现图片截取

C#图形和图像处理

下载此实例
  • 开发语言:C#
  • 实例大小:0.08M
  • 下载次数:122
  • 浏览次数:2027
  • 发布时间:2016-04-07
  • 实例类别:C#图形和图像处理
  • 发 布 人:fairystepwgl
  • 文件格式:.zip
  • 所需积分:2
 相关标签: 图片 C# 截图

实例介绍

【实例简介】

【实例截图】

【核心代码】

    public partial class Form2 : Form
    {
        public Form2() {
            InitializeComponent();
            this.FormBorderStyle = FormBorderStyle.None;
            this.Location = new Point(0, 0);
            this.Size = new Size(Screen.PrimaryScreen.Bounds.Width,
                Screen.PrimaryScreen.Bounds.Height);
            pictureBox1.Dock = DockStyle.Fill;
            this.TopMost = true;
            toolStrip1.SendToBack();
        }

        ~Form2() {//窗体关闭时卸载Hook
            mHook.UnLoadMouseHook();
        }

        Bitmap screenBmp;   //保存全屏的图像
        bool isDrawed;      //是否已经存在截图区域了
        bool isDraw;        //是否允许绘制(鼠标点下拖动)
        IntPtr hWnd;        //保存相应对象的句柄(最终获取窗体大小信息就用这个句柄)
        int sx, sy;         //鼠标点下时的鼠标坐标 Start X,Start Y;
        int w, h;           //鼠标拖动出来的区域的宽高(也就是要截图的宽高)
        int x, y;           //鼠标抬起是最终的矩形框左上角坐标(鼠标拖动绘制矩形 也就是要截图的左上角坐标)
        
        MouseHook mHook = new MouseHook();//创建一个Hook
        
        private void Form2_Load(object sender, EventArgs e) {
            screenBmp = GetScreen();            //保存全屏画面
            pictureBox1.Image = GetScreen();    //再次取得全屏画面(在上面填充半透明黑色)
            using (Graphics g = Graphics.FromImage(pictureBox1.Image)) {
                SolidBrush sb = new SolidBrush(Color.FromArgb(125, 0, 0, 0));
                g.FillRectangle(sb, 0, 0, this.Width, this.Height);
                sb.Dispose();
            }
            this.Enabled = false;       //禁用此窗体(这样在查找的时候才能把当前窗体忽略)
            mHook.HooKMouseEvent  =new MouseHook.MEventhandler(mHook_HooKMouseEvent);
            mHook.SetMouseHook();       //启用Hook
        }

        public Bitmap GetScreen() {//获得全屏图像
            Bitmap bmp = new Bitmap(this.Width, this.Height);
            using (Graphics g = Graphics.FromImage(bmp)) {
                g.CopyFromScreen(0, 0, 0, 0, this.Size);
            }
            return bmp;
        }
        //绑定到Hook上面的事件
        private void mHook_HooKMouseEvent(object sender,MouseInfoEventArys e) {
            if (!isDrawed && !isDraw)          //如果已经存在截图区域或者用户正在拖动那么就不用找寻了
                FoundRect();
            if (e.MBtn == Btn.LeftDowm) {//判断左键是否点下
                if (isDrawed)              //如果已经存在截图区域了那么久返回
                    return;
                this.Enabled = true;          //点下的时候恢复窗体的禁用
                sx = MousePosition.X;     //记录下当前鼠标位置以
                sy = MousePosition.Y;
                DrawRect("Normal");     //然后把当前区域绘制出来
                isDrawed = true;        //已经存在截图区域
                isDraw = true;          //只要左键还没有抬起允许拖动绘制自己的区域
            } else if(e.MBtn == Btn.RightUp) {//如果右键抬起
                if (isDrawed) {             //判断是否已存在截图区域 已经存在就撤销
                    hWnd = IntPtr.Zero;     //句柄清空 重新找寻
                    isDrawed = false;       //没有截图区域
                    this.Enabled = false;   //继续禁用窗体 (查找时忽略禁用的窗体)
                    toolStrip1.SendToBack();//工具栏隐藏起来(至于所有控件底部)
                } else {
                    mHook.UnLoadMouseHook();    //退出之前 先卸载Hook
                    this.Enabled = true;        //如果没有截图区域 那关闭窗体 先恢复窗体
                    new Thread(new ThreadStart(() => {
                        Thread.Sleep(100);//暂停100毫秒再关闭窗体 (让改窗体接受到鼠标右键抬起)
                        try {//好吧 我承认 这里我也不知道为什么 有时候提示改 不能再该句柄创建前调用Invoke(我很郁闷我的窗体不是创建了么)
                            this.Invoke(new MethodInvoker(() => {
                                this.Close();
                            }));
                        } catch {
                            this.Close();
                        } 
                    })).Start();
                }
            }
        }
        public void FoundRect() {
            //mhWnd找到的窗体的句柄main hWnd
            IntPtr mhWnd = WinAPI.ChildWindowFromPointEx(
                    WinAPI.GetDesktopWindow(),                          //从桌面开始查找
                    new WinAPI.LPPOINT(MousePosition.X,MousePosition.Y), //鼠标当前坐标
                    WinAPI.CWP_SKIPDISABLED | WinAPI.CWP_SKIPINVISIBL);//忽略桌面上隐藏或者禁用的窗体

            WinAPI.LPPOINT lp = new WinAPI.LPPOINT(MousePosition.X,MousePosition.Y);     //注意这里的鼠标不是屏幕坐标 而是 窗体内部坐标
            //fhWnd作为继续查找的标志 flag hWnd
            IntPtr fhWnd = mhWnd;
            IntPtr rhWnd = IntPtr.Zero;//rhWnd查找上来的句柄
            bool isEnd = false;
            while (!isEnd) {//循环的去找寻在窗体上当前坐标最内层的控件
                WinAPI.ScreenToClient(fhWnd, out lp);//循环一次 转化一下(查找是用内部坐标)
                rhWnd = WinAPI.ChildWindowFromPointEx(fhWnd, new WinAPI.LPPOINT(lp.x, lp.y), WinAPI.CWP_All);
                if (rhWnd == IntPtr.Zero || rhWnd == fhWnd) {//如果循环是没有找到或找到的与上一个句柄一样那么就结束
                    rhWnd = fhWnd;  //结束前赋值为上一次找到的句柄 
                    isEnd = true;
                } else {
                    fhWnd = rhWnd;//否则根据找到的句柄的作为标志句柄再在其内部继续找寻
                }
            }
            if (hWnd == rhWnd)  //如果找到的句柄 和上一次绘制是用的句柄一样 那么 就直接返回
                return;
            hWnd = rhWnd;                //把查找上来的句柄 赋值 给最终要是用的句柄
            DrawRect("Normal");          //然后在这个新的句柄外面绘制一圈
        }
        
        public void DrawRect(string type) {//绘制区域
            using (Graphics g = pictureBox1.CreateGraphics()) //建立画布
            using (Pen p = new Pen(Color.FromArgb(255, 24, 219, 255), 4)) {//画笔
                pictureBox1.Refresh();  //绘制前先清空画布
                switch (type) {
                    case "Normal"://绘制找到的区域
                        WinAPI.LPRECT rect = new WinAPI.LPRECT();
                        WinAPI.GetWindowRect(hWnd, out rect);
                        x = rect.left;y = rect.top;
                        w = rect.right - rect.left;h = rect.bottom - rect.top;
                        g.DrawRectangle(p, x, y, w, h);
                        Rectangle drawRect = new Rectangle(x, y, w, h);
                        g.DrawImage(screenBmp, drawRect, drawRect, GraphicsUnit.Pixel);
                        break;
                    case "Rectangle"://鼠标点下并且拖动的时候 绘制矩形(也就是自定义区域 - 现在鼠标处于拖动状态)
                        p.Width = 1;
                        w = Math.Abs(MousePosition.X - sx);//注意当前鼠标于鼠标点下时的坐标的差值的绝对值
                        h = Math.Abs(MousePosition.Y - sy);
                        if (MousePosition.X < sx) {  //如果x轴是负数那么图像x轴的其实坐标用当前鼠标的x
                            x = MousePosition.X;
                        } else {                        //否则就用鼠标点下是的坐标
                            x = sx;
                        }
                        if (MousePosition.Y < sy) {
                            y = MousePosition.Y;
                        } else {
                            y = sy;
                        }
                        g.DrawRectangle(p, x, y, w, h);//s,y矩形框左上角,w,h矩形框宽高 也就是图像的大小
                        break;
                    case "MouseUp"://鼠标抬起的时候 把相应区域的图片也画上去(正常的不是黑色的图)
                        //为什么要加一个像素?为了精确 你的屏幕宽1440你鼠标放到右边坐标是1339 多想想就明白了
                        //鼠标在第一像素时x为0 在第二个像素时x为1
                        Rectangle imgRect = new Rectangle(x, y, w   1, h   1);
                        g.DrawRectangle(p, x, y, w   1, h   1);
                        g.DrawImage(screenBmp, imgRect, imgRect, GraphicsUnit.Pixel);
                        break;
                }
            }
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e) {
            //判断鼠标是否点下 如果点下没有松开 那么移动的时候就绘制区域
            if (isDraw) {
                //因为窗体在恢复禁用的时候就会马上出发Move事件 所以判断一下 如果鼠标在点下的时候 位置没用动那么什么都不做
                if (sx == MousePosition.X && sy == MousePosition.Y) {
                    return;
                }
                isDrawed = false;     
                //前面去看 鼠标默认才点下的时候isDrawed = true;isDraw = true如果鼠标不移动就抬起
                //那么就以找到的区域作为截图区域 如果点下的时候鼠标没有抬起移动的话 那么isDrawed = false取消默认找到的区域
                //直到鼠标抬起才确认为 isDrawed = true表示 截图区已经存在
                DrawRect("Rectangle");//注意 这个是自己拖动出来的区域 如果你是从右向左拖动 那么宽度的差值是负数
            }
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e) {
            isDraw = false;             //进制鼠标move事件里面的代码
            SetToolStripLocation();     //既然鼠标抬起 那么就说用户确认好了截图区 那么设置工具条的位置
            toolStrip1.BringToFront();  //显示工具条
            //因为第一次点下鼠标 默认是 绘制自动框选的区域 所以 坐标没有变的话 什么都不做
            if (sx == MousePosition.X && sy == MousePosition.Y || isDrawed) {
                return;
            }
            DrawRect("MouseUp");
            isDrawed = true;
        }
        //设置工具条的位置
        public void SetToolStripLocation() {
            toolStrip1.Left = x   10;
            if (y   h   20   toolStrip1.Height <= Screen.PrimaryScreen.Bounds.Height) {
                toolStrip1.Top = y   h   10;
            } else if (toolStrip1.Height   20 <= y) {
                toolStrip1.Top = y - 10 - toolStrip1.Height;
            } else {
                toolStrip1.Top = y   10;
            }

            if (toolStrip1.Right >= Screen.PrimaryScreen.Bounds.Width - 10)
                toolStrip1.Left = Screen.PrimaryScreen.Bounds.Width - 10 - toolStrip1.Width;
        }
        //双击就把截图区域的内容复制到剪贴板
        private void pictureBox1_DoubleClick(object sender, EventArgs e) {
            Clipboard.SetImage(GetSaveBmp());
            this.Close();
        }
        //工具条上面的 复制到剪贴板
        private void tool_Clipboard_Click(object sender, EventArgs e) {
            pictureBox1_DoubleClick(null, null);
        }
        //工具条上面的 退出
        private void tool_Exit_Click(object sender, EventArgs e) {
            this.Close();
        }
        //工具条上面的 撤销
        private void tool_Cancel_Click(object sender, EventArgs e) {
            mHook_HooKMouseEvent(null, new MouseInfoEventArys(Btn.RightUp, 0, 0));
        }
        //工具条上面的 保存
        private void tool_Save_Click(object sender, EventArgs e) {
            SaveFileDialog saveFile = new SaveFileDialog();
            saveFile.Filter = "JPEG文件|*.jpg;*.jpeg|BMP文件|*.bmp";
            saveFile.FileName = "SL截图"   GetTimeStr();          //设置默认的文件名
            if (DialogResult.OK == saveFile.ShowDialog()) {
                switch (saveFile.FilterIndex) { 
                    case 1:
                        GetSaveBmp().Save(saveFile.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
                        break;
                    case 2:
                        GetSaveBmp().Save(saveFile.FileName, System.Drawing.Imaging.ImageFormat.Bmp);
                        break;
                }
                this.Close();
            }
        }
        //保存的时候默认文件名取时间
        public String GetTimeStr(){
            DateTime time = DateTime.Now;
            return time.Year   "-"   time.Month   "-"   time.Day   "_"  
                time.Hour   time.Minute   time.Second;
        }
        //获得最终要保存的图像内容
        public Bitmap GetSaveBmp() {
            Bitmap bmp = new Bitmap(w, h);
            using (Graphics g = Graphics.FromImage(bmp)) {
                Rectangle srcRect = new Rectangle(x, y, w   1, h   1);
                Rectangle destRect = new Rectangle(0, 0, w   1, h   1);
                g.DrawImage(screenBmp, destRect, srcRect, GraphicsUnit.Pixel);
            }
            return bmp;
        }
    }

标签: 图片 C# 截图

实例下载地址

C# 实现图片截取

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警