VB6 GDI+ 入门教程[8] Bitmap魔法(1):创建
其实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):创建的更多相关文章
- VB6 GDI+ 入门教程[9] Bitmap魔法(2):数据读写
本文转自 http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[9] Bitmap魔法(2):数据读写 200 ...
- VB6 GDI+ 入门教程[7] Graphics 其他内容
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[7] Graphics 其他内容 2009 年 9 月 ...
- VB6 GDI+ 入门教程[1] GDI+介绍
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[1] GDI+介绍 2009 年 6 月 18 日 17 ...
- VB6 GDI+ 入门教程[2] GDI+初始化
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[2] GDI+初始化 2009 年 6 月 18 日 7 ...
- VB6 GDI+ 入门教程[3] 笔、刷子、矩形、椭圆绘制
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[3] 笔.刷子.矩形.椭圆绘制 2009 年 6 月 1 ...
- VB6 GDI+ 入门教程[4] 文字绘制
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[4] 文字绘制 2009 年 6 月 18 日 7条评论 ...
- VB6 GDI+ 入门教程[5] 基础绘图小结
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[5] 基础绘图小结 2009 年 6 月 18 日 4条 ...
- VB6 GDI+ 入门教程[6] 图片
http://vistaswx.com/blog/article/category/tutorial/page/2 VB6 GDI+ 入门教程[6] 图片 2009 年 6 月 19 日 15条评论 ...
- WCF入门教程(二)如何创建WCF服务
WCF入门教程(二)从零做起-创建WCF服务 通过最基本的操作看到最简单的WCF如何实现的.这是VS的SDK默认创建的样本 1.创建WCF服务库 2.看其生成结构 1)IService1.cs(协议) ...
随机推荐
- Java过滤器应用-对Ajax请求做Session失效判断
过滤器常用来对Session过期做判断 Layout.js 1.为ajax请求添加标识 2.无论ajax请求成功与否,complete函数终会执行 // 全局Ajax设置, 用于session过期后的 ...
- Spring中MultipartHttpServletRequest实现文件上传
Spring中MultipartHttpServletRequest实现文件上传 转贴自:http://my.oschina.net/nyniuch/blog/185266 实现图片上传 用户必须能 ...
- [转载]单元测试之道(使用NUnit)
首先来看下面几个场景你是否熟悉 1.你正在开发一个系统,你不断地编码-编译-调试-编码-编译-调试……终于,你负责的功能模块从上到下全部完成且编译通过!你长出一口气,怀着激动而又忐忑的心情点击界面上的 ...
- Cheatsheet: 2013 07.01 ~ 07.08
.NET The overhead of async/await in NET 4.5 await Task, Task.Wait and Friends 350 Interview Question ...
- shutdown命令
其实不需要使用软件,就可以实现自动关机或重启等功能的:Windows XP的关机是由Shutdown.exe程序来控制的,位于Windows\System32文件夹中.如 果想让Windows 200 ...
- The property 'RowId' is part of the object's key information and cannot be modified.
2016-10-20 10:19:46,667 [12] ERROR ClientApp.FormDownload - ErrorSystem.InvalidOperationException: T ...
- How To Tune or Test PLSQL Code Performance in Oracle D2k Forms
You can test or tune your program unit performance in Oracle forms with Ora_Prof package.Suppose you ...
- CUBRID学习笔记 36 在net中添加多行记录
using System.Data.Common; using CUBRID.Data.CUBRIDClient; namespace Sample { class Add_MultipleRows ...
- 动态CSS--less
忙了很久终于有时间来写点东西了,不知道大家有没有发现,我们在写CSS的时候总是在重复很多代码,一个相同的属性值往往要重复N次,以前我就经常想有没有什么办法能让我们不用一直重复的font-size啊co ...
- iOS - Swift NSTimeZone 时区
前言 public class NSTimeZone : NSObject, NSCopying, NSSecureCoding NSTimeZone 表示时区信息. 1.NSTimeZone 时区的 ...