VB6 GDI+ 入门教程[8] Bitmap魔法,1:创建

http://vistaswx.com/blog/article/category/tutorial/page/2

VB6 GDI+ 入门教程[8] Bitmap魔法(1):创建

2009 年 9 月 9 日 4条评论

标签: Bitmap,GdiPlus,vb 分类: Tutorial,VB6 GDI+

点击下载 vIstaswx VB6 Gdi+ 模块(最后更新 2011/2/8)

其实Bitmap和Image是很像的(位图、图片),事实上他们也可以互相转化,不过他们各有不同特点。Bitmap有很多神奇的魔法,内容比较多,加上开学了,我每次只能说小部分了~~

知识点少,所以代码我会比较充实一点 :).. (其实我很幸运,我们班其他人这会儿不能开电脑)

1.CreateBitmapFromFile

函数是GdipCreateBitmapFromFile。如名,这个函数是从文件载入一个Bitmap。既然bmp和img可以串用,所以说一定程度上这个和GdipLoadImageFromFile差不多。

当然,这两个函数的参数也的确也是几乎一样的。

注意:下例中,载入文件是C:TestImg.png。

OptionExplicit

DimbitmapAsLong, bmWAsLong, bmHAsLong

DimgraphicsAsLong

PrivateSubForm_Load()

InitGDIPlus

'从文件载入Bitmap

GdipCreateBitmapFromFile StrPtr("C:TestImg.png"), bitmap

GdipGetImageWidth bitmap, bmW

GdipGetImageHeight bitmap, bmH

'以下是用于绘制Bitmap的

GdipCreateFromHDCMe.hDC, graphics

GdipDrawImageRectI graphics, bitmap, 0, 0, bmW, bmH

'扫地工作

GdipDeleteGraphics graphics

GdipDisposeImage bitmap'Bitmap没有释放函数,直接拿Image的来用。这是允许的,因为这样做返回0(OK)。

TerminateGDIPlus

EndSub

同样,不要忘记了,Form的AutoRedraw=True.

看到这里,可能有人要问了,以前我一直把Terminate之类的东西放到Form_Unload中,但是这次却放到了Load中,那么到底放在哪里呢?其实,具体放哪里要看实际情况。

首先,Terminate这些东西,是用于释放资源的。因此无论如何我们都要调用一下~。

然后在我们这个例子中,我们其实只绘制了一次,没有后续绘制的需求,因此可以完成任务以后就Terminate/Delete/Dispose掉。

而我前面的例子其实都可以这么做。不过你自己的程序不一定就是这样。

例如我们用GDI+边写一个钟。钟是一个不断重新绘制的过程,因此最后Unload时候释放为宜;而如果我们要用GDI+绘制一个不变的界面,那么一般可以绘制后就释放。不过一般来说因为界面不只一个,一个窗体的界面部分绘制完毕后可以释放相关资源,但是GDI+是不Shutdown的,因为我们还要给他其他窗体的绘制任务……

2.CreateBitmapFromStream

这个函数跟GdipLoadImageFromStream是差不多的。。

下例:载入图片从101号资源。

OptionExplicit

PrivateDeclareSubCreateStreamOnHGlobalLib"ole32.dll"(ByRefhGlobalAsAny,ByValfDeleteOnReleaseAsLong,ByRefppstmAsAny)

DimimgAsLong, imgWAsLong, imgHAsLong, graphicsAsLong

PrivateSubForm_Load()

InitGDIPlus

DimResData()AsByte, IStreamAsObject

ResData = LoadResData(101,"CUSTOM")

CreateStreamOnHGlobal ResData(0),False, IStream

GdipCreateBitmapFromStream IStream, bitmap

GdipGetImageWidth img, imgW

GdipGetImageHeight img, imgH

SetIStream =Nothing'不要忘记把他释放了

GdipCreateFromHDCMe.hDC, graphics

GdipDrawImageRectI graphics, img, 0, 0, imgW, imgH

GdipDeleteGraphics graphics

GdipDisposeImage img

TerminateGDIPlus

EndSub

3.CreateBitmapFromHBITMAP

这里的HBITMAP就是我们的PictureBox/Form等等的Picture.Handle中获取。具体作用是什么呢?例如,GDI与GDI+的图片的转换。

一般来说,GdipCreateBitmapFromHBITMAP的第二个参数为0.

注意 本函数有个问题……转换得到的Bitmap数据是正确的,但是位图格式是错误的,所以例如只用这个代码创建一个32位hBitmap的Bitmap,绘制时候就会有问题~~

OptionExplicit

