MFC 對話框Picture Control(圖片控件)中靜態和動態顯示Bmp圖片
最近有同學問我如何實現MFC基於對話框在圖片控件中加載圖片?其實使用MFC顯示圖片的方法各種各樣,但是還是有些同學不知道怎樣顯示.以前在《數字圖像處理》課程中完成的軟件都是基於單文檔的程序,這裏介紹兩種在對話框picthre控件中顯示BMP圖片的最簡單基礎的方法.
~~方法可能並不完美,高手忽略,但是提供一種能運行的方法,希望對剛接觸這方麵知識的同學有所幫助.可能你覺得文章過於簡單或者有些過於詳細敘述(點到即可我並不反對),但也為哪些入門同學想想,當初自己也是一頭霧水.
一.靜態顯示bmp圖片
1.創建MFC基於對話框程序,添加一個button1和picture控件,其中“資源視圖”中編輯picture控件ID為:IDC_STATIC_PIC.
2.在"資源視圖"(如果沒有,視圖中可調用出來)中右鍵鼠標Dialog處,選擇"添加資源".在對話框中選擇Bitmap,點擊"導入",選擇本地bmp圖片(建議位圖放置在res文件夾中).它會添加一張IDB_BITMAP1圖片.
3.點擊button1按鈕,在生成的函數中添加如下代碼:
void CShowBmpDlg::OnBnClickedButton1() { //從資源中加載圖片 CBitmap bitmap; //加載指定位圖資源 Bmp圖片ID bitmap.LoadBitmap(IDB_BITMAP1); //獲取對話框上的句柄 圖片控件ID CStatic *p=(CStatic *)GetDlgItem(IDC_STATIC_PIC); //設置靜態控件窗口風格為位圖居中顯示 p->ModifyStyle(0xf,SS_BITMAP|SS_CENTERIMAGE); //將圖片設置到Picture控件上 p->SetBitmap(bitmap); }
4.運行結果如下圖所示:
5.總結
通過上麵的截圖我們可以發現:該方法是通過資源ID來獲取BMP圖片的,所以我稱之為靜態的方法.同時,可能你見到過在添加Picture控件時修改其Type為Bitmap在通過image選擇ID的方法.但這裏是通過代碼來實現的,而且ModifyStyle函數的功能就相當於設置其屬性.
~~上圖很明顯的反應了它顯示圖片時,如果圖片尺寸超過控件size隻能顯示部分圖片.方法我隻敘述到這,需要你自己去嚐試.曾經在單文檔中顯示BMP圖片時,是通過重載onpaint事件,GetClientRect獲取尺寸調用StretchBlt(圖像可拉伸壓縮)實現(參照前文).
其實LoadBitmap函數已被LoadImage替代,該函數用於裝載圖標\光標\位圖.如下代碼所示可以實現同樣的效果,其中Rockies.bmp為本地文件,與程序相同文件夾.
void CShowBmpDlg::OnBnClickedButton1() { //獲取對話框上圖片控件的句柄 CStatic* pWnd = (CStatic*)GetDlgItem(IDC_STATIC_PIC); //設置靜態控件窗口風格為位圖居中顯示 pWnd->ModifyStyle(0xf,SS_BITMAP|SS_CENTERIMAGE); //顯示圖片 pWnd->SetBitmap((HBITMAP)::LoadImage(NULL, _T("Rockies.bmp"), //資源號或本地文件名 IMAGE_BITMAP, //裝載位圖 IMAGE_CURSOR光標 IMAGE_ICON圖標 0, //寬度 0為默認大小 0, //高度 像素為單位 LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE)); }
二.動態加載bmp圖片
動態添加的方法一樣,隻是添加代碼如下(這結合我以前的代碼完成).主要的步驟是:
1.先定義打開文件對話框,通過它獲取bmp圖片,其中dlg.DoMal()==IDOK表示按下確認按鈕,實現後麵操作.如果你學過C#就會發現它的OpenFileDialog控件與這個有些類似.
2.然後,獲取讀取文件的路徑和後綴,確保其為bmp時執行讀取圖片信息,在"2.MFC-bmp圖片讀取保存"中,我曾詳細講述過如何讀取bmp圖片,這裏也是二進製讀取文件,讀取其文件頭(BITMAPFILEHEADER)、信息頭(BITMAPINFOHEADER)、獲取其位圖數據.
3.最後顯示圖像到Picture控件中,並通過GetClientRect函數獲取矩形區域,顯示圖像.
void CShowBmpDlg::OnBnClickedButton1() { //打開文件 定義四種格式的文件bmp gif jpg tiff CString filter; filter="所有文件(*.bmp,*.jpg,*.gif,*tiff)|*.bmp;*.jpg;*.gif;*.tiff| BMP(*.bmp)|*.bmp| JPG(*.jpg)|*.jpg| GIF(*.gif)|*.gif| TIFF(*.tiff)|*.tiff||"; CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY,filter,NULL); //按下確定按鈕 dlg.DoModal() 函數顯示對話框 if( dlg.DoModal() == IDOK ) { //打開對話框獲取圖像信息 CString BmpName = dlg.GetPathName(); //獲取文件路徑名 如D:\pic\abc.bmp CString EntName = dlg.GetFileExt(); //獲取文件擴展名 EntName.MakeLower(); //將文件擴展名轉換為一個小寫字符 if(EntName.Compare(_T("bmp")) == 0) { //定義變量存儲圖片信息 BITMAPINFO *pBmpInfo; //記錄圖像細節 BYTE *pBmpData; //圖像數據 BITMAPFILEHEADER bmpHeader; //文件頭 BITMAPINFOHEADER bmpInfo; //信息頭 CFile bmpFile; //記錄打開文件 //以隻讀的方式打開文件 讀取bmp圖片各部分 bmp文件頭 信息 數據 if(!bmpFile.Open(BmpName, CFile::modeRead|CFile::typeBinary)) return; if (bmpFile.Read(&bmpHeader,sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER)) return; if (bmpFile.Read(&bmpInfo,sizeof(BITMAPINFOHEADER)) != sizeof(BITMAPINFOHEADER)) return; pBmpInfo = (BITMAPINFO *)new char[sizeof(BITMAPINFOHEADER)]; //為圖像數據申請空間 memcpy(pBmpInfo,&bmpInfo,sizeof(BITMAPINFOHEADER)); DWORD dataBytes = bmpHeader.bfSize - bmpHeader.bfOffBits; pBmpData = (BYTE*)new char[dataBytes]; bmpFile.Read(pBmpData,dataBytes); bmpFile.Close(); //顯示圖像 CWnd *pWnd=GetDlgItem(IDC_STATIC_PIC); //獲得pictrue控件窗口的句柄 CRect rect; pWnd->GetClientRect(&rect); //獲得pictrue控件所在的矩形區域 CDC *pDC=pWnd->GetDC(); //獲得pictrue控件的DC pDC->SetStretchBltMode(COLORONCOLOR); StretchDIBits(pDC->GetSafeHdc(),0,0,rect.Width(),rect.Height(),0,0, bmpInfo.biWidth,bmpInfo.biHeight,pBmpData,pBmpInfo,DIB_RGB_COLORS,SRCCOPY); } } }
運行程序顯示結果如下圖所示,點擊按鈕打開圖片,顯示圖片.
總結:通過這個程序你可以很明顯的看到動態加載圖片由於是通過獲取picture控件矩形來顯示圖的,圖像被拉伸了.而且代碼很好的反應了如何獲取bmp圖像的方法.通過靜態的和動態的兩種方法講述.
~~最後希望該文章對大家有所幫助,如果文章中有錯誤或不足之處,還請海涵.
(By:Eastmount 2014-5-21 夜2點半 原創CSDN
https://blog.csdn.net/eastmount/)
PS:《數字圖像處理》課程希望大家也可以學習下,你可以自己完成一個軟件,你將對圖像有更深的認識.以前我們要求實現的功能就包括:圖像載入保存、采樣量化、直方圖顯示、線性和非線性變換(對比度拉伸、圖像均衡化)、幾何運算(最近鄰差值和雙線性差值)、幾何變換(平移、反轉、旋轉)、圖像增強(平滑、銳化Laplacian等各種算子)、邊緣檢測、圖像編碼壓縮(Huffman編碼和遊程編碼)、圖像分割複原、二值圖像細化等功能.記得最蛋疼的是DICOM醫學圖像在Android顯示與處理花了很長時間才完成的.
最後更新:2017-04-03 08:26:12