C#怎么把线c 绘制线段 颜色到缓存当中

3109人阅读
C#绘图双缓冲
C#双缓冲解释:
简单说就是当我们在进行画图操作时,系统并不是直接把内容呈现到屏幕上,而是先在内存中保存,然后一次性把结果输出来,如果没用双缓冲的话,你会发现在画图过程中屏幕会闪的很厉害,因为后台一直在刷新,而如果等用户画完之后再输出就不会出现这种情况,具体的做法,其实也就是先创建一个位图对象,然后把内容保存在里面,最后把图呈现出来。
GDI+的双缓冲问题
一直以来的误区:.net1.1 和 .net 2.0 在处理控件双缓冲上是有区别的。
.net 1.1 中,使用:this.SetStyle(ControlStyles.DoubleBuffer, true);&
.net 2.0中,使用:this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
导致画面闪烁的关键原因分析:
&&&&& 一、绘制窗口由于大小位置状态改变进行重绘操作时
&&&& 绘图窗口内容或大小每改变一次,都要调用Paint事件进行重绘操作,该操作会使画面重新刷新一次以维持窗口正常显示。刷新过程中会导致所有图元重新绘制,而各个图元的重绘操作并不会导致Paint事件发生,因此窗口的每一次刷新只会调用Paint事件一次。窗口刷新一次的过程中,每一个图元的重绘都会立即显示到窗口,因此整个窗口中,只要是图元所在的位置,都在刷新,而刷新的时间是有差别的,闪烁现象自然会出现。
&&&& 所以说,此时导致窗口闪烁现象的关键因素并不在于Paint事件调用的次数多少,而在于各个图元的重绘。
&&&& 根据以上分析可知,当图元数目不多时,窗口刷新的位置也不多,窗口闪烁效果并不严重;当图元数目较多时,绘图窗口进行重绘的图元数量增加,绘图窗口每一次刷新都会导致较多的图元重新绘制,窗口的较多位置都在刷新,闪烁现象自然就会越来越严重。特别是图元比较大绘制时间比较长时,闪烁问题会更加严重,因为时间延迟会更长。
&&&& 解决上述问题的关键在于:窗口刷新一次的过程中,让所有图元同时显示到窗口。
&&&&& 二、进行鼠标跟踪绘制操作或者对图元进行变形操作时
&&&& 当进行鼠标跟踪绘制操作或者对图元进行变形操作时,Paint事件会频繁发生,这会使窗口的刷新次数大大增加。虽然窗口刷新一次的过程中所有图元同时显示到窗口,但也会有时间延迟,因为此时窗口刷新的时间间隔远小于图元每一次显示到窗口所用的时间。因此闪烁现象并不能完全消除!
&&&& 所以说,此时导致窗口闪烁现象的关键因素在于Paint事件发生的次数多少。
&&&&&解决此问题的关键在于:设置窗体或控件的几个关键属性。
使用双缓冲
解决双缓冲的关键技术:
1、设置显示图元控件的几个属性:& 必须要设置,否则效果不是很明显!
this.SetStyle(ControlStyles.OptimizedDoubleBuffer |   
&&&&&&&&&&&&&&&&&&& ControlStyles.ResizeRedraw |
&&&&&&&&&&&&&&&&&&& ControlStyles.AllPaintingInWmPaint, true);
2、窗口刷新一次的过程中,让所有图元同时显示到窗口。
&&& 可以通过以下几种方式实现,这几种方式都涉及到Graphics对象的创建方式。
1、& 利用默认双缓冲
(1)在应用程序中使用双缓冲的最简便的方法是使用 .NET Framework 为窗体和控件提供的默认双缓冲。通过将 DoubleBuffered 属性设置为 true。
&&&&& this.DoubleBuffered=
(2)使用 SetStyle 方法可以为 Windows 窗体和所创作的 Windows 控件启用默认双缓冲。
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
2、& 手工设置双缓冲
.netframework提供了一个类BufferedGraphicsContext负责单独分配和管理图形缓冲区。每个应用程序域都有自己的默认 BufferedGraphicsContext 实例来管理此应用程序的所有默认双缓冲。大多数情况下,每个应用程序只有一个应用程序域,所以每个应用程序通常只有一个默认 BufferedGraphicsContext。默认 BufferedGraphicsContext 实例由 BufferedGraphicsManager 类管理。通过管理BufferedGraphicsContext实现双缓冲的步骤如下:
(1)获得对 BufferedGraphicsContext 类的实例的引用。
(2)通过调用 BufferedGraphicsContext.Allocate 方法创建 BufferedGraphics 类的实例。
(3)通过设置 BufferedGraphics.Graphics 属性将图形绘制到图形缓冲区。
(4)当完成所有图形缓冲区中的绘制操作时,可调用 BufferedGraphics.Render 方法将缓冲区的内容呈现到与该缓冲区关联的绘图图面或者指定的绘图图面。
(5)完成呈现图形之后,对 BufferedGraphics 实例调用释放系统资源的 Dispose 方法。
完整的例子,在一个400*400的矩形框内绘制10000个随机生成的小圆。
&&&&&&&&&& BufferedGraphicsContext current = BufferedGraphicsManager.C //(1)
&&&&&&&&&& BufferedG
&&&&&&&&&& bg = current.Allocate(this.CreateGraphics(),this.DisplayRectangle); //(2)
&&&&&&&&&& Graphics g = bg.G//(3)
&&&&&&&&&& //随机 宽400 高400
&&&&&&&&&& System.Random rnd = new Random();
&&&&&&&&&& int x,y,w,h,r,i;
&&&&&&&&&& for (i = 0; i & 10000; i++)
&&&&&&&&&& {
&&&&&&&&&&&&&& x = rnd.Next(400);
&&&&&&&&&&&&&& y = rnd.Next(400);
&&&&&&&&&&&&&& r = rnd.Next(20);
&&&&&&&&&&&&&& w = rnd.Next(10);
&&&&&&&&&&&&&& h = rnd.Next(10);
&&&&&&&&&&&&&& g.DrawEllipse(Pens.Blue, x, y, w, h);
&&&&&&&&&& }
&&&&&&&&&& bg.Render();//(4)
&&&&&&&&&& //bg.Render(this.CreateGraphics());
&&&&&&&&&& bg.Dispose();//(5)
3、&& 自己开辟一个缓冲区(如一个不显示的Bitmap对象),在其中绘制完成后,再一次性显示。
完整代码如下:
&&&&&&&&&& Bitmap bt = new Bitmap(400, 400);
&&&&&&&&&& Graphics bg = Graphics.FromImage(bt);
&&&&&&&&&& System.Random rnd = new Random();
&&&&&&&&&& int x, y, w, h, r,
&&&&&&&&&& for (i = 0; i & 10000; i++)
&&&&&&&&&& {
&&&&&&&&&&&&&& x = rnd.Next(400);
&&&&&&&&&&&&&& y = rnd.Next(400);
&&&&&&&&&&&&&& r = rnd.Next(20);
&&&&&&&&&&&&&& w = rnd.Next(10);
&&&&&&&&&&&&&& h = rnd.Next(10);
&&&&&&&&&&&&&& bg.DrawEllipse(Pens.Blue, x, y, w, h);
&&&&&&&&&& }
&&&&&&&&&& this.CreateGraphics().DrawImage(bt, new Point(0, 0));&
另外一个例子,差不多
Graphics对象的创建方式:
&a、在内存上创建一块和显示控件相同大小的画布,在这块画布上创建Graphics对象。
&&&& 接着所有的图元都在这块画布上绘制,绘制完成以后再使用该画布覆盖显示控件的背景,从而达到“显示一次仅刷新一次”的效果!
  实现代码(在OnPaint方法中):
  Rectangle rect = e.ClipR
  Bitmap bufferimage = new Bitmap(this.Width, this.Height);
