比如绘制一个时钟,20毫秒或者40毫秒走动一次(精密控制就要求这个速度),我用GDI+就绘制一个都占%7以上,我看见人家也是用GDI+绘制的,占用很少,而且我的是一个屏幕都全部要用来显示仪表的,这样就有N个仪表同时在走动,占用CPU相当高,难以忍受,不知道有什么妙方(不要跟我说什么DX)。

解决方案 »

  1.   

    在windows下 做几十毫秒的时间,控制估计还是比较难哦!
      

  2.   

    应该是你在绘制的时候处理的不好。
    建议:时间效率和空间效率是相矛盾的。游戏的性能高,除了游戏使用了一些汇编级优化,更重要的是,游戏使用了大量的缓存来提高执行的速度。
    所以,你也应该使用GDI建立大量的缓存,比如HDC/CDC 变量/对象,仅作BitBlt操作减少计算量大的操作。总之是要优化,优化,再优化如果确实要高性能,还是建议使用DX。要不,摄像头的驱动都使用 Direct Show呢!
      

  3.   

    可以像Windows处理WM_MOUSEMOVE一样去处理。
      

  4.   

    我就在一个自定义函数void DrawMeter()里调用几个GDI+函数(还没没把图象画到屏幕呢),然后按20毫秒一次的频率调用DrawMeter()函数,运行9个实例,晕,CPU 100%了我已经使用缓存了,比如表盘是基本固定的,那我就在一个InitDial()函数先把表盘画到一个Bitmap中并保存起来,然后画指针时,把这个Bitmap指针克隆过来就可以,但指针是走动的不能缓存啊,每次都得重新画一次。http://www.vckbase.com/document/viewdoc/?id=1727
    这个作者做的还可以,效率也符合我的要求,但源码....
      

  5.   

    我就在一个自定义函数void   DrawMeter()里调用几个GDI+函数(还没没把图象画到屏幕呢),然后按20毫秒一次的频率调用DrawMeter()函数,运行9个实例,晕,CPU   100%了如何实现20毫秒频率调用是关键,楼主不说清楚怎么能解决呢~~
      

  6.   

    Timer?
    新线程?
    把具体的调用代码贴出来
      

  7.   

    是响应WM_TIMER消息,然后刷新控件客户区域,我只在控件的OnPaint函数中把缓存在内存中的表盘克隆一份过来,然后在上面画走动指针,最后拷贝到屏幕,当然SetTimer定时20毫秒不是很准确啦,但已经符合要求了,等我整理好了,再拿出来给大家讨论应该在那方面改进。还有有什么好的GDI+方面的书籍或者资料介绍下,.cn一度一枚指针,做上360幅这样的图,初始化的时候全部读到内存里,用的时候,合并出来。
    -----------------------
    这位兄弟的做法不符合要求,我画时钟那不是要缓存360个Bitmap*了???我要是画其他的呢?比如画温度计,那你想要缓存多少Bitmap*??根本不可预知...
      

  8.   

    参见WINDOWS程序设计“多任务和多线程”章节
      

  9.   

    CPU占用高很大程度是你的循环太占用时间了.
      

  10.   

    如果只是重画指针应该不会占用多少时间,lz在重画的时候还做了什么?DrawMeter 在什么地方使用?
      

  11.   

    还有lz在重画的时候用到 gdi+ 的函数吗?
      

  12.   

    楼上的大哥,我所作的都是用GDI+函数实现的呀,
    这个作者http://www.vckbase.com/document/viewdoc/?id=1727
    也是用GDI+实现的,效率还可以啊,可见应该不是GDI+函数的问题,等我整理好了拿来大家看看怎么改进..
      

  13.   

    我的控件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左右了,晕啊
      

  14.   

    http://www.vckbase.com/document/viewdoc/?id=1727 可没有说在话的时候也用到GDI+吧。还是用 GDI 来画指针吧,快很多的。