当前位置: 首页 > 编程日记 > 正文

使用bitblt提高GDI+绘图的效率(转)

最近在做使用GDI+绘制K线界面发现传统的GDI+绘制方式效率比较低,根本无法满足K线界面及时刷新的速度要求。

所以做了个GDI+绘制图形界面的试验,改试验主要在一个600×600的区域内每隔10MS绘制60×60个点,每隔10MS改变其颜色,并记录每次绘制的帧数作为比较GDI+绘图性能的依据(这个界面是摘自网上)

在这里定义个一个timer控件,刷新时间设为10ms,tick事件里写入一下代码

DateTime t = DateTime.Now;

ClientDC = this.CreateGraphics();

if (flag)

{

brush =

brush1;

flag = false;

}

else

{


brush = brush2;

flag = true;

}

for (int j = 0; j < 60; j++)

{

for (int i = 0; i < 60; i++)

{

ClientDC.FillEllipse(brush, i * 10, j * 10, 10, 10);

}

}

DateTime t2 = DateTime.Now;

TimeSpan sp = t2 - t;

float per = 1000 / sp.Milliseconds;

this.label1.Text = "速度:" + per.ToString() + "帧/秒";

这里我没有使用任何的双缓冲技术,直接向显示设备中画入图形,运行程序发现帧数仅为5到7帧,闪烁现象明显。

我简要分析下原因,GDI+画图,是将所有的图形先换入显卡的缓存中看,显卡会每隔一段时间将显存中的内容输出到显示器中,如果在这个显示周期内,无法将所有的图形都放到显存中,就会出现闪烁的现象,那改如何消除闪烁呢答案就是双缓冲。

双缓冲的主要思路是在内存中开辟一块和要进行画图区域大小一致的内存区域,我们一般使用BitMap类来创建这个内存区域,然后将所有的图形先画到这个内存里,画完之后, 在一起放入到显卡显存中,这样就不存在显示的内容会在不同的的显示周期内显示到设备上,也就从消除了闪烁。

双缓冲的主要代码如下:

DateTime t = DateTime.Now;

memDC = Graphics.FromImage(bitmap);

if (flag)

{

brush =

brush1;

flag = false;

}

else

{


brush = brush2;

flag = true;

}

for (int j = 0; j < 60; j++)

{

for (int i = 0; i < 60; i++)

{

memDC.FillEllipse(brush, i * 10, j * 10, 10, 10);

}

}

this.CreateGraphics().DrawImage(bitmap,new PointF(600f,600f)

);

DateTime t2 = DateTime.Now;

TimeSpan sp = t2 - t;

float per = 1000 / sp.Milliseconds;

this.label1.Text = "速度:" + per.ToString() + "帧/秒";

使用双缓冲后运行程序,帧数可达到14到17帧,是不是用双缓冲技术的两倍, memDC = Graphics.FromImage(bitmap); 这里从bitmap创建一个Graphics对象

