




已阅读5页,还剩10页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C# GDI+ 简单绘图知识最近对GDI+这个东西接触的比较多,也做了些简单的实例,比如绘图板,仿QQ截图等废话不多说了,我们先来认识一下这个GDI+,看看它到底长什么样.GDI+:Graphics Device Interface Plus也就是图形设备接口,提供了各种丰富的图形图像处理功能;在C#.NET中,使用GDI+处理二维(2D)的图形和图像,使用DirectX处理三维(3D)的图形图像,图形图像处理用到的主要命名空间是System . Drawing:提供了对GDI+基本图形功能的访问,主要有Graphics类、Bitmap类、从Brush类继承的类、Font类、Icon类、Image类、Pen类、Color类等.大概了解了什么是GDI+后,我们来看一下绘图要用到的主要工具,要画图,肯定要画板吧,在C#中画板可以通过Graphics这个类来创建,有了画板,总得弄个笔什么之类的吧,不然怎么画呀,难不成我们用手指画.笔又可以分好多种类,比如铅笔,画刷等.它们的区别主要是铅笔可以用来画线条,而画刷呢,嘿嘿,自己考虑下.在c#中我们可以用Pen,Brush类来实现类似功能.颜料则自然是用Color类了.有了工具,我们就可以开始动手了!(所需命名空间:using System.Drawing;)实现效果:在空白窗体中画基本图形准备一个画板:创建一个画板主要有3种方式:A: 在窗体或控件的Paint事件中直接引用Graphics对象B: 利用窗体或某个控件的CreateGraphics方法C: 从继承自图像的任何对象创建Graphics对象这次我们就先以A为例:private void Form1_Paint(object sender, PaintEventArgs e)Graphics g = e.Graphics; /创建画板,这里的画板是由Form提供的.然后,我们要只笔:private void Form1_Paint(object sender, PaintEventArgs e)Graphics g = e.Graphics; /创建画板,这里的画板是由Form提供的.Pen p = new Pen(Color.Blue, 2);/定义了一个蓝色,宽度为的画笔接下来我们就可以来画画了.private void Form1_Paint(object sender, PaintEventArgs e)Graphics g = e.Graphics; /创建画板,这里的画板是由Form提供的.Pen p = new Pen(Color.Blue, 2);/定义了一个蓝色,宽度为的画笔g.DrawLine(p, 10, 10, 100, 100);/在画板上画直线,起始坐标为(10,10),终点坐标为(100,100)g.DrawRectangle(p, 10, 10, 100, 100);/在画板上画矩形,起始坐标为(10,10),宽为,高为g.DrawEllipse(p, 10, 10, 100, 100);/在画板上画椭圆,起始坐标为(10,10),外接矩形的宽为,高为效果图如下:在上一片里已经向大家介绍了如何使用GDI+绘制简单的图像,这一片继续向大家介绍其它一些绘图知识.1.首先我们来看下上一片中我们使用过的Pen.Pen的属性主要有: Color(颜色),DashCap(短划线终点形状),DashStyle(虚线样式),EndCap(线尾形状), StartCap(线头形状),Width(粗细)等.我们可以用Pen 来画虚线,带箭头的直线等Penp = newPen(Color.Blue, 5);/设置笔的粗细为,颜色为蓝色Graphicsg = this.CreateGraphics();/画虚线p.DashStyle = DashStyle.Dot;/定义虚线的样式为点g.DrawLine(p, 10, 10, 200, 10);/自定义虚线p.DashPattern = newfloat 2, 1 ;/设置短划线和空白部分的数组g.DrawLine(p, 10, 20, 200, 20);/画箭头,只对不封闭曲线有用p.DashStyle = DashStyle.Solid;/实线p.EndCap = LineCap.ArrowAnchor;/定义线尾的样式为箭头g.DrawLine(p, 10, 30, 200, 30);g.Dispose();p.Dispose();以上代码运行结果:2.接下来我们来看下Brush的使用作用:我们可以用画刷填充各种图形形状,如矩形、椭圆、扇形、多边形和封闭路径等,主要有几种不同类型的画刷:? SolidBrush:画刷最简单的形式,用纯色进行绘制? HatchBrush:类似于 SolidBrush,但是可以利用该类从大量预设的图案中选择绘制时要使用的图案,而不是纯色? TextureBrush:使用纹理(如图像)进行绘制? LinearGradientBrush:使用沿渐变混合的两种颜色进行绘制? PathGradientBrush :基于编程者定义的唯一路径,使用复杂的混合色渐变进行绘制我们这里只是简单介绍使用其中的几种:Graphics g = this.CreateGraphics();Rectangle rect = new Rectangle(10, 10, 50, 50);/定义矩形,参数为起点横纵坐标以及其长和宽/单色填充SolidBrush b1 = new SolidBrush(Color.Blue);/定义单色画刷g.FillRectangle(b1, rect);/填充这个矩形/字符串g.DrawString(字符串, new Font(宋体, 10), b1, new PointF(90, 10);/用图片填充TextureBrush b2 = new TextureBrush(Image.FromFile(e:picture1.jpg);rect.Location = new Point(10, 70);/更改这个矩形的起点坐标rect.Width = 200;/更改这个矩形的宽来rect.Height = 200;/更改这个矩形的高g.FillRectangle(b2, rect);/用渐变色填充rect.Location = new Point(10, 290);LinearGradientBrush b3 = newLinearGradientBrush(rect, Color.Yellow , Color.Black , LinearGradientMode.Horizontal);g.FillRectangle(b3, rect);运行效果图:3.坐标轴变换在winform中的坐标轴和我们平时接触的平面直角坐标轴不同,winform中的坐标轴方向完全相反:窗体的左上角为原点(0,0),水平向左则X增大,垂直下向则Y增大接下来,我们来实际操作下,通过旋转坐标轴的方向来画出不同角度的图案,或通过更改坐标原点的位置来平衡坐标轴的位置.Graphics g = this.CreateGraphics();/单色填充/SolidBrush b1 = new SolidBrush(Color.Blue);/定义单色画刷Pen p = new Pen(Color.Blue,1);/转变坐标轴角度for (int i = 0; i 90; i+)g.RotateTransform(i);/每旋转一度就画一条线g.DrawLine(p, 0, 0, 100, 0);g.ResetTransform();/恢复坐标轴坐标/平移坐标轴g.TranslateTransform(100, 100);g.DrawLine(p, 0, 0, 100, 0);g.ResetTransform();/先平移到指定坐标,然后进行度旋转g.TranslateTransform(100,200);for (int i = 0; i 8; i+)g.RotateTransform(45);g.DrawLine(p, 0, 0, 100, 0);g.Dispose();运行效果图:4.最后我们来看下Graphics这个画板上我们还可以画什么其实我们上面用到的都是在画一些简单的图形,直线,矩形,扇形,圆孤等,我们还可以用它来绘制图片,这可以用它的DrawImage方法.这里我不详细讲解,大家有兴趣可以自己去MSDN了解下.我们后面会讲到的截图就会用到这个方法.感谢大家的支持,这几天从早忙到晚,一个字累呀!现在挺困的,但是又不习惯这么早睡觉,哎还是利用这个时间继续来写第三篇吧.前两篇已经基本向大家介绍了绘图的基本知识.那么,我就用我们上两篇所学的,做几个例子我们先来做一个简单的-仿QQ截图关于这个的例子其实网上已经有这方面的资料了,但是为了文章的完整性,还是觉得有必要讲解我们先来看一下效果:(图1)(图2)接下来看看这是如何做到的.思路:聊天窗体上有一个截图按钮,点击按钮后,程序将整个屏幕画在一个新的全屏窗体上,然后显示这个窗体.因为是全屏的窗体,并且隐藏了菜单栏、工具栏等,所以在我们看来就好像是一个桌面的截图,然后在这个新窗体上画矩形,最后保存矩形中的内容并显示在原来的聊天窗体中.步骤:A.新建一个窗体命名为Catch.然后设置这个窗体的FormBorderStyle为None,WindowState为MaximizedB.我们对代码进行编辑:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;namespace Clientpublic partial class Catch : Formpublic 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.AllScreens0.Bounds.Width, Screen.AllScreens0.Bounds.Height);/新建一个和屏幕大小相同的图片Graphics g = Graphics.FromImage(CatchBmp);g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.AllScreens0.Bounds.Width, Screen.AllScreens0.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画板的程序前几篇我已经向大家介绍了如何使用GDI来绘图,并做了一个截图的实例,这篇我向大家介绍下如何来做一个类似windows画图的工具.个人认为如果想做一个功能强大的绘图工具,那么单纯掌握GDI还远远不够,我的目前也只能做一个比较简单的绘图工具了不足之处,欢迎大家讨论!先来看一下最终效果吧:主要实现功能:画直线,矩形,橡皮,圆形,切换颜色,打开图片,保存图片,清除图片,手动调节画布大小;软件刚启动时,为一张空白画布,我们可以直接在画布上绘图,也可以通过菜单中的“打开”,导入一张图片,然后我们就可以在这张图片上进行绘制。平台:VS2005 WINFORM由于代码过多,在这里只简要介绍下制作步骤,提供大家工程下载1.对整个界面进行布局2.实现绘图工具的功能3.实现颜色拾取的功能,这里我们直接拿上次写的自定义控件来用4.实现菜单功能5.实现手动调节画布大小的功能6.测试实现绘图工具的功能为了让代码藕合度小点,稍许用了些设计模式,因为不是很会,所以代码还是有点乱乱的,绘图工具的这些功能块全部写在了DrawTools这个类里那么在主窗体中,只需要调用这个类来完成绘制就行了,而不需要过多的涉及到具体的绘图代码。绘图工具这个类提供的主要工具就是:铅笔、橡皮、直线、矩形、圆形、实心矩形、实心圆形。关于这些功能块的代码,并不难,只要大家对认真看过前几篇内容,那应该都看得懂。这里有几点要注意:.如何防止记录不必要的绘图过程中的痕迹?这个问题在第三篇中有提到过,大家不妨先去看看那一篇。为了让代码看起来可读性高点,我设置了两个Image变量,finishingImg用来保存绘图过程中的痕迹,orginalImg用来保存已完成的绘图过程和初始时的背景图片。2.这个类如何与主窗体进行通信?当然如果直接将这些功能块写在主窗体中自然没有这个问题。但是那样代码会显得很混杂,如果只是工具代码出现问题就需要改整个项目。我在这里通过定义方法和属性,让主窗体通过给属性赋值将画板画布以及颜色什么的信息传给这个工具类,然后通过调用相应的工具方法来使用这些工具。3.关键属性要想让这些工具能正常使用,必须传递给他以下几样东西:目标画板(也就是picturebox),绘图颜色,原始画布。实现菜单功能这里就需要我们对文件的操作有一点了解,大家可以去查一下相关资料。难点主要就是“打开”这个菜单项的实现我们要实现将打开后的图片在修改后重新保存就必须让文件在打开后就能关闭,否则就会因为文件打开而无法覆盖原文件。就会导致编译时弹出“GDI 一般性错误”。所以根据网上其它朋友的做法就是先将打开的图片通过GDI+将图片画到另一个画布上,然后及时关闭打开的图片和用来绘制该图片的画板。详见/redirect.php?tid=3&goto=lastpostprivate void openPic_Click(object sender, EventArgs e)OpenFileDialog ofd = new OpenFileDialog();/实例化文件打开对话框ofd.Filter = JPG|*.jpg|Bmp|*.bmp|所有文件|*.*;/设置对话框打开文件的括展名if (ofd.ShowDialog() = DialogResult.OK)Bitmap bmpformfile = new Bitmap(ofd.FileName);/获取打开的文件panel2.AutoScrollPosition = new Point(0,0);/将滚动条复位pbImg.Size = bmpformfile.Size;/调整绘图区大小为图片大小reSize.Location = new Point(bmpformfile.Width, bmpformfile.Height);/reSize为我用来实现手动调节画布大小用的/因为我们初始时的空白画布大小有限,打开操作可能引起画板大小改变,所以要将画板重新传入工具类dt.DrawTools_Graphics = pbImg.CreateGraphics();Bitmap bmp = new Bitmap(pbImg.Width, pbImg.Height);Graphics g = Graphics.FromImage(bmp);g.FillRectangle(new SolidBrush(pbImg.BackColor), new Rectangle(0, 0, pbImg.Width, pbImg.Height);/不使用这句话,那么这个bmp的背景就是透明的g.DrawImage(bmpformfile, 0, 0,bmpformfile.Width,bmpformfile.Height);/将图片画到画板上g.Dispose();/释放画板所占资源/不直接使用pbImg.Image = Image.FormFile(ofd.FileName)是因为这样会让图片一直处于打开状态,也就无法保存修改后的图片bmpformfile.Dispose();/释放图片所占资源g = pbImg.CreateGraphics();g.DrawImage(bmp, 0, 0);g.Dispose();dt.OrginalImg = bmp;bmp.Dispose();sFileName = ofd.FileName;/储存打开的图片文件的详细路径,用来稍后能覆盖这个文件ofd.Dispose();清除图像其实就是用白色填充整个画布,其它的都比较简单,这就不具体讲了。实现手动调节画布大小网上有人说使用API,但是个人觉得还是使用其它控件帮忙比较简单,至少我们还看得懂。思路:放置一个picturebox1(尺寸为5*5),将它固定在主画板的右下角,然后改变鼠标进入时的Cursor为箭头形状,设置鼠标按下移动时的事件,让该picturebox1 跟随鼠标移动。当鼠标松开时,将主画板的右下角坐标调整为picturebox1的坐标。下面来看下代码:其中的reSize就是我们用来帮忙的picturebox控件private bool bReSize = false;/是否改变画布大小private voi
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 个人协议用工范文
- 脑梗塞康复护理健康教育
- 2025年事业单位工勤技能-湖南-湖南地质勘查员三级(高级工)历年参考题库典型考点含答案解析
- 2025年事业单位工勤技能-湖北-湖北行政岗位工四级(中级工)历年参考题库含答案解析
- 2025年事业单位工勤技能-湖北-湖北检验员四级(中级工)历年参考题库典型考点含答案解析
- 2025年医药电商平台医药电商保险与合规监管报告
- 2025年事业单位工勤技能-湖北-湖北护理员五级(初级工)历年参考题库含答案解析
- 2025年事业单位工勤技能-湖北-湖北地图绘制员五级(初级工)历年参考题库典型考点含答案解析
- 2025-2030中国素颜霜市场需求状况及销售模式预测分析报告
- 2025年事业单位工勤技能-浙江-浙江药剂员一级(高级技师)历年参考题库含答案解析(5套)
- 2025湖南省低空经济发展集团有限公司及下属子公司招聘7人笔试备考试题及答案解析
- 中医医院创建三甲汇报工作大纲
- 2025年注册会计师(CPA)全国统一考试(税法)历年参考题库含答案详解(5套)
- 卫星互联网基础知识培训课件
- 2025年高考化学四川卷试题答案解读及备考指导(精校打印)
- 2025年押品评估准入考试题库
- 刑法基本原则解读课件
- 2025年药物医疗器械临床试验质量管理规范(GCP)试题(附答案)
- 新疆处方管理办法
- 心肺复苏术课件2024新版
- 水利工程管理单位定岗标准(试点)
评论
0/150
提交评论