VB6 GDI+ 入门教程——图片

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

php

 

VB本身的绘图语句都须要用LoadPicture载入图片,一样,GDI+中也须要。html

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

(1)来自文件:GdipLoadImageFromFile数组

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

 
[vb]  view plain  copy
 
 print?
  1. Dim img As Long, img_W As Long, img_H As Long  
  2.   
  3. GdipLoadImageFromFile StrPtr("C:\TestImage.png"), img   
  4.   
  5. '若是你但愿获得长宽信息,可使用下面的语句:   
  6.   
  7. GdipGetImageWidth img, img_W    
  8.   
  9. GdipGetImageHeight img, img_H   
  10.   
  11. Msgbox "长为:" & CStr(img_W) & "px, 宽为:" & CStr(img_H) & "px."  
  12.   
  13. 'GdipDisposeImage img  

 

载入图像以后别忘记释放Image,不然会形成MemoryLeak内存泄漏(另外若是没有Dispose掉的话这个文件是被占用的)。spa

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

这个函数主要是用来从资源文件(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。那咱们如何获得数据的内存句柄呢?新申请一块内存就获得句柄了,而后咱们只须要复制数据便可。code

 
[vb]  view plain  copy
 
 print?
  1. '声明部分以下   
  2.   
  3. Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long  
  4.   
  5. Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long  
  6.   
  7. Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long  
  8.   
  9. Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long  
  10.   
  11. Private Declare Sub RtlMoveMemory Lib "kernel32" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)   
  12.   
  13. Const GMEM_MOVEABLE As Long = &H2   
  14.   
  15.   
  16.   
  17. '实现部分以下   
  18.   
  19. Dim img As Long  
  20.   
  21. Dim ResData() As Byte, IStream As Object  
  22.   
  23. ResData = LoadResData(101, "CUSTOM")  '获取数据   
  24.   
  25.     
  26.   
  27. '接下来须要一个内存句柄而不是内存地址   
  28.   
  29. Dim hMemObj As Long, pMem As Long  
  30.   
  31. hMemObj = GlobalAlloc(GMEM_MOVEABLE, UBound(ResData) + 1) '申请新内存得到句柄   
  32.   
  33. pMem = GlobalLock(hMemObj)'锁定内存块,返回内存块的指针   
  34.   
  35. If pMem = 0 Then  '分配内存失败   
  36.   
  37.     Msgbox "Global alloc failed!"  
  38.   
  39.     Exit Sub  
  40.   
  41. End If  
  42.   
  43. RtlMoveMemory ByVal pMem, ResData(0), UBound(ResData)+1  '复制源数据到新内存。  
  44. '注:最后一个参数,传递的是数据的字节数,因为数组是字节类型,因此数组有多少个元素,就有多少个字节   
  45.   
  46. GlobalUnlock hMemObj'解锁   
  47.   
  48. CreateStreamOnHGlobal ByVal hMemObj, False, IStream  '根据新内存句柄建立IStream   
  49.   
  50. GdipLoadImageFromStream IStream, img  '创建Image   
  51.   
  52. Set IStream = Nothing  
  53.   
  54. GlobalFree hMemObj  '释放新内存   
  55.   
  56. 'GdipDisposeImage img   '图片不要忘记释放了  
 

2.绘制图片orm

(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.   
  4. '此处请初始化GDI+以及graphics   
  5.   
  6. 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.     
  3. GdipLoadImageFromFile StrPtr("C:\TestImage.png"), img   
  4. '此处请初始化GDI+以及graphics   
  5. 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.     
  3. GdipLoadImageFromFile StrPtr("C:\TestImage.png"), img   
  4. '此处请初始化GDI+以及graphics   
  5. 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.   
  3. GdipLoadImageFromFile StrPtr("C:\TestImage.png"), img   
  4. '此处请初始化GDI+以及graphics   
  5. GdipCreateTexture img, WrapModeTileFlipX, textureBrush   
  6. GdipFillRectangle graphics, textureBrush, 0, 0, 100, 100  

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

贴个图,直观明了。

 

Photobucket

 

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

相关文章
相关标签/搜索