在下写了一个图像输出函数,IdDestination 为要进行图像输出的对象的HDC
数组ColOut(x,y,a) a=0,1,2 用来存放事先得到的各个点的颜色值
例如ColOut(100,200,0)存放的是点(100,200)的红色分量。并且已经用SETPIXEL函数验证无误。而为了加快图像输出的速度,我在这里想使用SetDIBitsToDevice 
但是得到的总是花屏,反复调试也无法解决,望各位高手大侠加以援助。指出我程序中的问题所在。也可以给我EMIAL解决[email protected] 。非常感谢。Public Sub ImgOutPut(ByVal IdDestination As Long)
Dim P As Long
Dim X As Long
Dim Y As Long
Dim LineBytes As Long  '一个扫描行的长度,计算公式:LineBytes=((biWidth*biBitCount+31)And &HFFFFFFE0)\8
Dim BmpInfo As BITMAPINFOHEADERWith BmpInfo
   .biSize = Len(BmpInfo)
   .biWidth = OutPutWid
   .biHeight = OutPutHei
   .biBitCount = 24       '24位色
   .biPlanes = 1
   .biCompression = 0
   LineBytes = ((OutPutWid * 24 + 31) And &HFFFFFFE0) \ 8
   .biSizeImage = LineBytes * OutPutHei
   ReDim MapData(0 To .biSizeImage - 1)
End WithP = 0
For Y = OutPutHei - 1 To 0 Step -1
   For X = 0 To OutPutWid - 1
      MapData(P) = ColOut(X, Y, 0)      'red
      MapData(P + 1) = ColOut(X, Y, 1)  'green
      MapData(P + 2) = ColOut(X, Y, 2)  'blue
      P = P + 3
   Next
   P = (P \ LineBytes)   '用来调整扫描行记数
   P = P + 1
   P = P * LineBytes
Next
SetDIBitsToDevice IdDestination, 0, 0, OutPutWid, OutPutHei, 0, 0, 0, OutPutHei, MapData(0), BmpInfo, 1   'DIB_RGB_COLORSEnd Sub

