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)

相關文章
相關標籤/搜索