然后向bitmap中画如图形memDC.FillEllipse(brush, i * 10, j * 10, 10, 10); 最后所有的图形绘制完毕之后,在同一放入显示设备中的显存里this.CreateGraphics().DrawImage(bitmap,new PointF(600f,600f)。

双缓冲技术有效的解决了GDI+绘图时屏幕闪烁的问题,但对于K线图这种图形较多的程序来说,仅仅使用双缓冲技术还是不够的。

DrawImage函数效率是十分低的,这拖慢了内存图形画到显存中进行显示的效率, 解决的办法是引入bitblt来进行从内存中向显存中进行绘图,bitblt是gdi32.dll中的一个函数,使用P/Invoke的方式使托管代码调用非托管代码:

[System.Runtime.InteropServices.DllImport("gdi32.dll")]

private static extern int BitBlt(

IntPtr hdcDest,     // handle to destination DC (device context)

int nXDest,         // x-coord of destination upper-left corner

int nYDest,         // y-coord of destination upper-left corner

int nWidth,         // width of destination rectangle

int nHeight,        // height of destination rectangle

IntPtr hdcSrc,      // handle to source DC

int nXSrc,          // x-coordinate of source upper-left corner

int nYSrc,          // y-coordinate of source upper-left corner

System.Int32 dwRop  // raster operation code

);

修改后的tick事件代码如下:

try

{

DateTime t = DateTime.Now;

offScreenDC = Graphics.FromImage(bitmap);

ClientDC = this.CreateGraphics();

ClientDC.SetClip(new RectangleF(0, 0, 600, 600));

hdc = ClientDC.GetHdc();

memdc = GDI.CreateCompatibleDC(hdc);

GDI.SelectObject(memdc, bitmap.GetHbitmap());

memDC = Graphics.FromHdc(memdc);

if (flag)

{

brush =

brush1;

flag = false;

}

else

{


brush = brush2;

flag = true;

}

for (int j = 0; j < 60; j++)

{

for (int i = 0; i < 60; i++)

{

memDC.FillEllipse(brush, i * 10, j * 10, 10, 10);

}

}

GDI.GDIBitBlt(hdc, 0, 0, 600, 600, memdc, 0, 0, 13369376);

DateTime t2 = DateTime.Now;

TimeSpan sp = t2 - t;

float per = 1000 / sp.Milliseconds;

this.label1.Text = "速度:" + per.ToString() + "帧/秒";

}

finally

{

ClientDC.ReleaseHdc(hdc);

GDI.DeleteDC(memdc);

GDI.DeleteObject(bitmap.GetHbitmap());

//bitmap.Dispose();

}

使用bitblt进行绘图后帧数可达到23至26帧左右。

转载于:https://www.cnblogs.com/carekee/articles/2178308.html

相关文章:

Bruck:一个Web界面布局原型设计框架\n

Bruck是一个面向网页设计师的新型lo-fi原型系统&#xff0c;让设计师可以快速为客户构建响应式且易于访问的布局原型。设计师可以通过组合多达25个Web组件来建立各种布局原型。设计师还可以在Bruck提供的在线Playground中实时可视化组合布局。Bruck可以生成屏幕阅读器可访问和响…

白盒测试方法之语句覆盖测试

语句覆盖测试 概念需求示例测试用例分析设计测试用例脚本语句覆盖情况总结概念 语句覆盖法的基本思想是设计若干测试用例,运行被测程序,使程序中的每个可执行语句至少被执行一次。 需求示例 程序源代码如下: void func(int a, int b, double c

每天学习Linux(3)---pwd命令

Linux中用 pwd 命令来查看”当前工作目录“的完整路径。 简单得说&#xff0c;每当你在终端进行操作时&#xff0c;你都会有一个当前工作目录。 在不太确定当前位置时&#xff0c;就会使用pwd来判定当前目录在文件系统内的确切位置。 1&#xff0e;命令格式&#xff1a; pwd […

恢复Opera11.50地址栏的下拉列表按钮

恢复Opera11.50地址栏的下拉列表按钮 我觉得新版本里取消这个功能很蛋痛. -------------------------------------------------- http://www.stormcn.cn/post/1066.html Opera11.50的地址栏从外观上已经默认取消了下拉列表的点击按钮&#xff0c;就是那个在地址栏最右边的倒三角…

大数据推荐(个性化推荐)

大数据推荐分享。三场讲座系统的讲解了关于基于大数据的个性化推荐的体系和针对模型的探索。作为讲师主讲了关于个性化推荐的一些流程和算法。 转载于:https://www.cnblogs.com/wenBlog/articles/10364415.html

白盒测试方法之条件覆盖测试

条件覆盖测试 概念需求示例测试用例分析设计测试用例脚本条件覆盖情况总结概念 条件覆盖的基本思想是设计若干测试用例,执行被测程序以后,要使每个判断中每个条件的可能取值至少满足一次。 这里要强调的是每个判断中的每一个条件,即使是同一条件,但在不同的判断中也需要分…

第三波精品Android源码袭来!免费下载

今天又汇总了一些源码供大家免费下载学习&#xff01;1.Android实现NewQuickAction快捷菜单NewQuickAction能根据点击事件发生的坐标来显示一个快捷菜单&#xff0c;比如点击位置在靠近底部&#xff0c;则弹出的菜单出现在点击位置的下面&#xff0c;反之&#xff0c;则出现在上…

记一次数据库崩溃的恢复

NEC集群&#xff0c;其中db-2操作系统出现异常&#xff0c;无法点击操作。重启同步主备数据库后&#xff0c;发现数据库出现异常&#xff0c;客户端无法连接&#xff0c;报错&#xff1a;ORA-01033、ORA-00600等。 经分析&#xff0c;是由于操作系统出现异常后强制重启导致数据…

javascript:为string类添加三个成员,实现去左,右,及所有空格

<script language"JavaScript"> //此处为string类添加三个成员 String.prototype.Trim function(){ return Trim(this);} String.prototype.LTrim function(){return LTrim(this);} String.prototype.RTrim function(){return RTrim(this);} //…

MongoDB基本使用

成功启动MongoDB后&#xff0c;再打开一个命令行窗口输入mongo&#xff0c;就可以进行数据库的一些操作。 输入help可以看到基本操作命令&#xff1a; show dbs:显示数据库列表 show collections&#xff1a;显示当前数据库中的集合&#xff08;类似关系数据库中的表&#xff0…

还是这个序列化的解释比较好懂

序列化&#xff08;Serialization&#xff09;是.NET平台最酷的特性之一。 1、为什么要序列化&#xff1a; 首先你应该明白系列化的目的就不难理解他了。系列化的目的就是能在网络上传输对象&#xff0c;否则就无法实现面向对象的分布式计算。比如你的客户端要调用服务器上的一…

InfoQ趋势报告:架构和设计领域技术演变详解

本文概述了我们对当前“架构和设计”领域的看法&#xff0c;这个领域侧重于基础设施模式、技术框架模式的实现&#xff0c;以及软件架构师必须掌握的设计流程和技能。关键要点&#xff1a; 我们看到了“演化式架构”设计需求的增长&#xff0c;这种架构建立在可替换性设计和关注…

白盒测试之基本路径覆盖测试

基本路径覆盖测试 概念独立路径测试用例分析设计自己再试试总结概念 要学习基本路径测试前还需要弄清楚一个概念独立路径。 独立路径是指该路径至少引入一系列新的处理语句或条件的路径。在流程图中从程序入口出发,一条边一条边地往下走,一直走到程序的一个出口,这些边构成…

hdu3321

Problem Description Professor Brute is not good at algorithm design. Once he was asked to solve a path finding problem. He worked on it for several days and finally came up with the following algorithm: Any fool but Brute knows that the function “funny” …

[leedcode 118] Pascal's Triangle

Given numRows, generate the first numRows of Pascals triangle. For example, given numRows 5,Return [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1] ] public class Solution {public List<List<Integer>> generate(int numRows) {//杨辉三角形&#xff0c;把每…

bzoj 4025 二分图——线段树分治+LCT

题目&#xff1a;https://www.lydsy.com/JudgeOnline/problem.php?id4025 线段树分治&#xff0c;用 LCT 维护链的长度即可。不过很慢。 正常&#xff08;更快&#xff09;的方法应该是线段树分治并查集&#xff08;按秩合并&#xff0c;链长可以暴力爬&#xff09;或者 LCT 维…

黑盒测试之功能分解法

功能分解法前言概念需求示例测试用例分析设计总结前言 首先和各位道个歉&#xff0c;最近事情比较多&#xff0c;本来计划的一周一更推迟了这么久。今天咱们继续&#xff0c;开始黑盒测试方法部分的分享。 概念 在学习软件测试的时候经常听到功能分解法&#xff0c;很多人项…

java中Class.forName与new

一、使用Class.forName 1、装载类 Class clazz Class.forName("xx.xx.xx"); 2、初始化对象 clazz.newInstance() 二、使用 new new Object(); 使用Class.forName的好处&#xff0c; 比如加载数据库驱动&#xff0c;若更换数据库&#xff0c;则需要更换驱动。 如果使…

UVA 10041 Vito's Family

UVA_10041这个题目是一个贪心的题目。如果设按升序排列的si的数组为s[]&#xff0c;那么Vito的位置一定为s[(r-1)/2]。对于这一点&#xff0c;我们分两种情况进行讨论&#xff1a;①如果si的数量为奇数&#xff0c;那么Vito的位置一定取数组s[]中间的那个值s[(r-1)/2]。因为如果…

数据结构杂题集

Codechef SD ER • 给出一棵树&#xff0c;维护点集 ?&#xff08;加点删点&#xff09; • 如果 ? 的大小是偶数&#xff0c;输出&#xff1a;如果将 ? 中的点两两连上边权为树上距离的边&#xff0c;那么 ? 里的最小权完美匹配是多少• ?, ? ≤ 10^6 考虑边的贡献 交叉…

黑盒测试方法之等价类划分法

等价类划分法 概念需求示例测试用例分析设计总结概念 等价类是指某个输入域的子集,在该子集中每个输入数据的作用是等效的,也就是该子集中每个输入数据的揭错概率是一样的。等价类分为有效等价类和无效等价类。 等价类划分法是将输入数据分成若干个子集,从每个子集选取一个…

JSEL 表达式

JSTL标签库的使用是为类弥补html表的不足&#xff0c;规范自定义标签的使用而诞生的。在告别modle1模式开发应用程序后&#xff0c;人们开始注重软件的分层设计&#xff0c;不希望在jsp页面中出现java逻辑代码&#xff0c;同时也由于自定义标签的开发难度较大和不利于技术标准化…

JavaEE程序员必读图书大推荐 .

下面是我根据多年的阅读和实践经验&#xff0c;给您推荐的一些图书&#xff1a; 第一部分&#xff1a; Java语言篇 1 《Java编程规范》 星级&#xff1a; 适合对象&#xff1a;初级&#xff0c;中级 介绍&#xff1a;作者James Gosling&#xff08;Java之父&#xff09;&#x…

10 个深恶痛绝的 Java 异常。。

异常是 Java 程序中经常遇到的问题&#xff0c;我想每一个 Java 程序员都讨厌异常&#xff0c;一 个异常就是一个 BUG&#xff0c;就要花很多时间来定位异常问题。 什么是异常及异常的分类请看这篇文章&#xff1a;一张图搞清楚 Java 异常机制。今天&#xff0c;栈长来列一下 J…

黑盒测试方法之边界值分析法

边界值分析法 概念需求示例1测试用例分析设计1需求示例2测试用例分析设计2总结概念 很多错误发生在输入或输出范围的边界上,因此针对各种边界情况设置测试用例,可以更有效地发现缺陷。 边界值分析法测试用例设计方法:1)确定边界情况(输入或输出等价类的边界);2)选取正…

leetcode381. Insert Delete GetRandom O(1) - Duplicates allowed

题目要求 Design a data structure that supports all following operations in average O(1) time.Note: Duplicate elements are allowed. insert(val): Inserts an item val to the collection. remove(val): Removes an item val from the collection if present. getRando…

js 判断 是否为android

引用&#xff1a;http://www.oschina.net/code/snippet_163910_6094 [代码] JavaScript判断方法 view source print?1if(navigator.userAgent.match(/Android/i)) {2 // Do something!3 // Redirect to Android-site?4 window.location http://android.davidwalsh.nam…

B - Networking - poj 1287

有一些地方需要铺盖电缆&#xff0c;这些地方两点间的路可能不止一条&#xff0c;需要求出来至少需要多少电缆才能让所有的点都连接起来&#xff0c;当然&#xff0c;间接连接也算。/#include<iostream>#include<cstring>#include<cstdio>#include<queue&…

因果图方法中的基本符号

因果图方法中的基本符号 前言基本符号1、恒等2、非3、或4、与5、互斥6、包含7、唯一8、要求9、屏蔽总结前言 经过了春节假期,我们重新回到工作学习中。在学习因果图法前首先要学习因果图方法中的基本符号,今天我们就先解决这些基本符合。 基本符号 1、恒等 恒等:表示原因与…

BZOJ 2190: [SDOI2008]仪仗队( 欧拉函数 )

假设C君为(0, 0), 则右上方为(n - 1, n - 1). 一个点(x, y) 能被看到的前提是gcd(x, y) 1, 所以 answer ∑ phi(i) * 2 2 - 1 ∑phi(i) * 2 1 ( 1 < i < n ). 2是因为(1, 0), (0, 1) 两个点, -1是因为(1, 1)重复计算了--------------------------------------------…