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

VB6 GDI+ 入门教程[8] Bitmap魔法(1):创建的更多相关文章

  1. VB6 GDI+ 入门教程[9] Bitmap魔法(2):数据读写

    本文转自 http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[9] Bitmap魔法(2):数据读写 200 ...

  2. VB6 GDI+ 入门教程[7] Graphics 其他内容

    http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[7] Graphics 其他内容 2009 年 9 月 ...

  3. VB6 GDI+ 入门教程[1] GDI+介绍

    http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[1] GDI+介绍 2009 年 6 月 18 日 17 ...

  4. VB6 GDI+ 入门教程[2] GDI+初始化

    http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[2] GDI+初始化 2009 年 6 月 18 日 7 ...

  5. VB6 GDI+ 入门教程[3] 笔、刷子、矩形、椭圆绘制

    http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[3] 笔.刷子.矩形.椭圆绘制 2009 年 6 月 1 ...

  6. VB6 GDI+ 入门教程[4] 文字绘制

    http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[4] 文字绘制 2009 年 6 月 18 日 7条评论 ...

  7. VB6 GDI+ 入门教程[5] 基础绘图小结

    http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[5] 基础绘图小结 2009 年 6 月 18 日 4条 ...

  8. VB6 GDI+ 入门教程[6] 图片

    http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[6] 图片 2009 年 6 月 19 日 15条评论 ...

  9. WCF入门教程(二)如何创建WCF服务

    WCF入门教程(二)从零做起-创建WCF服务 通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK默认创建的样本 1.创建WCF服务库 2.看其生成结构 1)IService1.cs(协议) ...

随机推荐

  1. sql 邮件发送测试情况

    sql 邮件发送测试情况 select * from msdb.dbo.sysmail_allitems select * from msdb.dbo.sysmail_event_log

  2. HTTP请求&响应、POST与GET

    HTTP请求&响应 既然说从入门级开始就说说Http请求包的结构.一次请求就是向目标服务器发送一串文本.什么样的文本?有下面结构的文本.HTTP请求包结构 请求包例子: POST /meme. ...

  3. CodeForces 670D2 Magic Powder 二分

    D2. Magic Powder - 2 The term of this problem is the same as the previous one, the only exception — ...

  4. 不同分辨率的LCM进行兼容

    1.读取不同LCM ID的时序不同,如何处理? 2.开机后android会自动resize图片资源的大小,但开机logo无法自行resize,如何操作?保证识别到不同分辨率的LCM后开机logo可以正 ...

  5. 分别向Set集合以及List集合中添加"A"、"a"、"c"、"C"、"a",观察重复值"a"能否添加成功

    package lianxi; import java.util.*; public class JhSet { public static void main(String[] args) { Se ...

  6. CodeForces 131A cAPS lOCK

    cAPS lOCK Time Limit:500MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit St ...

  7. Devexpress TreeList选择父级联动

    Treelist当显示复选框后,父级和子级的复选框没有关联,使用过程中很不便,如图所示 自己给treelist添加父子级联动 /// <summary> /// 初始化TreeList,父 ...

  8. JAVA查找--[二分查找]

    package com.array; public class BinaryFind { /* * 项目名称:二分查找 ; * 项目要求:用JAVA对数组进行查找,并运用快速查找算法; * 作者:Se ...

  9. C# WPF – 利用“Attached Property” 把 RoutedEvent 接上 ICommand

    本文说明怎样把 DoubleClick 连接至 ICommand.方法很多.推荐使用 Attach Property 方式,因为它能把任何 RoutedEvent 接上任何 ICommand. 之前写 ...

  10. herf窗口点击跳转

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...