&&&&&Graphics g = Graphics.FromImage(bufferimage);
  g.Clear(this.BackColor);
&&&&&g.SmoothingMode = SmoothingMode.HighQ //高质量
&&&&&g.PixelOffsetMode = PixelOffsetMode.HighQ //高像素偏移质量
  foreach (IShape drawobject in doc.drawObjectList)
&&&&&&&&&&&&&&&&&if (rect.IntersectsWith(drawobject.Rect))
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& drawobject.Draw(g);
&&&&&&&&&&&&&&&&&&& if (drawobject.TrackerState == config.Module.Core.TrackerState.Selected
&&&&&&&&&&&&&&&&&&&&&&& && this.CurrentOperator == Enum.Operator.Transfrom)//仅当编辑节点操作时显示图元热点
&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&& drawobject.DrawTracker(g);
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& }
    using (Graphics tg = e.Graphics)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& tg.DrawImage(bufferimage, 0, 0);  //把画布贴到画面上
&&&&&&&&&&& }
&b、直接在内存上创建Graphics对象:
     Rectangle rect = e.ClipR
     BufferedGraphicsContext currentContext = BufferedGraphicsManager.C
&&&&&&&&&&& BufferedGraphics myBuffer = currentContext.Allocate(e.Graphics, e.ClipRectangle);
&&&&&&&&&&& Graphics g = myBuffer.G
&&&&&&&&&&& g.SmoothingMode = SmoothingMode.HighQ
&&&&&&&&&&& g.PixelOffsetMode = PixelOffsetMode.HighS
&&&&&&&&&&& g.Clear(this.BackColor);
&&&&&&&&&&& foreach (IShape drawobject in doc.drawObjectList)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& if (rect.IntersectsWith(drawobject.Rect))
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& drawobject.Draw(g);
&&&&&&&&&&&&&&&&&&& if (drawobject.TrackerState == config.Module.Core.TrackerState.Selected
&&&&&&&&&&&&&&&&&&&&&&& && this.CurrentOperator == Enum.Operator.Transfrom)//仅当编辑节点操作时显示图元热点
&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&& drawobject.DrawTracker(g);
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
    myBuffer.Render(e.Graphics);
