“仿Win8截图工具”的制作

 

    这是我发表在CSDN博客上的第一篇博文,是关于“仿Win8截图工具”。这个仿Win8截图工具及其源代码也上传至CSDN。

     C#里的GDI+应该知道吧,通俗点说就是“搞图像”的。一个月以前我电脑装了Win8消费者预览版,Win8里自带了一个截图工具(后来发现WIn7里也有。。。糗大了)。我便模仿这个Win8截图工具也做了一个(当然我的水平有限,也看了一些别人做截图的代码,但我感觉好的代码是可以拿来好好研究,好好改造,只要能使自己进步就行),当然功能没那么全,有很多地方做的不好,但基本实现了截图,在所截图片上绘图,保存图片的功能。

          

       用过Win8的朋友应该知道截图工具长啥样,怎么个工作过程。其实截图工具应该有三个窗体,一个是主窗体Main,也就是最小的那个窗体。还有一个是可以显示截图过程的窗体Catch,这个窗体其实是最大化的。最后一个是画图窗体Draw,就是可以实现截完图后,在截图上画画的功能。

       这三个窗体是怎么工作的呢?首先当你双击“截图工具”这个应用程序时,出现的是主窗体Main。当你点击“新建”按钮,主窗体Main会执行一个操作,那就是将当前显示器上显示的全屏内容画在一张图片上,并将该图片设为全屏窗体Catch的壁纸,就相当于向Catch类传递了一个原材料,接下来,当然由Catch类处理这张图片,处理完后得到一张截图,截图是保存在剪切板上的。随后又回到主窗体Main,通过调用Draw类将剪切板的图片设为窗体Draw的背景,其实就相当然于将截图贴到窗体Draw上,而Draw窗体具有画图功能,因此就可以对截图进行绘画和保存工作了。

       当然博文所能介绍的内容是有限的,而且也没必要从零开始介绍这个小项目的细节。下面我就挑些比较基础比较关键的地方讲吧。

       第一,基础的GDI+。GDI+里有一个“图像采集”(我自己命名)的功能,这算是比较基础的了。就是可以将图像显示在一张图片上,就相当于将虚像变成实像。那要怎么实现呢,我简单概括下:步骤1:创建一个空白图片;步骤2:在该图片上建立一个画板;步骤3:将图像画至该画板上。执行完后,空白图片上便有了图像。当然还要记得释放画板,有时若图片没用了,也要释放,这样可以释放内存空间。

        第二,就介绍截图以及绘图的核心吧。其实截图和绘图基本都由鼠标操作,那么当然就要定义鼠标响应事件了。先以截图部分为例吧。截图呢,有四个鼠标鼠标响应事件:左击(开始截图),拖动(画出矩形),松开(调出绘图窗体),双击(取消截图,即退出屏幕定格的状态)而左击,拖动,松开是连贯性的动作,因此要定义一个布尔常量catchStart当作开关,还没左击时catchStart值是false,左击后catchStart值就变为true,这样才能执行拖动以及松开这两个连贯的动作,当然松开事件中又得将catchStart值设为false,因为截图结束了嘛,就相当于还没截图,开关是闭上的。
下面我再详细介绍这四个事件具体怎么实现。

1.左击事件其实很简单,就是获取该左击点的横纵坐标,该点就是初始点startPoint,当然该变量要设为全局变量,因为其他函数里还要用到该值。

2.拖动事件就比较复杂了,可以说是截图这部分的核心吧。首先当然还要获取一点movePoint,我之所以命名为movePoint,是因为这点是变化的,不像初始点startPoint一旦你左击,初始点坐标即固定。movePoint点的横纵坐标是随着你鼠标的拖动而改变的。好了,有了初始点和移动点,我们通过它们的横纵坐标当然很容易就可以得到所画矩形的大小(这里注意计算时要加个绝对值,很简单,不解释),有了矩形的大小,当然还需矩形左上点的横纵坐标,这不就是初始点startPoint的横纵坐标么。当然,我们得到的只是个虚的矩形,要想将他变为现实,就要用到“图像采集”了,怎么采集,我前面已经说过。这里我还要说下,这个拖动事件确实比较麻烦。因为它是动态的,之所以说动态,是因为矩形的形状是随着movePoint点的变化而改变。那这里面就涉及到了一个“重画”技术。其实游戏图像看起来之所以会动,就是因为图形不断在重画。而矩形也一样,随这movePoint点横纵坐标的不断变化,画板上的矩形形状就不断变化,得到的矩形图像当然是变化的,只不过CPU处理速度快,你根本看不到它一条线一条线画上去。

3.松开事件其实不复杂。在讲松开事件之前我要说下,这里有一个问题,为什么要定义原始图片,中介图片,为什么不定义一张图片就够了。其实,中介图片是拖动事件里画图用的,画完图后矩形就留在上面,就相当于该中介图片已被污染,不能再用。我们要的是矩形截出来的那一部分,当然要按照和矩形一样的尺寸,位置在一块干净的图片上切割下来。而这块干净的图片便是原始图片,因为它在这之前没被做过任何“手脚”。好了,如何按照和矩形一样的尺寸,位置在一块原始图片上切割下来呢?这就是松开事件要做的。怎么做,见代码!最后要将图片保存至剪切板,怎么做,见代码!

        /// <summary>
        /// 鼠标松开事件;
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Up_Mouse(object sender, MouseEventArgs e)
        {
            //截图开始状态;
                if (catchStart)
                {
                    //这个if框架不能省,注释掉if框架后,虽然程序可运行,但当我左击后,不拖鼠标就松开(相当于就点了一点)程序就会报错;
                    if (catchRectangle.Width != 0 && catchRectangle.Height!=0)
                    {
                        catchStart = false;  //截图结束;
                        Bitmap catchedPicture = new Bitmap(catchRectangle.Width, catchRectangle.Height);   //新建一个于矩形等大的空白图片catchedPicture(这才是真正的截图);
                        Graphics g = Graphics.FromImage(catchedPicture);   //在图片catchedPicture上新建画板;
                        g.DrawImage(originalPicture, new Rectangle(0, 0, catchRectangle.Width, catchRectangle.Height), catchRectangle, GraphicsUnit.Pixel);   //把全屏图片中与矩形同位置同大小的部分(就是刚才在全屏上截得的那部分虚像)显示在画板上;
                        Clipboard.SetImage(catchedPicture);//将图片保存到剪切板;

                        g.Dispose();   //释放画板;
                        catchedPicture.Dispose();   //释放截图(因为截图已经保存至剪切板);
                        this.DialogResult = DialogResult.OK;   //将窗体DialogResult设为Ok,以通知主窗体该窗体截图完毕;
                        this.Close();
                    }
                }
        }


 

4.右击事件就是结束Catch窗体,取消截图。
至于绘图部分,其实跟截图部分大同小异,只是一个用铅笔一个是矩形,当然在Draw里还要注意一点,那就是避免你在截图上画的线条消失的方法,其实还是个“重画”,怎么做,见代码!  


 

        /// <summary>
        /// 窗体最小化造成所画图像消失的处理方法;
        /// </summary>
        /// <param name="paintevent"></param>
        protected override void OnPaint(PaintEventArgs paintevent)
        {
            Graphics g = paintevent.Graphics;
            g.DrawImage(originalBmp, 0, 0);
        }


 

关于这个截图工具,我的体会说这些吧,有说的不妥的地方(毕竟新手嘛),还望大虾们指教啊!



 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值