VB6 GDI+ 入门教程——图片

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://vistaswx.blogbus.com/logs/41225905.html

VB自己的绘图语句都需要用LoadPicture载入图片,同样,GDI+中也需要。

1.载入(初始化)图片资源

(1)来自文件:GdipLoadImageFromFile

我们先来看看这个最简单基本的载入图片来自文件:

[vb] view plain copy

print?

  1. Dim img As Long, img_W As Long, img_H As Long
  2. GdipLoadImageFromFile StrPtr("C:\TestImage.png"), img
  3. ‘如果你希望得到长宽信息,可以使用下面的语句:
  4. GdipGetImageWidth img, img_W
  5. GdipGetImageHeight img, img_H
  6. Msgbox "长为:" & CStr(img_W) & "px, 宽为:" & CStr(img_H) & "px."
  7. ‘GdipDisposeImage img

载入图像之后别忘记释放Image,否则会造成MemoryLeak内存泄漏(另外如果没有Dispose掉的话这个文件是被占用的)。

(2)来自资源文件:GdipLoadImageFromStream (2010/2/9修改)

这个函数主要是用来从资源文件(RES)载入图像的,怎么载入呢?我们来看函数,函数是从Stream载入,但是我们VB6没有集成Stream对象,从RES读取出来(LoadResData)也只是返回Byte()。不过很好,OLE提供了一个函数能够将Byte()变为一个IStream对象——我们需要这个API

[vb] view plain copy

print?

  1. Declare Sub CreateStreamOnHGlobal Lib "ole32.dll" (ByVal hGlobal As Long, ByVal fDeleteOnRelease As Long, ByRef ppstm As Any)

但是,函数第一个参数需要的是一个内存句柄而不是内存地址,这两个值有时一样有时不一样。当调用申请内存GlobalAlloc函数使用GMEM_FIXED参数时候它们相同,其它时候它们不同,一个数组的内存空间是否是GMEM_FIXED申请的取决于数组的声明位置等各种因素。所以我们可不能这么冒险假定hMem=pMem。那我们如何得到数据的内存句柄呢?新申请一块内存就得到句柄了,然后我们只需要复制数据即可。

[vb] view plain copy

print?

  1. ‘声明部分如下
  2. Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
  3. Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
  4. Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
  5. Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
  6. Private Declare Sub RtlMoveMemory Lib "kernel32" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
  7. Const GMEM_MOVEABLE As Long = &H2
  8. ‘实现部分如下
  9. Dim img As Long
  10. Dim ResData() As Byte, IStream As Object
  11. ResData = LoadResData(101, "CUSTOM")  ‘获取数据
  12. ‘接下来需要一个内存句柄而不是内存地址
  13. Dim hMemObj As Long, pMem As Long
  14. hMemObj = GlobalAlloc(GMEM_MOVEABLE, UBound(ResData) + 1) ‘申请新内存获得句柄
  15. pMem = GlobalLock(hMemObj)‘锁定内存块,返回内存块的指针
  16. If pMem = 0 Then  ‘分配内存失败
  17. Msgbox "Global alloc failed!"
  18. Exit Sub
  19. End If
  20. RtlMoveMemory ByVal pMem, ResData(0), UBound(ResData)+1  ‘复制源数据到新内存。
  21. ‘注:最后一个参数,传递的是数据的字节数,由于数组是字节类型,所以数组有多少个元素,就有多少个字节
  22. GlobalUnlock hMemObj‘解锁
  23. CreateStreamOnHGlobal ByVal hMemObj, False, IStream  ‘根据新内存句柄创建IStream
  24. GdipLoadImageFromStream IStream, img  ‘建立Image
  25. Set IStream = Nothing
  26. GlobalFree hMemObj  ‘释放新内存
  27. ‘GdipDisposeImage img   ‘图片不要忘记释放了

2.绘制图片

(1)GdipDrawImage(I) 

这是Gdi+绘图的一种基础画法,不需要进行长宽设置,不过我们平时不怎么用它。它按照图片的物理大小绘制,完全无视所有Graphics的Scale等缩放参数。这个函数支持32位透明通道绘制。(技巧:有I的一般 坐标、长宽都是Long型 没有I的一般都是Single型)

什么是物理大小?这个就要跟图像的分辨率(dpi)有关了。打开你的Photoshop或者是Fireworks或者是AI或者其他专业绘图软件,新建一个文档,你就会发现有分辨率选项,一般你看到的是72像素/英寸。但是,请注意,一般屏幕的分辨率是96像素/英寸。