DimbitmapAsLong, bmWAsLong, bmHAsLong, graphicsAsLong

PrivateSubForm_Load()

InitGDIPlus

GdipCreateBitmapFromHBITMAP Picture1.Picture.Handle, 0, bitmap

GdipGetImageWidth bitmap, bmW

GdipGetImageHeight bitmap, bmH

GdipCreateFromHDCMe.hDC, graphics

GdipDrawImageRectI graphics, bitmap, 0, 0, bmW, bmH

GdipDeleteGraphics graphics

GdipDisposeImage bitmap

TerminateGDIPlus

EndSub

4.CreateBitmapFromHICON

VB6中用这个呢,主要是为了获取窗体等等的ICON。注意了,虽然看上去VB中Icon属性和Picture属性貌似是一个东西其实不然。因此读取Icon必须要这么读,不能用上面方法。

同上,也有同样的BUG。

OptionExplicit

DimbitmapAsLong, bmWAsLong, bmHAsLong, graphicsAsLong

PrivateSubForm_Load()

InitGDIPlus

GdipCreateBitmapFromHICONMe.Icon.Handle, bitmap

GdipGetImageWidth bitmap, bmW

GdipGetImageHeight bitmap, bmH

GdipCreateFromHDCMe.hDC, graphics

GdipDrawImageRectI graphics, bitmap, 0, 0, bmW, bmH

GdipDeleteGraphics graphics

GdipDisposeImage bitmap

TerminateGDIPlus

EndSub

5.CreateBitmapFromGraphics

这个是从一个现存的Graphics创建位图。这个和GdipGetImageGraphicsContext不一样,GdipGetImageGraphicsContext创建出来的Graphics修改后会影响原来的Image(绑定),而这个GdipCreateBitmapFromGraphics就不会,完全是创建一个副本。

DeclareFunctionGdipCreateBitmapFromGraphicsLib"gdiplus"(ByValWidthAsLong,ByValHeightAsLong,ByValgraphicsAsLong, bitmapAsLong)AsGpStatus

参数说明:

Width,Height:新创建的位图的长、宽

graphics:从哪个Graphic创建Bitmap

bitmap:创建出来的Bitmap指针放到哪里

OptionExplicit

DimbitmapAsLong, graphicsAsLong

PrivateSubForm_Load()

InitGDIPlus

GdipCreateFromHDCMe.hDC, graphics

GdipGraphicsClear graphics, &HFFFF0000'为了显示点内容

GdipCreateBitmapFromGraphics 100, 100, graphics, bitmap'创建一个现存的副本

GdipDrawImageRectI graphics, bitmap, 0, 0, 100, 100'绘制这个副本

GdipDeleteGraphics graphics

GdipDisposeImage bitmap

TerminateGDIPlus

EndSub

6.CreateBitmapFromScan0 [Important]

说了那么多,我们可以发现,貌似所有的CreateBitmap都要有一个现存的蓝本……那么如何凭空创建一个Bitmap呢(其实是从内存)?就是这个函数了!

DeclareFunctionGdipCreateBitmapFromScan0Lib"gdiplus"(ByValWidthAsLong,ByValHeightAsLong,ByValstrideAsLong,ByValPixelFormatAsLong, scan0AsAny, bitmapAsLong)AsGpStatus

参数说明:

Width,Height:新位图的长、宽

stride:这个参数是在从一个指定数据创建Graphics时候设置数据扫描行间隔的。如果不是从已知内存创建创建的话则是0

PixelFormat:设定这个Bitmap的色深,我比较喜欢GpPixelFormat.PixelFormat32bppARGB。

scan0:这个参数是在从一个指定数据创建Graphics时候设置数据地址的,一定要用ByVal方式!如果是0就是从内存新创建一个而不是已知内容中数据。注意 得用ByVal 0

bitmap:传回的位图指针

OptionExplicit

DimbitmapAsLong, graphicsAsLong, gBmpAsLong

PrivateSubForm_Load()

InitGDIPlus

GdipCreateBitmapFromScan0 100, 100, 0, GpPixelFormat.PixelFormat32bppARGB,ByVal0, bitmap

GdipGetImageGraphicsContext bitmap, gBmp

GdipGraphicsClear gBmp, &HFFFF0000

GdipCreateFromHDCMe.hDC, graphics

GdipDrawImageRectI graphics, bitmap, 0, 0, 100, 100

GdipDeleteGraphics gBmp

GdipDeleteGraphics graphics

GdipDisposeImage bitmap

TerminateGDIPlus

EndSub

现在基本上所有常用的创建Bitmap方式都结束了。好累啊。。。