解决方案 »

  1.   

    这儿不对,DIB_RGB_COLORS = 0这样写试一试:
    P乘一个除一个太难懂了。For Y = OutPutHei - 1 To 0 Step -1
    P = lintbytes * (OutPutHei - 1 - y)
       For X = 0 To OutPutWid - 1
          MapData(P) = ColOut(X, Y, 0)      'red
          MapData(P + 1) = ColOut(X, Y, 1)  'green
          MapData(P + 2) = ColOut(X, Y, 2)  'blue
          P = P + 3
       Next
    Next
      

  2.   

    别的也看不出什么问题。
    DIB这玩意儿很那调的。一调就是一个小时。
      

  3.   

    谢谢以上各位的大力相助,特别是ColdMooon(天行健,君子以自强不息)的意见使我的程序效率提高很多,加快了运行的速度。经过我后来的仔细研究,又发现一个新的问题,非常有趣,现在交给大家一起讨论:
    本来我的这段程序是要放在一个控件内的。(所以我使用了Public Sub,而不是Private Sub)
    后来为了调试方便,我把这段代码原样方入了一个EXE工程,很奇怪的事发生了:它工作了!
    这个现象非常有意思。难道说SetDIBitsToDevice只能在本地工程中正常工作,而不能在控件中向它的宿主程序正常绘图吗?希望各位能与我一起研究这个问题。同样奇怪的情况我还遇到过,就是如果有两个程序,程序A向程序B中的PICTUREBOX控件绘制线条,我使用的是API: MoveToEx和LineTo 。当我将程序B的PICTUREBOX的HDC传给程序A,可以正常地进行绘制,但是无论我无论如何也无法将程序B的PICTUREBOX上的图形保存下来。而且我可以保证,并非是PICTUREBOX属性设置的问题,因为我知道要保存一个PICTUREBOX上的图形需要将它的AUTOREDRAW设为TRUE,并且使用:SAVEPICTURE "FILENAME",PICTURE.IMAGE。
    我又试着将PICTUREBOX的hWND属性传给程序A,程序A中使用GETDC(hWND)得到的句炳来绘制曲线。结果是程序A同样可以在程序B的PICTUREBOX上正确地绘制曲线,而PICTUREBOX的内容还是无法保存。当时这个问题也困扰了我好久,后来我不得不另想办法解决了,就是在程序A向程序B绘图的同时,也在自己的窗体上画一个同样的图形并且可以正常地保存下来。以上两个问题都是我在实际编程中遇到的问题,因为我不是很了解WINDOWS的原理,所以无法对他们做出解释,希望论坛上的兄弟如果有知道这个问题的给我指个方向。如果没有遇到过这样的问题的朋友有兴趣的话也可以试试看,是否和我得到一样的结果。
    我的软件环境是:WIN2000 + VB6 +SP5
      

  4.   

    我来回答你上面的问题:
    1、这是由于VB的某些类似动态语言特性的特质导致的。很多情况下VB声明产生的数组即使有同样的维度和维数,在内存中的结构也不尽相同。更何况,使用SetDIBitsToDevice是较接近系统底层的函数,需要你自己写代码进行一些标准的验证。
    2、不清楚你是在那里执行了“将程序B的PICTUREBOX上的图形保存”的操作。如果是在A中,那显然是不行的。SAVEPICTURE函数不具备获得其它进程中对象的数据的能力,它不是API。不过从另外的角度说,你已经学会使用SetDIBitsToDevice,就应该已经会把你能看见的东西全部保存下来了吧?要知道,使用GetDIBits函数是不受AutoRedraw限制的,它能够将缓存中存在的数据保存下来。
      

  5.   

    你说的情况没遇到过。
    应该传picture.hdc的。这是内存DC。用getdc绘图必然不能保存。但是你为什么要用DIB,这个问题用createcompatibledc,createcompatiblebitmap就可以解决的。
      

  6.   

    在PICTUREBOX上绘图不能保存的问题我也碰到过,不知道怎么回事,呵呵。
      

  7.   

    第一个问题:看了 CCL(VB卡尔)的两点建议,能否给出一个解决的方法呢?因为我将这段代码放到控件中后确实如同你说的问题,象是数组中的数据的位置偏移了,而它在标准EXE工程中运行是很正常的。我找不到其中的规律。这段代码和我自己目前所用的是一致的,所以能否请阁下也用我的方法尝试一下,帮我一起解决呢?第二个问题:实质上程序B是一个SERVER,程序A是一个CLINT,通过DDE来交换数据,程序A是不可见的,它负责在后台将数据绘制到B的PICTUREBOX上,而由B来保存。这样作的目的是为了减少SERVER端的代码量,和加快前台的响应速度。而且我现在学到的DIB还不够系统和全面,还不能达到随心所欲的程度。当然,如前所说的,我是通过另外的方法将这个问题绕开了,而不是真正的解决了。另外回复ColdMooon(天行健,君子以自强不息) 阁下:
    我一直一来有个习惯都是习惯尽量使用VB本身的语句来解决我所需要的问题的。遇到实在不行的时候才会不得已去用一点API,而且基本都是现学现用,没有什么系统性,象我这次遇到的问题本来我是用SETPIXEL这个API的,但是后来实在是觉得太慢太慢,只好改用DIB,但是这个东西好像比较复杂,又找不到比较实用的资料。看MSDN也是觉得云里雾里,总觉得抓不住根。因为我的计算机都是自学的,平时都是针对一些具体应用写程序,所以特别是对于一些基于WINDOWS的底层原理不是很明白,才想到来这里找大家帮忙了。
      

  8.   

    我用GetDIBits处理位图,图像小于32×32(这个值不太记得了,反正差不多吧)得到的数组里面的数据就打乱了,搞不清顺序了,如果宽度大于640就会出现溢出,好奇怪啊!
      

  9.   

    TO 楼主:
    1、事实上我针对现在困扰着你的问题也做过相当数量的研究,但是最终的结果的确证明了不能使用VB6内置的数组进行这样的应用。所以在这里我也要推荐一下.NET了,这些问题在.NET下不存在,至少我目前没有看到。
    2、针对你的程序结构(C/S),我认为,使用VB内置函数是很不明智的选择。VB内置的函数不能跨内存区域访问(所有参数都是以指针方式传输的),没有数据校验,这在实际使用当中会导致相当多的问题。所以我还是推荐你自己写数据传输函数,手动将图像转换为字节流,在S端直接将数据写入文件。TO fmaliang(良马):
    你的问题很不普遍。一般情况下,如果不是由于BITMAPINFOHEADER的数据有错的话,在正常的VB EXE/DLL中不会出现你说的问题。除非你的位图实在太大(超出了Long能够索引的范围)。
      

  10.   

    谢谢各位对我提出的问题的关注。尤其感谢CCL(VB卡尔)给出的意见,不过暂时我还不想把工作转移到.NET平台,因为我曾经尝试过在.NET下开发,发现里面的很多东西改变很大,很多东西几乎都要从头学过。并且.NET是针对网络支持很出色,但是对于我所关心的速度方面则没有多少提高。所以我会在以后再考虑用.NET开发。再次感谢你对于我的支持。另对ColdMooon(天行健,君子以自强不息)提出的几个API方法,非常有兴趣,我会尝试一下。对于fmaliang(良马) 提出的问题,似乎我没有遇到,因为,我这里最小的输出是12x12,最大的输出超过1500x1500,在我作本地EXE工程用DIB输出的时候均为正常。
      

  11.   

    我的系统是98,用的VB5,用这些低版本是为了编写绿色软件,我喜欢所有软件都是一个程序就搞定,不喜欢调用好多其它的DD。^_^