VC下加載多種格式圖片的方法總結IPicture, CxImage, CImage(AtlImage), CPictureEx


盡管VC有提供相應的API和類來操作bmp位圖、圖標和(增強)元文件,但卻不支持jpg、gif和png等格式的圖片,而這幾種格式卻是常常要用到的。這里我給大家介紹兩種辦法來操作這些格式的圖片。

1.用API OleLoadPicture來加載JPG、GIF格式的圖片(注:不支持PNG格式,另外GIF只能加載第一幀,且不支持透明)

OleLoadPicture 函數實際上創建了一個IPicture類型的COM接口對象,然后我們可以通過這個COM接口來操作圖片(實際上你也可以用API OleCreatePictureIndirect來加載圖片,不過相比而言OleLoadPicture函數簡化了基於流的IPicture對象的創建),下面是示例代碼:(注:由於只是用來示例,代碼中省去了出錯情況的處理)

[cpp]  view plain  copy
 
  1. <pre class="cpp" name="code">#include <olectl.h></pre>/*     *如下代碼段實現的功能是從指定的路徑中讀取圖片,並顯示出來     */ void DisplayImage(HDC hDC, LPCTSTR szImagePath) {             HANDLE hFile=CreateFile(szImagePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //從指定的路徑szImagePath中讀取文件句柄             DWORD dwFileSize=GetFileSize(hFile, NULL); //獲得圖片文件的大小,用來分配全局內存             HGLOBAL hImageMemory=GlobalAlloc(GMEM_MOVEABLE, dwFileSize); //給圖片分配全局內存             void *pImageMemory=GlobalLock(hImageMemory); //鎖定內存             DWORD dwReadedSize; //保存實際讀取的文件大小             ReadFile(hFile, pImageMemory, dwFileSize, &dwReadedSize, NULL); //讀取圖片到全局內存當中             GlobalUnlock(hImageMemory); //解鎖內存             CloseHandle(hFile); //關閉文件句柄                  IStream *pIStream;//創建一個IStream接口指針,用來保存圖片流             IPicture *pIPicture;//創建一個IPicture接口指針,表示圖片對象             CreateStreamOnHGlobal(hImageMemory, false, &pIStream); //用全局內存初使化IStream接口指針             OleLoadPicture(pIStream, 0, false, IID_IPicture, (LPVOID*)&(pIPicture));//用OleLoadPicture獲得IPicture接口指針                  //得到IPicture COM接口對象后,你就可以進行獲得圖片信息、顯示圖片等操作             OLE_XSIZE_HIMETRIC hmWidth;             OLE_YSIZE_HIMETRIC hmHeight;             pIPicture->get_Width(&hmWidth); //用接口方法獲得圖片的寬和高             pIPicture->get_Height(&hmHeight);             pIPicture->Render(hDC,0,0,100,100,0,hmHeight,hmWidth,-hmHeight,NULL); //在指定的DC上繪出圖片                  GlobalFree(hImageMemory); //釋放全局內存             pIStream->Release(); //釋放pIStream             pIPicture->Release(); //釋放pIPicture     }   


2.利用第三方的開發庫來操作圖片

這 里我向大家推薦一個庫CxImage。 CxImage里面包含了許多的類,可以用來加載、保存、顯示和變換圖片,而且支持許多的圖片格式,包括BMP、 JPEG、 GIF、 PNG、 TIFF、 MNG、 ICO、 PCX、 TGA、 WMF、 WBMP、 JBG、 J2K等。另外CxImage也支持Alpha通道,動畫幀等許多功能,而且它還是開源免費的。CxImage的當前的版本是v6.00, 介紹和下載可以訪問:http://www.codeproject.com/KB/graphics/cximage.aspx。CxImage的用法十分簡單,示例如下(省去出錯處理):   

