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


    http://vistaswx.com/blog/article/category/tutorial/page/2
    2009 年 9 月 9 日 4条评论
    标签: ,, 分类: 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方式都结束了。好累啊。。。

  • 相关阅读:
    Vue中改变对象的注意事项
    Object.assign简单总结
    Base64编码
    vue中prop传值时加不加v-bind(冒号:)
    内联元素的padding和margin
    flex自适应宽度显示省略号
    Http和Https
    JVisualVM 模拟一次内存泄漏场景分析
    Lucene
    布隆算法原理
  • 原文地址:https://www.cnblogs.com/liuzhaoyzz/p/4035045.html
Copyright © 2020-2023  润新知