绘制快速走动的仪表时,怎样降低CPU占用率??有好方法的进来讨论一下 比如绘制一个时钟,20毫秒或者40毫秒走动一次(精密控制就要求这个速度),我用GDI+就绘制一个都占%7以上,我看见人家也是用GDI+绘制的,占用很少,而且我的是一个屏幕都全部要用来显示仪表的,这样就有N个仪表同时在走动,占用CPU相当高,难以忍受,不知道有什么妙方(不要跟我说什么DX)。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 在windows下 做几十毫秒的时间,控制估计还是比较难哦! 应该是你在绘制的时候处理的不好。建议:时间效率和空间效率是相矛盾的。游戏的性能高,除了游戏使用了一些汇编级优化,更重要的是,游戏使用了大量的缓存来提高执行的速度。所以,你也应该使用GDI建立大量的缓存,比如HDC/CDC 变量/对象,仅作BitBlt操作减少计算量大的操作。总之是要优化,优化,再优化如果确实要高性能,还是建议使用DX。要不,摄像头的驱动都使用 Direct Show呢! 可以像Windows处理WM_MOUSEMOVE一样去处理。 我就在一个自定义函数void DrawMeter()里调用几个GDI+函数(还没没把图象画到屏幕呢),然后按20毫秒一次的频率调用DrawMeter()函数,运行9个实例,晕,CPU 100%了我已经使用缓存了,比如表盘是基本固定的,那我就在一个InitDial()函数先把表盘画到一个Bitmap中并保存起来,然后画指针时,把这个Bitmap指针克隆过来就可以,但指针是走动的不能缓存啊,每次都得重新画一次。http://www.vckbase.com/document/viewdoc/?id=1727这个作者做的还可以,效率也符合我的要求,但源码.... 我就在一个自定义函数void DrawMeter()里调用几个GDI+函数(还没没把图象画到屏幕呢),然后按20毫秒一次的频率调用DrawMeter()函数,运行9个实例,晕,CPU 100%了如何实现20毫秒频率调用是关键,楼主不说清楚怎么能解决呢~~ Timer?新线程?把具体的调用代码贴出来 是响应WM_TIMER消息,然后刷新控件客户区域,我只在控件的OnPaint函数中把缓存在内存中的表盘克隆一份过来,然后在上面画走动指针,最后拷贝到屏幕,当然SetTimer定时20毫秒不是很准确啦,但已经符合要求了,等我整理好了,再拿出来给大家讨论应该在那方面改进。还有有什么好的GDI+方面的书籍或者资料介绍下,.cn一度一枚指针,做上360幅这样的图,初始化的时候全部读到内存里,用的时候,合并出来。-----------------------这位兄弟的做法不符合要求,我画时钟那不是要缓存360个Bitmap*了???我要是画其他的呢?比如画温度计,那你想要缓存多少Bitmap*??根本不可预知... 参见WINDOWS程序设计“多任务和多线程”章节 CPU占用高很大程度是你的循环太占用时间了. 如果只是重画指针应该不会占用多少时间,lz在重画的时候还做了什么?DrawMeter 在什么地方使用? 还有lz在重画的时候用到 gdi+ 的函数吗? 楼上的大哥,我所作的都是用GDI+函数实现的呀,这个作者http://www.vckbase.com/document/viewdoc/?id=1727也是用GDI+实现的,效率还可以啊,可见应该不是GDI+函数的问题,等我整理好了拿来大家看看怎么改进.. 我的控件OnPaint函数里是这样的:void CClockMeter::OnPaint(){ CPaintDC dc(this); Graphics graphics(dc.GetSafeHdc()); // 构造memGrph对象(传设备描述表做为参数) CRect ClienRect; GetClientRect(&ClienRect); if(!ClienRect.EqualRect(&m_rectCtrl)) // 如果将控件位置改变了 { InitDial(); // 重新初始化表盘 } // 把表盘克隆过来 Bitmap *pClonebmp = m_pDialMemBmp->Clone(0,0,m_pDialMemBmp->GetWidth(),m_pDialMemBmp->GetHeight(),PixelFormatDontCare); ASSERT(pClonebmp!=NULL); Graphics memGrph(pClonebmp); // 先画到内存图象中 memGrph.SetSmoothingMode(SmoothingModeAntiAlias); // GDI+反锯齿 // 画指针 DrawNeedle(memGrph); graphics.SetInterpolationMode(InterpolationModeHighQuality); // 保证不拉伸位图 CachedBitmap cachebmp(pClonebmp,&graphics); // 用cache位图显示速度快 graphics.DrawCachedBitmap(&cachebmp,m_rectCtrl.left,m_rectCtrl.top); delete pClonebmp;}DrawNeedle函数是这样的:void CClockMeter::DrawNeedle(Graphics &memGrph,DWORD dwNeedleStyle){ // 画指针 // 指针顶端坐标 if(dwNeedleStyle==0) { int x0,y0,x1,y1; x0 = m_ptCenter.x -(m_nOutsideRadius - m_nDitchWidth-m_PenWidthFrame)*cos(M_PI*m_dCurrentValue/360.0); y0 = m_ptCenter.y -(m_nOutsideRadius - m_nDitchWidth-m_PenWidthFrame)*sin(M_PI*m_dCurrentValue/360.0); /*int nAcrossdegree = 40; // 指针两边的跨度(0~360) insiderect.GetSize(&sz); insideRadius = sz.Width/2;*/ // 指针底端坐标 Pen NeedlePen(m_colorNeedle,2); x1 = m_ptCenter.x - (m_nInsideRadius+10)*cos(M_PI*(m_dCurrentValue+180)/360.0); y1 = m_ptCenter.y - (m_nInsideRadius+10)*sin(M_PI*(m_dCurrentValue+180)/360.0); memGrph.DrawLine(&NeedlePen,x0,y0,x1,y1); }}我现在的表盘相对画得有点复杂后,SetTimer(1,50,NULL);发现开一个实例CPU就百分之30左右了,晕啊 http://www.vckbase.com/document/viewdoc/?id=1727 可没有说在话的时候也用到GDI+吧。还是用 GDI 来画指针吧,快很多的。 MFC如何读取txt文件中数据? 100分求助,请问怎么在对话框中加一个进度条,显示数据接收进度 点阵字体的放大缩小 求计算机专业的本科学士学位的教学课程计划,详细一点的 我想自学 谢谢 如何向窗口发送“Ctrl+V”?在线等! 读二进制文件碰到的疑惑,高手帮帮我吧 qq音乐和wps那种使用脚本的界面是如何实现的呢 *nix平台的进程加载器是ld,win平台的加载器是什么? 请问如何将jpeg图象显示在主对话框中? 各位大哥帮帮忙!关于编译Windows高级编程指南的范例的问题?????? Activex在网页中自动下载,并且安装! everyone都有完全控制权限
建议:时间效率和空间效率是相矛盾的。游戏的性能高,除了游戏使用了一些汇编级优化,更重要的是,游戏使用了大量的缓存来提高执行的速度。
所以,你也应该使用GDI建立大量的缓存,比如HDC/CDC 变量/对象,仅作BitBlt操作减少计算量大的操作。总之是要优化,优化,再优化如果确实要高性能,还是建议使用DX。要不,摄像头的驱动都使用 Direct Show呢!
这个作者做的还可以,效率也符合我的要求,但源码....
新线程?
把具体的调用代码贴出来
-----------------------
这位兄弟的做法不符合要求,我画时钟那不是要缓存360个Bitmap*了???我要是画其他的呢?比如画温度计,那你想要缓存多少Bitmap*??根本不可预知...
这个作者http://www.vckbase.com/document/viewdoc/?id=1727
也是用GDI+实现的,效率还可以啊,可见应该不是GDI+函数的问题,等我整理好了拿来大家看看怎么改进..
void CClockMeter::OnPaint()
{
CPaintDC dc(this); Graphics graphics(dc.GetSafeHdc()); // 构造memGrph对象(传设备描述表做为参数)
CRect ClienRect;
GetClientRect(&ClienRect);
if(!ClienRect.EqualRect(&m_rectCtrl)) // 如果将控件位置改变了
{
InitDial(); // 重新初始化表盘
}
// 把表盘克隆过来
Bitmap *pClonebmp = m_pDialMemBmp->Clone(0,0,m_pDialMemBmp->GetWidth(),m_pDialMemBmp->GetHeight(),PixelFormatDontCare);
ASSERT(pClonebmp!=NULL);
Graphics memGrph(pClonebmp); // 先画到内存图象中
memGrph.SetSmoothingMode(SmoothingModeAntiAlias); // GDI+反锯齿 // 画指针
DrawNeedle(memGrph);
graphics.SetInterpolationMode(InterpolationModeHighQuality); // 保证不拉伸位图 CachedBitmap cachebmp(pClonebmp,&graphics); // 用cache位图显示速度快
graphics.DrawCachedBitmap(&cachebmp,m_rectCtrl.left,m_rectCtrl.top); delete pClonebmp;}
DrawNeedle函数是这样的:void CClockMeter::DrawNeedle(Graphics &memGrph,DWORD dwNeedleStyle)
{
// 画指针 // 指针顶端坐标
if(dwNeedleStyle==0)
{
int x0,y0,x1,y1; x0 = m_ptCenter.x -(m_nOutsideRadius - m_nDitchWidth-m_PenWidthFrame)*cos(M_PI*m_dCurrentValue/360.0);
y0 = m_ptCenter.y -(m_nOutsideRadius - m_nDitchWidth-m_PenWidthFrame)*sin(M_PI*m_dCurrentValue/360.0);
/*int nAcrossdegree = 40; // 指针两边的跨度(0~360)
insiderect.GetSize(&sz);
insideRadius = sz.Width/2;*/
// 指针底端坐标
Pen NeedlePen(m_colorNeedle,2); x1 = m_ptCenter.x - (m_nInsideRadius+10)*cos(M_PI*(m_dCurrentValue+180)/360.0);
y1 = m_ptCenter.y - (m_nInsideRadius+10)*sin(M_PI*(m_dCurrentValue+180)/360.0); memGrph.DrawLine(&NeedlePen,x0,y0,x1,y1);
}
}
我现在的表盘相对画得有点复杂后,SetTimer(1,50,NULL);
发现开一个实例CPU就百分之30左右了,晕啊