在下写了一个图像输出函数,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
数组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
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
DIB这玩意儿很那调的。一调就是一个小时。
本来我的这段程序是要放在一个控件内的。(所以我使用了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
1、这是由于VB的某些类似动态语言特性的特质导致的。很多情况下VB声明产生的数组即使有同样的维度和维数,在内存中的结构也不尽相同。更何况,使用SetDIBitsToDevice是较接近系统底层的函数,需要你自己写代码进行一些标准的验证。
2、不清楚你是在那里执行了“将程序B的PICTUREBOX上的图形保存”的操作。如果是在A中,那显然是不行的。SAVEPICTURE函数不具备获得其它进程中对象的数据的能力,它不是API。不过从另外的角度说,你已经学会使用SetDIBitsToDevice,就应该已经会把你能看见的东西全部保存下来了吧?要知道,使用GetDIBits函数是不受AutoRedraw限制的,它能够将缓存中存在的数据保存下来。
应该传picture.hdc的。这是内存DC。用getdc绘图必然不能保存。但是你为什么要用DIB,这个问题用createcompatibledc,createcompatiblebitmap就可以解决的。
我一直一来有个习惯都是习惯尽量使用VB本身的语句来解决我所需要的问题的。遇到实在不行的时候才会不得已去用一点API,而且基本都是现学现用,没有什么系统性,象我这次遇到的问题本来我是用SETPIXEL这个API的,但是后来实在是觉得太慢太慢,只好改用DIB,但是这个东西好像比较复杂,又找不到比较实用的资料。看MSDN也是觉得云里雾里,总觉得抓不住根。因为我的计算机都是自学的,平时都是针对一些具体应用写程序,所以特别是对于一些基于WINDOWS的底层原理不是很明白,才想到来这里找大家帮忙了。
1、事实上我针对现在困扰着你的问题也做过相当数量的研究,但是最终的结果的确证明了不能使用VB6内置的数组进行这样的应用。所以在这里我也要推荐一下.NET了,这些问题在.NET下不存在,至少我目前没有看到。
2、针对你的程序结构(C/S),我认为,使用VB内置函数是很不明智的选择。VB内置的函数不能跨内存区域访问(所有参数都是以指针方式传输的),没有数据校验,这在实际使用当中会导致相当多的问题。所以我还是推荐你自己写数据传输函数,手动将图像转换为字节流,在S端直接将数据写入文件。TO fmaliang(良马):
你的问题很不普遍。一般情况下,如果不是由于BITMAPINFOHEADER的数据有错的话,在正常的VB EXE/DLL中不会出现你说的问题。除非你的位图实在太大(超出了Long能够索引的范围)。