感谢大家的支持,这几天从早忙到晚,一个字累呀!!!现在挺困的,但是又不习惯这么早睡觉,哎~~还是利用这个时间继续来写第三篇吧.
  前两篇已经基本向大家介绍了绘图的基本知识.那么,我就用我们上两篇所学的,做几个例子.
  我们先来做一个简单的----仿QQ截图,关于这个的例子其实网上已经有这方面的资料了,但是为了文章的完整性,还是觉得有必要讲解.
  我们先来看一下效果:


                                                                                                                  (图1)
                                                      
                                                                                                                     (图2)

  接下来看看这是如何做到的. 
  思路:聊天窗体上有一个截图按钮,点击按钮后,程序将整个屏幕画在一个新的全屏窗体上,然后显示这个窗体.因为是全屏的窗体,并且隐藏了菜单栏、工具栏等,所以在我们看来就好像是一个桌面的截图,然后在这个新窗体上画矩形,最后保存矩形中的内容并显示在原来的聊天窗体中.
  步骤:
  A.新建一个窗体.命名为Catch.然后设置这个窗体的FormBorderStyle为None,WindowState为Maximized.
  B.我们对代码进行编辑:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Client
{
    public partial class Catch : Form
    {
        public Catch()
        {
            InitializeComponent();
        }

        用户变量#region 用户变量
        private Point DownPoint = Point.Empty;//记录鼠标按下坐标,用来确定绘图起点
        private bool CatchFinished = false;//用来表示是否截图完成
        private bool CatchStart = false;//表示截图开始
        private Bitmap originBmp;//用来保存原始图像
        private Rectangle CatchRect;//用来保存截图的矩形
        #endregion

        //窗体初始化操作
        private void Catch_Load(object sender, EventArgs e)
        {
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
            this.UpdateStyles();
            //以上两句是为了设置控件样式为双缓冲,这可以有效减少图片闪烁的问题,关于这个大家可以自己去搜索下
            originBmp = new Bitmap(this.BackgroundImage);//BackgroundImage为全屏图片,我们另用变量来保存全屏图片
        }

        //鼠标右键点击结束截图
        private void Catch_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }

        //鼠标左键按下时动作
        private void Catch_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (!CatchStart)
                {//如果捕捉没有开始
                    CatchStart = true;
                    DownPoint = new Point(e.X, e.Y);//保存鼠标按下坐标
                }
            }
        }

        private void Catch_MouseMove(object sender, MouseEventArgs e)
        {
            if (CatchStart)
            {//如果捕捉开始
                Bitmap destBmp = (Bitmap)originBmp.Clone();//新建一个图片对象,并让它与原始图片相同
                Point newPoint = new Point(DownPoint.X, DownPoint.Y);//获取鼠标的坐标
                Graphics g = Graphics.FromImage(destBmp);//在刚才新建的图片上新建一个画板
                Pen p = new Pen(Color.Blue,1);
                int width = Math.Abs(e.X - DownPoint.X), height = Math.Abs(e.Y - DownPoint.Y);//获取矩形的长和宽
                if (e.X < DownPoint.X)
                {
                    newPoint.X = e.X;
                }
                if (e.Y < DownPoint.Y)
                {
                    newPoint.Y = e.Y;
                }
                CatchRect = new Rectangle(newPoint,new Size(width,height));//保存矩形
                g.DrawRectangle(p,CatchRect);//将矩形画在这个画板上
                g.Dispose();//释放目前的这个画板
                p.Dispose();
                Graphics g1 = this.CreateGraphics();//重新新建一个Graphics类
                //如果之前那个画板不释放,而直接g=this.CreateGraphics()这样的话无法释放掉第一次创建的g,因为只是把地址转到新的g了.如同string一样
                g1 = this.CreateGraphics();//在整个全屏窗体上新建画板
                g1.DrawImage(destBmp,new Point(0,0));//将刚才所画的图片画到这个窗体上
                //这个也可以属于二次缓冲技术,如果直接将矩形画在窗体上,会造成图片抖动并且会有无数个矩形.
                g1.Dispose();
                destBmp.Dispose();//要及时释放,不然内存将会被大量消耗
                
            }
        }

        private void Catch_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (CatchStart)
                {
                    CatchStart = false;
                    CatchFinished = true;
                  
                }
            }
        }

        //鼠标双击事件,如果鼠标位于矩形内,则将矩形内的图片保存到剪贴板中
        private void Catch_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left&&CatchFinished)
            {
                if (CatchRect.Contains(new Point(e.X, e.Y)))
                {
                    Bitmap CatchedBmp = new Bitmap(CatchRect.Width, CatchRect.Height);//新建一个于矩形等大的空白图片
                    Graphics g = Graphics.FromImage(CatchedBmp);
                    g.DrawImage(originBmp, new Rectangle(0, 0, CatchRect.Width, CatchRect.Height), CatchRect, GraphicsUnit.Pixel);
                    //把orginBmp中的指定部分按照指定大小画在画板上
                    Clipboard.SetImage(CatchedBmp);//将图片保存到剪贴板
                    g.Dispose();
                    CatchFinished = false;
                    this.BackgroundImage = originBmp;
                    CatchedBmp.Dispose();
                    this.DialogResult = DialogResult.OK;
                    this.Close();
                }
            }
        }
    }
}

  C.创建了Catch窗体后,我们在截图按钮(位于聊天窗体上)上加入以下事件:

        private void bCatch_Click(object sender, EventArgs e)
        {

            if (bCatch_HideCurrent.Checked)
            {
                this.Hide();//隐藏当前窗体
                Thread.Sleep(50);//让线程睡眠一段时间,窗体消失需要一点时间
                Catch CatchForm = new Catch();
                Bitmap CatchBmp = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);//新建一个和屏幕大小相同的图片         
                Graphics g = Graphics.FromImage(CatchBmp);
                g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height));//保存全屏图片
                CatchForm.BackgroundImage = CatchBmp;//将Catch窗体的背景设为全屏时的图片
                if (CatchForm.ShowDialog() == DialogResult.OK)
                {//如果Catch窗体结束,就将剪贴板中的图片放到信息发送框中
                    IDataObject iData = Clipboard.GetDataObject();
                    DataFormats.Format myFormat = DataFormats.GetFormat(DataFormats.Bitmap);
                    if (iData.GetDataPresent(DataFormats.Bitmap))
                    {
                        richtextbox1.Paste(myFormat);
                        Clipboard.Clear();//清除剪贴板中的对象
                    }
                    this.Show();//重新显示窗体
                }
            }

        }

  这样我们的截图功能便完成了.
  我想对于初学者来说如何消去第一次绘制的图片是个比较困难的问题.如果没有采取措施,你会发现只要你鼠标移动,就会画一个矩形,这样便会出现N多的矩形,而我们只是要最后的那一个.
  一般解决这种问题的方法有两种:
  1.就是在绘制第二个图形时,我们先用与底色相同的颜色将上次绘制的图形重新绘制一下.但这往往需要底色为纯色时使用.
  2.我们并不直接将图形画在画板上,我们用一个图片A来保存原画板上的图片.然后再新建一个与图片A相同的图片B,将我们要绘制的图形画在该图片B上,然后再将该图片B画在画板上.这样图片A并没有被改变.于是第二次画的时候我们还是同样新建一个与图片A相同的图片进行绘制.那么上一次的图形就不会被保留下来.问题也就解决了.

  下一次,向大家介绍如何做一个仿windows画板的程序.

原作者:stg609

转载于:https://www.cnblogs.com/zhjzwl/archive/2009/02/27/1399498.html

C# GDI+ 简单绘图 (三) 仿浏览器截屏效果相关推荐

  1. js截屏代码_服务端浏览器截屏

    服务端浏览器截屏是结合 selenium + html2canvas 实现的通过在 Chrome 环境下生成图片. selenium是最广泛使用的开源Web UI自动化测试套件之一.本文中使用sele ...

  2. c# GDI+简单绘图(一)

    最近对GDI+这个东西接触的比较多,也做了些简单的实例,比如绘图板,仿QQ截图等. 最早接触这个类,是因为想做仿QQ截图的效果.巧的很,学会了如何做截图后,.NET课堂上老师也正巧要讲关于c#绘图方面 ...

  3. Chrome浏览器截屏插件的开发

    目 录 第一章 绪论 1 1.1选题背景及意义 1 1.2发展现状研究 2 1.2.1浏览器简介 2 1.2.2 浏览器发展历程 2 1.2.3 浏览器分类 3 1.2.4 chrome浏览器简介 3 ...

  4. C# 编写简单易用的 Windows 截屏增强工具

    前言 半年前我开源了 DreamScene2 一个小而快并且功能强大的 Windows 动态桌面软件.具体看查看<C# 编写小巧快速的 Windows 动态桌面软件>有很多的人喜欢,这使我 ...

  5. golang实现服务端浏览器截屏

    " 每天,探索一点点." 笔者近期在使用golang进行开发工作时,受360技术公众号曾发布过文章的启发,想到是否可以使用golang操作无屏浏览器(headless browse ...

  6. golong实现服务端浏览器截屏

    笔者说:近期在使用golang进行开发工作时,受360技术公众号曾发布过文章的启发,想到是否可以使用golang操作无屏浏览器(headless browser)实现诸如爬虫.截屏.自动化测试等功能. ...

  7. 运用插件html2canvas浏览器截屏的方法

    运用插件html2canvas浏览器截屏的方法 首先先安装 html2canvas 插件 toIMage() {// 获取dom元素let canvasBox = this.imageToFileRe ...

  8. Python+Selenium_UI自动化操作(5)——浏览器截屏

    UI自动化--浏览器截屏 练习: 用chrome浏览器打开不同的网页,并截屏. 语法: get_screenshot_as_file("图片名.格式") 数据准备: 将网页的域名w ...

  9. C#GDI+简单绘图

    原文地址:http://www.cnblogs.com/stg609/archive/2008/03/16/1108333.html (一)GDI+ 基础知识 最近对GDI+这个东西接触的比较多,也做 ...

最新文章

  1. g++使用C++11编译源文件
  2. python3教程-Python3教程
  3. vue.js实战——购物车练习(包含全选功能)
  4. 收集最优雅的8条编程最佳指导语录
  5. 如何做性能测试的一点思考总结
  6. java异常处理 ppt_Java异常处理、多线程ppt课件
  7. 基于WF设计业务流程平台_权限在流程模板外部映射
  8. 实验:基于keepalived实现两台realserver服务器中的nginx和php-fpm服务互为主从
  9. 拓端tecdat|在R语言中使用概率分布:dnorm,pnorm,qnorm和rnorm
  10. ScrollView不设置contentSize属性依然也可以作为底层滚动View(使用masonry设置scrollView的contentSize)...
  11. 基于java的教学评价系统的设计与实现
  12. java rxtx_Java使用开源Rxtx实现串口通讯(串口开发) | 学步园
  13. 用Multisim对高频丙类谐振功率放大器进行仿真
  14. 惠普803墨盒清零步骤_惠普2622墨盒清零步骤
  15. Windows 文件、目录操作编程 常用API
  16. 第三次作业:卷积神经网络基础
  17. 服务器基本搭建(Linux系统阿里云服务器为例)-购买云服务器
  18. 链上天眼2.0版本上线,欧科云链深耕区块链大数据产业成绩斐然
  19. 5.22非常虚伪的集训总结
  20. Total Access Emailer维护审计跟踪

热门文章

  1. c# 数据可视化_#OpenVisConf上的22位数据可视化从业者的10点收获
  2. 通da信TCP长连接数据算法分析
  3. Oracle嵌套表实例说明
  4. cvpr 深度估计_无监督单目视频深度估计中的uncertainty方法(CVPR#x27;20)
  5. 近段时间佛我就偶尔无
  6. java实现用户登录注册功能(用集合框架来实现)
  7. spring-redis-data的一个坑
  8. Android开发实践:为什么要继承onMeasure()
  9. 能说明你的Javascript技术很烂的五个原因
  10. 性能测试分析之带宽瓶颈的疑惑