陈晓猫

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::
http://vistaswx.com/blog/article/category/tutorial/page/2
2009 年 9 月 9 日 4条评论
标签: Bitmap,GdiPlus,vb 分类: Tutorial,VB6 GDI+

其实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方式都结束了。好累啊。。。

posted on 2014-10-19 16:20  陈晓猫  阅读(2487)  评论(0编辑  收藏  举报