[cpp]  view plain  copy
 
  1. void DisplayImage(HDC hDC, CString fileName)   
  2. {   
  3.             CString fileExt; //圖片的擴展名   
  4.             int len = fileName.GetLength();   
  5.             for(int i=len-1; i>=0; i--) //得到圖片的擴展名   
  6.             {   
  7.                     if(fileName[ i ] == '.')   
  8.                     {   
  9.                             fileExt=fileName.Mid(i+1);   
  10.                             break;   
  11.                     }   
  12.             }   
  13.             fileExt.MakeLower(); //將擴展名轉為小寫   
  14.             if(fileExt != _T(""))   
  15.             {   
  16.                     //創建CxImage對象,其中靜態方法CxImage::GetTypeIdFromName用來根據擴展名獲得圖片格式的ID代表   
  17.                     CxImage image(fileName,CxImage::GetTypeIdFromName(fileExt));   
  18.                     if(image.IsValid())   
  19.                     {   
  20.                             image.Draw(hDC);   
  21.                             image.Destroy();   
  22.                     }   
  23.             }   
  24. }   

 

3 提供一中更簡單的方法

VC MFC 提供的 API LoadBitmap / LoadImage 類 CBitmap 等都只能操作 BMP 位圖,圖標。對於其他常用的 JPG / JPEG / GIF / PNG 格式,它無能為力。VC 下怎樣才能加載各種非 BMP 格式的圖片呢? 下面介紹一種最簡單的辦法。用 CImage 類的 Load 函數加載圖片,之后用 Detach 取得 HBITMAP 句柄。取得圖片的HBITMAP 句柄后就可以像操作 BMP 圖片一樣處理 JPG / JPEG / GIF / PNG 格式的圖片了。具體代碼如下: 

[cpp]  view plain  copy
 
  1. #include <atlimage.h>   
  2.   
  3. CImage img;   
  4.   
  5. HRESULT ret = img.Load(filename ); // filename 是要加載的文件名(包含路徑)   
  6.   
  7. HBITMAP bitmap = img.Detach();   
  8.   
  9. //像操作 BMP 圖片一樣處理圖片  

 

但這些網上的方法還是有些問題,比如gif不能動態的顯示

下面說一下詳細步驟吧:

 1。下載 PictureEx.h和PictureEx.cpp兩個文件

把這兩個文件放在工程的文件夾里面,然后在將這兩個文件添加到工程里面去,這樣你的工程里就多了一個類了:CPictureEx

2.將你要加載的GIF圖片添加到項目文件夾里,這里我命名為:"inter.gif"

3。在試圖類的頭文件里添加:  

[cpp]  view plain  copy
 
  1. #include "PictureEx.h"  


定義一個對象: 

[cpp]  view plain  copy
 
  1. CPictureEx m_GifPic;  


4.在視圖類的OnCreate中創建 CPictureEx 對象並加載圖片:

[cpp]  view plain  copy
 
  1. <pre class="cpp" name="code">m_GifPic.Create(NULL,WS_CHILD | WS_VISIBLE |SS_ENHMETAFILE,CRect(50,50,100,100),this,1234);  
  2. m_GifPic.Load(_T("inter.gif"));  
  3. m_GifPic.ShowWindow(SW_HIDE);//SW_SHOW  
  4. </pre>  

 

注意:這一步驟不要在OnDraw里面實現,否則會出現錯誤,我一開始時一直有問題就是這個原因,還有load必須在movewindow(下一步的函數)之前,否則不會顯示圖片,還有就是load也可以放到ondraw里面去,但是那么做的話速度明顯不行了。

5。在ondraw里改變窗口位置並顯示圖片

[cpp]  view plain  copy
 
  1. m_GifPic.Create(NULL,WS_CHILD | WS_VISIBLE |SS_ENHMETAFILE,CRect(50,50,100,100),this,1234);  
  2. m_GifPic.Load(_T("inter.gif"));  
  3. m_GifPic.ShowWindow(SW_HIDE);//SW_SHOW  
  4. CRect rc =CRect(100,400,150,450);  
  5. m_GifPic.MoveWindow(&rc,true);  
  6. m_GifPic.Draw();  
  7. m_GifPic.ShowWindow(SW_SHOW);  

這里還有一個基於對話框加載GIF圖片的例子,添加了圖片鏈接和鼠標變換的功能。

下面是詳細的編程過程:

1. 新建項目:在VC6中用MFC新建一個基於對話框的GifDemo應用程序,接受所有缺省選項即可;

