其实Bitmap和Image是很像的(位图、图片),事实上他们也可以互相转化,不过他们各有不同特点。Bitmap有很多神奇的魔法,内容比较多,加上开学了,我每次只能说小部分了~~
知识点少,所以代码我会比较充实一点 :).. (其实我很幸运,我们班其他人这会儿不能开电脑)
1.CreateBitmapFromFile
函数是GdipCreateBitmapFromFile。如名,这个函数是从文件载入一个Bitmap。既然bmp和img可以串用,所以说一定程度上这个和GdipLoadImageFromFile差不多。
当然,这两个函数的参数也的确也是几乎一样的。
注意:下例中,载入文件是C:TestImg.png。
Option Explicit Dim bitmap As Long , bmW As Long , bmH As Long Dim graphics As Long Private Sub Form_Load() InitGDIPlus '从文件载入Bitmap GdipCreateBitmapFromFile StrPtr( "C:TestImg.png" ), bitmap GdipGetImageWidth bitmap, bmW GdipGetImageHeight bitmap, bmH '以下是用于绘制Bitmap的 GdipCreateFromHDC Me .hDC, graphics GdipDrawImageRectI graphics, bitmap, 0, 0, bmW, bmH '扫地工作 GdipDeleteGraphics graphics GdipDisposeImage bitmap 'Bitmap没有释放函数,直接拿Image的来用。这是允许的,因为这样做返回0(OK)。 TerminateGDIPlus End Sub |
同样,不要忘记了,Form的AutoRedraw=True.
看到这里,可能有人要问了,以前我一直把Terminate之类的东西放到Form_Unload中,但是这次却放到了Load中,那么到底放在哪里呢?其实,具体放哪里要看实际情况。
首先,Terminate这些东西,是用于释放资源的。因此无论如何我们都要调用一下~。
然后在我们这个例子中,我们其实只绘制了一次,没有后续绘制的需求,因此可以完成任务以后就Terminate/Delete/Dispose掉。
而我前面的例子其实都可以这么做。不过你自己的程序不一定就是这样。
例如我们用GDI+边写一个钟。钟是一个不断重新绘制的过程,因此最后Unload时候释放为宜;而如果我们要用GDI+绘制一个不变的界面,那么一般可以绘制后就释放。不过一般来说因为界面不只一个,一个窗体的界面部分绘制完毕后可以释放相关资源,但是GDI+是不Shutdown的,因为我们还要给他其他窗体的绘制任务……
2.CreateBitmapFromStream
这个函数跟GdipLoadImageFromStream是差不多的。。
下例:载入图片从101号资源。
Option Explicit Private Declare Sub CreateStreamOnHGlobal Lib "ole32.dll" ( ByRef hGlobal As Any, ByVal fDeleteOnRelease As Long , ByRef ppstm As Any) Dim img As Long , imgW As Long , imgH As Long , graphics As Long Private Sub Form_Load() InitGDIPlus Dim ResData() As Byte , IStream As Object ResData = LoadResData(101, "CUSTOM" ) CreateStreamOnHGlobal ResData(0), False , IStream GdipCreateBitmapFromStream IStream, bitmap GdipGetImageWidth img, imgW GdipGetImageHeight img, imgH Set IStream = Nothing '不要忘记把他释放了 GdipCreateFromHDC Me .hDC, graphics GdipDrawImageRectI graphics, img, 0, 0, imgW, imgH GdipDeleteGraphics graphics GdipDisposeImage img TerminateGDIPlus End Sub |
3.CreateBitmapFromHBITMAP
这里的HBITMAP就是我们的PictureBox/Form等等的Picture.Handle中获取。具体作用是什么呢?例如,GDI与GDI+的图片的转换。
一般来说,GdipCreateBitmapFromHBITMAP的第二个参数为0.
注意 本函数有个问题……转换得到的Bitmap数据是正确的,但是位图格式是错误的,所以例如只用这个代码创建一个32位hBitmap的Bitmap,绘制时候就会有问题~~
Option Explicit Dim bitmap As Long , bmW As Long , bmH As Long , graphics As Long Private Sub Form_Load() InitGDIPlus GdipCreateBitmapFromHBITMAP Picture1.Picture.Handle, 0, bitmap GdipGetImageWidth bitmap, bmW GdipGetImageHeight bitmap, bmH GdipCreateFromHDC Me .hDC, graphics GdipDrawImageRectI graphics, bitmap, 0, 0, bmW, bmH GdipDeleteGraphics graphics GdipDisposeImage bitmap TerminateGDIPlus End Sub |
4.CreateBitmapFromHICON
VB6中用这个呢,主要是为了获取窗体等等的ICON。注意了,虽然看上去VB中Icon属性和Picture属性貌似是一个东西其实不然。因此读取Icon必须要这么读,不能用上面方法。
同上,也有同样的BUG。
Option Explicit Dim bitmap As Long , bmW As Long , bmH As Long , graphics As Long Private Sub Form_Load() InitGDIPlus GdipCreateBitmapFromHICON Me .Icon.Handle, bitmap GdipGetImageWidth bitmap, bmW GdipGetImageHeight bitmap, bmH GdipCreateFromHDC Me .hDC, graphics GdipDrawImageRectI graphics, bitmap, 0, 0, bmW, bmH GdipDeleteGraphics graphics GdipDisposeImage bitmap TerminateGDIPlus End Sub |
5.CreateBitmapFromGraphics
这个是从一个现存的Graphics创建位图。这个和GdipGetImageGraphicsContext不一样,GdipGetImageGraphicsContext创建出来的Graphics修改后会影响原来的Image(绑定),而这个GdipCreateBitmapFromGraphics就不会,完全是创建一个副本。
Declare Function GdipCreateBitmapFromGraphics Lib "gdiplus" ( ByVal Width As Long , ByVal Height As Long , ByVal graphics As Long , bitmap As Long ) As GpStatus |
参数说明:
Width,Height:新创建的位图的长、宽
graphics:从哪个Graphic创建Bitmap
bitmap:创建出来的Bitmap指针放到哪里
Option Explicit Dim bitmap As Long , graphics As Long Private Sub Form_Load() InitGDIPlus GdipCreateFromHDC Me .hDC, graphics GdipGraphicsClear graphics, &HFFFF0000 '为了显示点内容 GdipCreateBitmapFromGraphics 100, 100, graphics, bitmap '创建一个现存的副本 GdipDrawImageRectI graphics, bitmap, 0, 0, 100, 100 '绘制这个副本 GdipDeleteGraphics graphics GdipDisposeImage bitmap TerminateGDIPlus End Sub |
6.CreateBitmapFromScan0 [Important]
说了那么多,我们可以发现,貌似所有的CreateBitmap都要有一个现存的蓝本……那么如何凭空创建一个Bitmap呢(其实是从内存)?就是这个函数了!
Declare Function GdipCreateBitmapFromScan0 Lib "gdiplus" ( ByVal Width As Long , ByVal Height As Long , ByVal stride As Long , ByVal PixelFormat As Long , scan0 As Any, bitmap As Long ) As GpStatus |
参数说明:
Width,Height:新位图的长、宽
stride:这个参数是在从一个指定数据创建Graphics时候设置数据扫描行间隔的。如果不是从已知内存创建创建的话则是0
PixelFormat:设定这个Bitmap的色深,我比较喜欢GpPixelFormat.PixelFormat32bppARGB。
scan0:这个参数是在从一个指定数据创建Graphics时候设置数据地址的,一定要用ByVal方式!如果是0就是从内存新创建一个而不是已知内容中数据。注意 得用ByVal 0
bitmap:传回的位图指针
Option Explicit Dim bitmap As Long , graphics As Long , gBmp As Long Private Sub Form_Load() InitGDIPlus GdipCreateBitmapFromScan0 100, 100, 0, GpPixelFormat.PixelFormat32bppARGB, ByVal 0, bitmap GdipGetImageGraphicsContext bitmap, gBmp GdipGraphicsClear gBmp, &HFFFF0000 GdipCreateFromHDC Me .hDC, graphics GdipDrawImageRectI graphics, bitmap, 0, 0, 100, 100 GdipDeleteGraphics gBmp GdipDeleteGraphics graphics GdipDisposeImage bitmap TerminateGDIPlus End Sub |
现在基本上所有常用的创建Bitmap方式都结束了。好累啊。。。