C#中在某些控件内实现双缓冲绘图的一些问题
来源:互联网 发布:php加密授权 编辑:程序博客网 时间:2024/04/30 04:13
自己在用到双缓冲绘图时候在网上搜索了很多方法,有直接设置,有自己开辟内存方法。到现在为止,我的理解是,如果你要在一个新窗口中直接绘图的话,可以用直接设置双缓冲的方法来搞定。但如果你要在某个控件(以panel举例)内部绘图,其双缓冲的设置方法最好是在内存当中开辟虚拟内存,在内存中绘制好后再在窗口当中显示出来。道理是这个道理,思路大家都知道,但在实现的时候会遇到一些问题。我将自己的遇到一些问题分享出来,免得大家再走弯路。
先贴上一段代码,新建一个窗体,里面只放进去一个控件panel1。在窗体画图事件里面写绘图代码。
private void Form1_Paint(object sender, PaintEventArgs e) { Bitmap bmp = new Bitmap(panel1.ClientRectangle.Width,panel1.ClientRectangle.Height); Graphics grid = Graphics.FromImage(bmp); int PX = panel1.Location.X;//panel1的X坐标 int PY = panel1.Location.Y;//panel1的Y坐标 Graphics g1 = e.Graphics; Graphics g2 = this.CreateGraphics(); Graphics g3 = e.Graphics; Graphics g4 = this.CreateGraphics(); g1.DrawLine(new Pen(Color.FromArgb(0x00, 0x00, 0xff)), panel1.Location.X, panel1.Location.Y, 0, 0);//蓝色的笔画从窗体左上角到panel的左上角的线 g2.DrawLine(new Pen(Color.FromArgb(0xff, 0x00, 0x00)), 50, 50, 100, 100);//画一段红线 grid.DrawLine(new Pen(Color.FromArgb(0x00, 0xff, 0x00)), 0, 0, panel1.ClientRectangle.Width, panel1.ClientRectangle.Height);//在内存中用绿色的笔画panel的对角线 g3.DrawImage(bmp,PX, PY);在窗体中显示出来 }这段代码是可以实现的,结果如下所示
如果对上面的图做一修改,则结果会发生改变,改动后代码如下,
private void Form1_Paint(object sender, PaintEventArgs e) { Bitmap bmp = new Bitmap(panel1.ClientRectangle.Width,panel1.ClientRectangle.Height); Graphics grid = Graphics.FromImage(bmp); int PX = panel1.Location.X; int PY = panel1.Location.Y; Graphics g1 = e.Graphics; Graphics g2 = this.CreateGraphics(); Graphics g3 = e.Graphics; Graphics g4 = this.CreateGraphics(); g1.DrawLine(new Pen(Color.FromArgb(0x00, 0x00, 0xff)), panel1.Location.X, panel1.Location.Y, 0, 0);//蓝色的笔画从窗体左上角到panel的左上角的线 g2.DrawLine(new Pen(Color.FromArgb(0xff, 0x00, 0x00)), 50, 50, 100, 100);//画一段红线 grid.DrawLine(new Pen(Color.FromArgb(0x00, 0xff, 0x00)), 0, 0, panel1.ClientRectangle.Width, panel1.ClientRectangle.Height);//在内存中用绿色的笔画panel的对角线 g4.DrawImage(bmp, PX, PY);在窗体中显示出来 }
把最后一句的Graphics对象变为g4,结果如下:
双缓冲功能并未实现,这说明Graphics对象的创建方式也会影响到结果的实现。
再对代码修改,将
Graphics g4 = this.CreateGraphics();改为
Graphics g4 = panel1.CreateGraphics();
再来观察结果
绿色的线显示了一段,但并没有按我们的预期显示在panel1内部的=的对角线上,这说明双缓冲功能实现了,但线的坐标不对,要更改坐标。
private void Form1_Paint(object sender, PaintEventArgs e) { Bitmap bmp = new Bitmap(panel1.ClientRectangle.Width,panel1.ClientRectangle.Height); Graphics grid = Graphics.FromImage(bmp); int PX = panel1.Location.X; int PY = panel1.Location.Y; Graphics g1 = e.Graphics; Graphics g2 = this.CreateGraphics(); Graphics g3 = e.Graphics; Graphics g4 = panel1.CreateGraphics(); g1.DrawLine(new Pen(Color.FromArgb(0x00, 0x00, 0xff)), panel1.Location.X, panel1.Location.Y, 0, 0);//蓝色的笔画从窗体左上角到panel的左上角的线 g2.DrawLine(new Pen(Color.FromArgb(0xff, 0x00, 0x00)), 50, 50, 100, 100);//画一段红线 grid.DrawLine(new Pen(Color.FromArgb(0x00, 0xff, 0x00)), 0, 0, panel1.ClientRectangle.Width, panel1.ClientRectangle.Height);//在内存中用绿色的笔画panel的对角线 g4.DrawImage(bmp, 0, 0);在窗体中显示出来 }
总结,容器内部实现双缓冲的关键地方有两个,一个是创建Graphics的方法,一个是DrawLine方法和DrawImage方法的坐标选择要匹配。其中创建图形对象的方法会关联影响到DrawLine方法和DrawImage方法的的坐标选择,其中有一个通常要注意的是,在C#容器内部的线条或者点坐标值通常都是以该容器的左上角为原点的参考值,已经不再以窗体的左上角为原点,其实我们只要分清楚创建的图形对象是在窗体内还是容器内,坐标值就好选择了。另外,使用C#自带的双缓冲类BufferedGraphics实现双缓冲还没搞明白,不乱说了,以免误导像我一样的小白。
- C#中在某些控件内实现双缓冲绘图的一些问题
- C#使用双缓冲解决绘图闪屏的问题
- C# 双缓冲技术实现和高效率的绘图方式
- Delphi中在TForm绘图时使用DoubleBuffered实现双缓冲的副作用
- C# 双缓冲绘图
- C#双缓冲绘图
- C#双缓冲绘图
- C#绘图双缓冲
- 用双缓冲进行绘图可解决在VC中绘图时的闪烁现象[ 转]
- c# 双缓冲绘图GDI
- 在重绘了背景的对话框上用双缓冲绘图的方式绘制picture控件时出现的问题
- 某些情况下闪烁是不能避免的 VC 绘图 双缓冲
- 陈灯WGF双缓冲绘图框架之gdi及gdiplus实现双缓冲时存在的效率问题及解决办法
- 双缓冲绘图技术在Delphi中的实现
- MFC中重写OnPaint实现双缓冲绘图
- vb.net中利用双缓冲绘图技术解决listview加载数据闪烁的问题
- 解决QTP在某些windows应用程序中对edit控件的set失败问题
- 解决QTP在某些windows应用程序中对edit控件的set失败问题
- BZOJ 1001 狼抓兔子(Dijkstra)
- SIFT算法详解
- 【HDOJ】elevator
- PAT乙级.1029. 旧键盘(20)
- Relaxation step(Dijkstra's 最短路径算法)
- C#中在某些控件内实现双缓冲绘图的一些问题
- 把postgresql中的表导入到mysql数据库中的两种方式
- 【Leetcode】116. Populating Next Right Pointers in Each Node
- Android VelocityTracker的使用
- 极客 - 博文5 - 第K值问题实现
- tjut 3572
- 颜色迁移之三——Welsh经典算法
- 简洁的迷你DVDjava代码
- Java 基本类型转换