96这个值可以在系统的显示设置中看到。在Windows7中的查看步骤是:桌面右键->屏幕分辨率->放大或缩小文本和其他项目->(左侧)设置自定义文本大小(DPI),在弹出对话框中有显示“每英寸 X 像素”。

图片一般的分辨率与屏幕的分辨率不一致,这会有什么结果?一般不会有问题,因为我们一般图像的绘制以px为单位,无论分辨率多高(结果是物理尺寸变小),图像都是包含了同样数量的像素点。可是现在这个函数是按照物理大小绘制的,这样Dpi的不同势必就会造成绘制出来的图像有“缩放”,一般呈现为比正常大小大。

分辨率如何调整?以后再说。

[vb] view plain copy

print?

  1. Dim img As Long
  2. GdipLoadImageFromFile StrPtr("C:\TestImage.png"), img
  3. ‘此处请初始化GDI+以及graphics
  4. GdipDrawImage graphics, img, 0, 0

拓展阅读:

1. 72dpi或96dpi的争论(cnBlogs)

2. Discussion of 72dpi & 96 dpi (English)

(2)GdipDrawImageRect(I) 推荐

这是我们常用的画法,一般Gdi+画图就用这个函数。我们可以对图片的大小进行平滑的拉伸缩放。

[vb] view plain copy

print?

  1. Dim img As Long
  2. GdipLoadImageFromFile StrPtr("C:\TestImage.png"), img
  3. ‘此处请初始化GDI+以及graphics
  4. GdipDrawImageRect graphics, img, 0, 0, 100, 200  ‘拉伸到100*200

(3)GdipDrawImageRectRect(I)

还有个有点常用的函数就是这个了。通过它我们可以画一个图的一个部分,并且同样可以改变大小(好处:我们可以把所有的图片资源综合到一个图片中),另外它支持一个叫做ImageAttribs的东西,这是图片的滤镜,我们可以改变图片透明度和各种颜色参数(如二值化,灰度化等)。ImageAttrib(utes)会在之后的教程中有所涉及。

代码如下:

[vb] view plain copy

print?

  1. Dim img As Long
  2. GdipLoadImageFromFile StrPtr("C:\TestImage.png"), img
  3. ‘此处请初始化GDI+以及graphics
  4. GdipDrawImageRectRectI graphics, img, 20, 20, 10, 10, 0, 0, 100, 200, UnitPixel

注意咯:

第三~第六个参数是原来图片中要截取的部分;第七~第十呢则是画到哪里以及画出来多大的设置

第三~第六个参数是为绘制位置和绘制尺寸;第七~第十则是截取位置和截取尺寸。

(4)贴图刷

贴图刷子主要用来绘制平铺的内容。贴图刷子跟其它刷子一样,我们需要创建刷子,另外对于这个刷子我们需要先初始化图片:)

[vb] view plain copy

print?

  1. Dim img As Long, textureBrush As Long
  2. GdipLoadImageFromFile StrPtr("C:\TestImage.png"), img
  3. ‘此处请初始化GDI+以及graphics
  4. GdipCreateTexture img, WrapModeTileFlipX, textureBrush
  5. GdipFillRectangle graphics, textureBrush, 0, 0, 100, 100

贴图刷子跟其它刷子有什么区别呢?普通的图片绘制(如DrawImageRectI)支持的是拉伸,贴图刷则是平铺。另外贴图刷还要注意定位问题。因为贴图刷纹理起始点是Graphics的0,0,而不是绘制内容的左上角坐标。

贴个图,直观明了。

那么贴图刷子中如何调整图片起始位置呢?我们可以平移图片——GdipTranslateTextureTransform。参数很简单 是平移量。(注意:这是个相对平移,也就是这个平移是参照之前量的,而不是原图片;因此建议更改平移量要先Reset下:GdipResetTextureTransform)

时间: 2024-08-01 10:45:20

VB6 GDI+ 入门教程——图片的相关文章

GDI+_入门教程【一】

GDI For VisualBasic6.0 [一]文件下载:GDI+ For VB6[一] 简单绘图实例演示百度网盘 1 '以下为作者[vIsiaswx]的教程 2 '(该教程发布的原地址已无法访问,此版是流散网络的电子书版复制过来的.如果声明必要,务必与我联系.) 3 ' E-mail : [email protected] 4 ' QQ: 1919988942 VB6 GDI+ 入门教程[1] GDI+ 介绍 引言:鉴于网上关于 GDI+的教程都是.Net 的,基本上没有 VB6.0 的,