2.在項目中插入文件:把PictureEx.h,PictureEx.cpp文件copy 到項目文件夾下,Project->Add to Project->Files中選上PictureEx.h,PictureEx.cpp, Insert;

3.加入圖片控件:從對話框控件中把Picture Control(圖片控件)拖入主對話框中,修改其屬性:ID:IDC_GIF,TYPE:Rectangle,其余接受缺省選項。再在ClassWiard中為IDF_GIF加入CSatic控制變量m_GifPic, 注意看一下,GifDemoDlg.h中是否加上了#include "PictureEx.h"(由ClassWiard加入)。然后將CSatic m_GifPic;更改成CPictureEx m_GifPic;

4.加載動畫文件:先將要加載的動畫文件放到 res 資源文件夾下,再將其Import進項目中,由於MFC只支持256BMP文件的圖片,因此,我們要新建一個圖片類型:"GIF",我在這里將我網站的宣傳圖片roaring.gif放進去 (希望大家多支持),並將其ID修改成:IDR_GIFROARING。

____________________________________

import(導入)gif動畫的詳細過程:
在resourceview窗口中,單擊鼠標右鍵,在出現的環境菜單中選擇“import...”命令,會出現“import resource”選擇文件對話框,文件類型選擇“所有文件(*.*)”,open as 選項為"auto",再選擇動畫文件所在目錄,選上要載入的動畫文件 roaring.gif,再單擊 import,由於gif動畫類型不是vc默認的文件類型,這時會出現"custom resource type"對話框,鍵入“"gif"”,再單擊ok,然后再修改其id。
________________________________________________________________

5.在程序的適當位置添入加載代碼: 這里,我們在CGifDemoDlg::OnInitDialog()函數中加入如下代碼:

[cpp]  view plain  copy
 
  1. // TODO: Add extra initialization here  
  2. if (m_GifPic.Load(MAKEINTRESOURCE(IDR_GIFROARING),_T("Gif")))  
  3. m_GifPic.Draw();  


如果僅僅把動畫載入,到這就可以了,運行一下,應該看看您的的成果了。

下面附帶說說如何將這幅動畫制作成超鏈接,以后,咱們也可以宣傳自已的公司、網站或產品了。

6.利用ClassWiard加入一個LButtonDown鼠標左鍵消息處理函數CGifDemoDlg::OnLButtonDown(UINT nFlags, CPoint point),  添入如下代碼:

[cpp]  view plain  copy
 
  1. void CGifDemoDlg::OnLButtonDown(UINT nFlags, CPoint point)   
  2. {  
  3. // TODO: Add your message handler code here and/or call default  
  4. CRect rect;  
  5. m_GifPic.GetWindowRect(&rect);  
  6. ScreenToClient(&rect);  
  7.   
  8. if (rect.PtInRect(point))  
  9. ShellExecute(AfxGetMainWnd()->m_hWnd,_T("open"),  
  10. _T("http://roaringwind.best.163.com"),_T(""),NULL,0);  
  11.   
  12.   
  13. CDialog::OnLButtonDown(nFlags, point);  
  14. }  

我在這兒將我主頁的地址放上了,運行,點擊動畫圖片就能進入我的站點的了。當然要是能象所有的超鏈接一樣,能將鼠標變成手形,就更好了。

7.改變鼠標形狀:將一個鼠標文件放在res文件夾中,IMPORT,ID:IDC_CURSOR1,利用ClassWiard加入一個WM_SETCURSOR消息處理函數CGifDemoDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message),  添入如下代碼:

[cpp]  view plain  copy
 
  1. BOOL CGifDemoDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)   
  2. {  
  3. // TODO: Add your message handler code here and/or call default  
  4. CRect rect;  
  5. m_GifPic.GetWindowRect(&rect);  
  6. ScreenToClient(&rect);  
  7.   
  8. CPoint point;  
  9. GetCursorPos(&point);  
  10. ScreenToClient(&point);  
  11.   
  12. if (rect.PtInRect(point) && m_hCursor)  
  13. {  
  14. SetCursor(m_hCursor);  
  15. return TRUE;  
  16. };  
  17.   
  18.   
  19. return CDialog::OnSetCursor(pWnd, nHitTest, message);  
  20. }  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM