我用FORM自带的PAINTPICTURE,非常慢,有类似的API比较快,而且可以平铺图片吗?

解决方案 »

  1.   

    PAINTPICTURE应该不慢,除非你循环调用个成千上万下.
    类似的API有: BITBLT, TRANSPARENTBLT, StretchBlt等等
      

  2.   

    还有,图形上处理慢的原因估计是你用的是你把AutoRedraw设置为True,然后进行绘制过程。
    这样效率会降低很多。因为你没做一个动作它都会记忆一次,并且刷新到窗口上显示出来。
    如果你要进行平铺50张图片,那么就会记忆和刷新50次,效率肯定不会高。通常的做法应该是将要处理的过程在内存中直接处理好,然后再刷新窗口显示出来。对于图形而言,
    通常使用GDI或GDI+或DirectX来做这些事。比较符合Windows习惯的做法就是GDI。GDI是一系列的API函数,通常GDI函数是指调用gdi32.dll里的API函数。比如楼上所说的BitBlt
    函数和StretchBlt函数都属于标准的GDI函数。但即使是GDI的API函数,如果使用的方法不对也是不能提高效率的,比如如果还是按照绘制一张图
    就刷新到窗口上显示出来,速度也不会提高多少,因为还是经过了平凡的显示着一块,这是很浪费资
    源的操作(在重复多次操作中特别明显)。所以需要在内存中直接处理重复的这些操作,然后可以在
    处理完成后一次刷新结果到窗口上,这样效果会好很多。不知道你有没有看过用GDI方法开发的游戏,大致就是这么一个过程,因为在频繁的图片绘制中,如果
    每一个小图片或小标志都要刷新一次窗口显示出来,那个游戏肯定没法玩下去,呵呵。而这种所谓在内存的处理方法其实就是建立一个内存里的GDI设备来完成,这个GDI设备就像PictureBox
    的hDC设备,但是他和不关联窗口(当然可以做关联窗口的设备),所以在这种设备绘制完不会显示出来,
    如果要显示这个设备的内容,那么就把这个设备的内容整个绘制到你要显示的设备上就可以了。就你的需求来说其实就像我上面所说的,用区域的方式以刷子填充还是比较快的,至于如何实现,你可以
    参考以下几个GDI函数:
    CreateRectRgn
    CreateEllipticRgn
    CreatePolygonRgn
    CreatePolyPolygonRgn
    FillRgn
    PaintRgn
    SelectObject
    DeleteObject
    CreatePatternBrush
    CreateDIBSection
    CreateCompatibleDC
    DeleteDC这些GDI函数使用起来也不难,在网上可以查一下使用方法应该可以做出你想要的效果了
      

  3.   


    这段话的观点我完全不同意。
    Autoredraw吧不会拖慢绘图的速度,你说的会拖慢是因为你用了不恰当的方法。
    如果你把Autoredraw设置为true,为了执行效率,你就不要用VB自带的一些绘图方法了,比如line,circle,因为这些封装好的方法会在执行完毕后执行refresh,这个时候我们就应该用GDI的函数来代替这些方法,并且在绘图结束后,手动调用refresh方法,让后台DC的图像绘制倒前台DC。Autoredraw和你后面所说的在内存中建立缓冲区是一个目的,都是为了实现双缓冲而已。如果我们自己建立双缓冲,一般都是需要在paint事件中加入代码的,而如果设置了autoredraw,则VB会bang我们完成任务。
      

  4.   

    SupermanKing和laviewpbt所说的我都认真看过了,可能我真的应该如laviewpbt所说,方法用得不太好,我是在usercontrol里来画一个窗口,然后再用一般的form进行加载来显示的,刚调用的时候没什么,但后来发现在改变大小后觉得非常慢,我主要是用paintpicture来画图,不知道是否因为usercontrol导致慢了?
      

  5.   

    发表一下我的看法:
    如果在同样的条件下频繁绘图,Autoredraw设置为true决对没有Autoredraw设置为False的速度快,
    因为Autoredraw设置为true毕竟会多一些处理过程,除了占用内存,还占用CPU,如果对大量频繁的
    绘图操作来说是很不利的。
    比如一个游戏的绘图操作基本都是这么个过程
    ...
    IsExit=False
    Do
       '这里是扫描键盘呀鼠标呀什么的其他过程
       ...
       '这里是将有关信息在设备里处理并绘图过程
       ...
       Scene.Refresh   '刷新到窗口
    Loop IsExit=True
    end...如果这时要刷新的窗口或PictureBox的Autoredraw设置为true,可能会产生以下问题
    1、会有卡的现象,画面可能不流畅(当然这也和硬件或分辨率有关,有些硬件快起来根本看不出卡,呵呵)
    2、有可能导致内存不够的情况(这种情况在Autoredraw设置为true的时候频繁操作很容易出现)但是Autoredraw设置为False则非常流畅,同时如果对比系统资源的使用情况将会发现,
    内存和CPU的占用也会少很多,对于频繁的绘图操作,比如动画、游戏等,建议都不要将
    Autoredraw设置为true,因为重绘窗口的速度可能比收到paint消息的速度还要快还要
    频繁,没必要让VB再去存储呀处理的了。
      

  6.   

    关键要考虑绘图速度和刷新频率。1)如果绘图比较慢。
    比如很复杂的图,要用 0.1 秒才能画出来,那么中间过程肉眼能够看到,用双缓冲(AutoRedraw = True)就能避免视觉滞留导致的闪烁。2)如果绘图很快,刷新适中。
    比如频率为 20 帧/秒,每帧只要 0.001 秒就可以画完,那么不用缓冲直接绘制(AutoRedraw = False)最合适。3)如果刷新过快。
    还是 0.001 秒画完 1 帧,但是频率为 1000 帧/秒,远高于一般显示器的刷新频率,大部分帧根本没机会显示到屏幕上;而且无论是否用缓冲,过量的刷新事件会拖慢整个程序的响应速度。
      

  7.   

    非常同意Tiger_Zhao
     
    (VB老鸟) 的意见。
      

  8.   

    一般的Bitblt就行了,比那个PaintPicture快多了。
    还想再快就要用Direct3D 或者 DirectDraw了。
      

  9.   


    但如果想平铺图片,用bitblt不就应该用for来循环吗?这样还会比paintpicture快吗?
      

  10.   

    会,如果在GDI设备环境下会快很多,图像越大差距越大。
      

  11.   

    关键是 penguinhzf 实测 1 次绘图用时多少?
    需求决定方案,没有前提单纯讨论哪种方案好是没意义的。