Android基础入门教程——1.6 .9(九妹)图片怎么玩

Android基础入门教程--1.6 .9(九妹)图片怎么玩 标签(空格分隔): Android基础入门教程 1.本节引言: 可能有的一些疑问: 1.什么是.9图片? 答:图片后缀名前有.9的图片,如pic1.9.png这样的图片 2. .9图片能干嘛? 答: 在图片拉伸的时候特定的区域不会发生图片失真,而不失真的区域可以由我们自己绘制 3. .9图片用什么做? 答:工欲善其事,必先利其器,做.9图片的工具有: ①Android SDK自带:draw9patch.bat,不过这玩意出了好久,谷歌

【OpenCV入门教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/26157633 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 知乎:http://www.zhihu.com/people/mao-xing-yun 邮箱: [email protected] 写作当前博文时配套使用的OpenCV版本: 2.4.9 这篇文章里,我们将一起探讨图像金字塔的一

OpenCV 入门教程 之环境配置 + 图片匹配 matchTemplate

1.什么是OpenCV OpenCV的全称是:Open Source Computer Vision Library.OpenCV是一个基于(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows和Mac OS操作系统上.它轻量级而且高效--由一系列 C 函数和少量 C++ 类构成. 总结特点: 1.开源, 商业用途也不必公开自己的源代码或者改善后的代码. 2.效率高,简单的图像处理就算了,涉及到复杂的处理一般的类库无法满足比如CXImage 3.有巨头维护(Intel) 有这三个

VS2010/MFC编程入门教程之目录和总结

      目前该教程可以到鸡啄米编程课堂去学习,阅读体验更好,更适合在线学习. 鸡啄米的这套VS2010/MFC编程入门教程到此就全部完成了,虽然有些内容还未涉及到,但帮助大家进行VS2010/MFC的入门学习业已足够.以此教程的知识为基础,学习VS2010/MFC较为深入的内容已非难事.作为本教程的最后一课,鸡啄米将对前面所讲内容进行目录归纳,并对这八个月加班加点的努力进行总结. 一.VS2010/MFC编程入门教程之目录 第一部分:VS2010/MFC开发环境 VS2010/MFC编程入门

Android基础入门教程——8.1.3 Android中的13种Drawable小结 Part 3

Android基础入门教程--8.1.3 Android中的13种Drawable小结 Part 3 标签(空格分隔): Android基础入门教程 本节引言: 本节我们来把剩下的四种Drawable也学完,他们分别是: LayerDrawable,TransitionDrawable,LevelListDrawable和StateListDrawable, 依旧贴下13种Drawable的导图: 1.LayerDrawable 层图形对象,包含一个Drawable数组,然后按照数组对应的顺序来

Android基础入门教程——8.1.2 Android中的13种Drawable小结 Part 2

Android基础入门教程--8.1.2 Android中的13种Drawable小结 Part 2 标签(空格分隔): Android基础入门教程 本节引言: 本节我们继续来学习Android中的Drawable资源,上一节我们学习了: ColorDrawable:NinePatchDrawable: ShapeDrawable:GradientDrawable!这四个Drawable~ 而本节我们继续来学习接下来的五个Drawable,他们分别是: BitmapDrawable:Insert

Sina App Engine(SAE)入门教程(3)-KVDB使用

简介 因为传统关系型数据库在分布式环境下表现的扩展性不足等缺点,近年来NoSQL的概念渐渐成为业界关注的焦点,越来越多的技术人员也习惯于使用NoSQL数据库进行日常开发,SAE为了应对这种新需求,也进行了NoSQL方向的研发. KV DB是SAE开发的分布式key-value数据存储服务,用来支持公有云计算平台上的海量key-value存储.KV DB支持的存储容量很大,对每个用户支持100G的存储空间,可支持1,000,000,000条记录,用户可以用KV DB存放简单数据,如好友关系等. 用

2015年最新Android基础入门教程目录(完结版)

2015年最新Android基础入门教程目录(完结版) 标签(空格分隔): Android基础入门教程 前言: 关于<2015年最新Android基础入门教程目录>终于在今天落下了帷幕,全套教程 共148节已编写完毕,附上目录,关于教程的由来,笔者的情况和自学心得,资源分享 以及一些疑问等可戳:<2015最新Android基础入门教程>完结散花~ 下面是本系列教程的完整目录: 第一章:环境搭建与开发相关(已完结 10/10) Android基础入门教程--1.1 背景相关与系统架构