&&&&&&&&&&&g.Dispose();
&&&&&&&&&&&myBuffer.Dispose();//释放资源
至此,双缓冲问题解决,两种方式的实现效果都一样,但最后一种方式的占有的内存很少,不会出现内存泄露!
接下来是对acdsee拖动图片效果的实现。开始不懂双缓冲,以为双缓冲可以解决这个问题,结果发现使用了双缓冲没啥效果,请教了高人,然后修改了些代码,完成这个效果。
图片是在pictureBox1里。
&&&&&&& Bitmap currentM
&&&&&&& bool first =
&&&&&&& private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
&&&&&&&&&&& if (zoom == 0)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& if (e.Button == MouseButtons.Left) //dragging
&&&&&&&&&&&&&&&&&&& mousedrag = e.L
&&&&&&&&&&&&&&& Image myImage = myMap.GetMap();
&&&&&&&&&&&&&&& currentMap = new Bitmap(myImage);
&&&&&&&&&&&&&&& first =
&&&&&&&&&&& }&&&
&&&&&&& private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
&&&&&&&&&&& if (zoom == 0&&!first)
&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& Image img = new Bitmap(Size.Width, Size.Height);
&&&&&&&&&&&&&&&&&&& Graphics g = Graphics.FromImage(img);
&&&&&&&&&&&&&&&&&&& g.Clear(Color.Transparent);//图片移动后显示的底色
&&&&&&&&&&&&&&&&&&& g.SmoothingMode = SmoothingMode.HighQ //高质量
&&&&&&&&&&&&&&&&&&& g.PixelOffsetMode = PixelOffsetMode.HighQ //高像素偏移质量
&&&&&&&&&&&&&&&&&&& g.DrawImageUnscaled(currentMap, new System.Drawing.Point(e.Location.X - mousedrag.X, e.Location.Y - mousedrag.Y));//在g中移动图片,原图在(0,0)画的,所以直接用new System.Drawing.Point(e.Location.X - mousedrag.X, e.Location.Y - mousedrag.Y)就好。
&&&&&&&&&&&&&&&&&&& g.Dispose();
&&&&&&&&&&&&&&&&&&& pictureBox1.Image =//img是在鼠标这个位置时生成被移动后的暂时的图片
&&&&&&&&&&& }
&&&&&&& private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
&&&&&&&&&&& if (zoom == 0)
&&&&&&&&&&& {
&&&&&&&&&&&&&&& System.Drawing.Point pnt = new System.Drawing.Point(Width / 2 + (mousedrag.X - e.Location.X),
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& Height / 2 + (mousedrag.Y - e.Location.Y));
&&&&&&&&&&&&&&&& myMap.Center = myMap.ImageToWorld(pnt);
&&&&&&&&&&&&&&& pictureBox1.Image = myMap.GetMap();
&&&&&&&&&&&&&&& first =
&&&&&&&&&&& }
说说思路,在鼠标点下时创建一个bitmap,currentMap,用它来存放当前图像。鼠标移动时,根据鼠标位置画图,最后,鼠标up时,重新画图。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:216612次
积分:2853
积分:2853
排名:第9069名
原创:53篇
转载:104篇
评论:20条
(1)(1)(1)(1)(1)(1)(2)(2)(2)(6)(4)(2)(1)(3)(6)(6)(8)(6)(1)(2)(2)(3)(7)(19)(10)(1)(1)(6)(2)(7)(4)(18)(21)C#中利用Cach建立缓存机制
时间: &&来源:
在web项目开发当,我们恰当的建立缓存机制可以加快用户对于动态网站的访问速度。官网技术人员在多个项目中就为客户在C#中利用Cach建立缓存机制,使客户的网站在用户访问时速度大大加快。以下提供的代码是远程调用webserver,不仅使用了Cach建立缓存机制还在本地建立了一个xml文件以存放远程调用webserver,使程序与远程webserver断开连接时可以直接调用本地文件。
&&&&&&&&&&& //缓存机制
&&&&&&&&&&& GetRegistInfoService instance = new GetRegistInfoService();//远程调用webserver
&&&&&&&&&&& instance.Timeout = 10000;
&&&&&&&&&&& string strweb = &&;
&&&&&&&&&&& object objModel = Cach.GetCache(Cach.cacheOutDeptList);//从缓存中获取
&&&&&&&&&&& if (objModel == null)//缓存里没有
&&&&&&&&&&& {
&&&&&&&&&&&&&&& string strserverxml = &&Request&&UserID&000000&/UserID&&UserPWD&000000&/UserPWD&&HospitalID&1&/HospitalID&&ParentDeptID&&/ParentDeptID&&GetType&2&/GetType&&/Request&&;//远程调用webserver需传的参
&&&&&&&&&&&&&&& try
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& strweb = instance.GetOutDeptList(strserverxml);
&&&&&&&&&&&&&&&&&&& Uitls.Insfile(strweb, Cach.cacheOutDeptList, &Cachexml/&);//远程webserver返回的数据存入本地文件
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& catch
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& strweb = handlexml.GetXml(Cach.cacheOutDeptList, &Cachexml/&);//获取本地文件数据
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& objModel =//赋值给cache
&&&&&&&&&&&&&&& if (objModel != null)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&& int CacheTime = Cach.cacheOutDeptL//缓存时间
&&&&&&&&&&&&&&&&&&& Cach.SetCache(Cach.cacheOutDeptList, objModel, DateTime.Now.AddSeconds(CacheTime), TimeSpan.Zero);//写入缓存
&&&&&&&&&&&&&&& }
&&&&&&&&&&& }
&&&&&&&&&&& else
&&&&&&&&&&& {
&&&&&&&&&&&&&&& strweb = objModel.ToString().Trim();
&&&&&&&&&&& }
项目中调用webserver使用本机制是大有好处的,中应用比较多,而且这样就算不同的用户访问网站只要访问的数据是同样的,就可以直接调用cache数据而无需与远程数据库连接,从而大大减少了用户等待时间。这就是在项目C#中利用Cach建立缓存机制的好处。
点击次数:C#怎样做一个转圈圈缓冲效果_百度知道C#选择画好的其中一根线并删除的问题!帮顶给分!谢谢!-.NET技术/C#-c/c++-电脑编程网C#选择画好的其中一根线并删除的问题!帮顶给分!谢谢!-.NET技术/C#作者:rizher 和相关&&C# winform中用DrawLine画了好几条线,怎么选取画好的其中一根线然后按del键删除它,谢谢------回答---------------其他回答(2分)---------不太明白你这啥意思,但是帮忙顶了------其他回答(2分)---------给画好的每根线做个标记。------其他回答(8分)---------C# code
using S
using System.Collections.G
ponentM
using System.D
using System.D
using System.T
using System.Windows.F
namespace WindowsApplication11
{
class Line
public Point P1, P2;
public Color C
public Line(Point P1, Point P2, Color Color)
this.P1 = P1;
this.P2 = P2;
this.Color = C
public partial class Form1 : Form
Bitmap OrgBmp = new Bitmap(500, 500);
List&Line& Lines = new List&Line&();
PictureBox PB = new PictureBox();
Line SelectedLine =
public Form1()
InitializeComponent();
this.Controls.Clear();
this.AutoSize =
this.KeyPreview =
this.KeyDown += new KeyEventHandler(Form1_KeyDown);
PB.Size = OrgBmp.S
PB.Parent =
PB.Image = OrgB
Lines.Add(new Line(new Point(0, 0), new Point(100, 100), Color.Red));
Lines.Add(new Line(new Point(20, 30), new Point(450, 200), Color.Green));
Lines.Add(new Line(new Point(300, 400), new Point(60, 300), Color.Blue));
RefreshImage();
SelectedLine = Lines[1]; // 删除绿线
void Form1_KeyDown(object sender, KeyEventArgs e)
if (e.KeyCode == Keys.Delete && SelectedLine != null)
Lines.Remove(SelectedLine);
RefreshImage();
void RefreshImage()
Bitmap CacheBmp = new Bitmap(OrgBmp);
Graphics G = Graphics.FromImage(CacheBmp);
foreach (Line L in Lines)
G.DrawLine(new Pen(new SolidBrush(L.Color)), L.P1, L.P2);
G.Dispose();
PB.Image = CacheB
}
}
------其他回答(8分)---------其实你最主要的问题是pick问题(就是是不是选中的问题)就是将先选中的问题楼上的已经把选中的给删除了,你可以写一个pick()方法解决如果有疑问可以加qq
注明: 图形------其他回答(5分)---------如果你是在鼠标单击等事件里画图,那是没法选择删除的。正确方法应该是楼上代码所说,将所有的线存放在集合里,鼠标划线的时候加入集合,选择的时候在集合里查找那条线符合单击的点的位置,如何在集合里删除这个线,在重绘事件里将集合的线全部显示就可以了不过如果你是按这个方法做的话,我想应该也不会问这个问题了,应该是直接在单击事件里绘图了吧,那要改改代码了------其他回答(2分)---------我觉得是……把不删除的线再重新画一遍……------其他回答(2分)---------不甚理解,学习了~------其他回答(2分)---------------其他回答(9分)---------blog.csdn.net/dunao参照V1.0.0.5的那版本的(VS2008开发)------其他回答(2分)---------至于选中问题,比较麻烦,如果要鼠标直接可选中,可以试试套用直线的两点式公式,不过公式要变换形式为(y-y1)/(y2-y1)-(x-x1)/(x2-x1)&误差值的形式,不过细节处理起来还是蛮麻烦的------其他回答(2分)---------四楼正解。 。
。。 ------其他回答(2分)---------不太了解------其他回答(2分)---------重绘???
Up------其他回答(2分)---------学习下~~~相关资料:|||||||C#选择画好的其中一根线并删除的问题!帮顶给分!谢谢!-.NET技术/C#来源网络,如有侵权请告知,即处理!编程Tags:                &                    

我要回帖

更多关于 c 绘制曲线 的文章

 

随机推荐