博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# GDI+ 简单绘图 (三)
阅读量:6622 次
发布时间:2019-06-25

本文共 4677 字,大约阅读时间需要 15 分钟。

感谢大家的支持,这几天从早忙到晚,一个字累呀!!!现在挺困的,但是又不习惯这么早睡觉,哎~~还是利用这个时间继续来写第三篇吧.

  前两篇已经基本向大家介绍了绘图的基本知识.那么,我就用我们上两篇所学的,做几个例子.

  我们先来做一个简单的----仿QQ截图,关于这个的例子其实网上已经有这方面的资料了,但是为了文章的完整性,还是觉得有必要讲解.

  我们先来看一下效果:

                              

                                                                                                                  (图1)
                                                      20083191642.JPG
                                                                                                                     (图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();
        }
        
用户变量
        
//
窗体初始化操作
        
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博客园博客,原文链接:http://www.cnblogs.com/stg609/archive/2008/03/19/1113694.html,如需转载请自行联系原作者

你可能感兴趣的文章
Mahout分步式程序开发 聚类Kmeans(转)
查看>>
修改linux最大文件句柄数
查看>>
接口幂等
查看>>
LibreOffice 打开中文乱码
查看>>
FromBottomToTop第十三周项目博客
查看>>
Activity的四种启动模式
查看>>
Centos vsftpd服务器搭建
查看>>
【常用工具】常用工具收集
查看>>
Tax
查看>>
网站页面多出&65279出现空白行的原因及解决方法
查看>>
第二阶段团队冲刺站立会议06
查看>>
html
查看>>
本地wampserver如何配置伪静态
查看>>
操作系统面试
查看>>
【转载】支持向量机SVM(一)
查看>>
C#串口通信实例
查看>>
小程序数据返回时刷新当前页面数据
查看>>
MySQL数据故障时备份与恢复
查看>>
Nlopt优化函数库,用法举例
查看>>
海思 core 电压动态调整
查看>>