MFC 對話方塊Picture Control(圖片控制元件)中靜態和動態顯示Bmp圖片
最近有同學問我如何實現MFC基於對話方塊在圖片控制元件中載入圖片?其實使用MFC顯示圖片的方法各種各樣,但是還是有些同學不知道怎樣顯示.以前在《數字影象處理》課程中完成的軟體都是基於單文件的程式,這裡介紹兩種在對話方塊picthre控制元件中顯示BMP圖片的最簡單基礎的方法.
~~方法可能並不完美,高手忽略,但是提供一種能執行的方法,希望對剛接觸這方面知識的同學有所幫助.可能你覺得文章過於簡單或者有些過於詳細敘述(點到即可我並不反對),但也為哪些入門同學想想,當初自己也是一頭霧水.
一.靜態顯示bmp圖片
1.建立MFC基於對話方塊程式,新增一個button1和picture控制元件,其中“資源檢視”中編輯picture控制元件ID為:IDC_STATIC_PIC.
2.在"資源檢視"(如果沒有,檢視中可調用出來)中右鍵滑鼠Dialog處,選擇"新增資源".在對話方塊中選擇Bitmap,點選"匯入",選擇本地bmp圖片(建議點陣圖放置在res資料夾中)
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影象的方法.通過靜態的和動態的兩種方法講述.
~~最後希望該文章對大家有所幫助,如果文章中有錯誤或不足之處,還請海涵.
)
PS:《數字影象處理》課程希望大家也可以學習下,你可以自己完成一個軟體,你將對影象有更深的認識.以前我們要求實現的功能就包括:影象載入儲存、取樣量化、直方圖顯示、線性和非線性變換(對比度拉伸、影象均衡化)、幾何運算(最近鄰差值和雙線性差值)、幾何變換(平移、反轉、旋轉)、影象增強(平滑、銳化Laplacian等各種運算元)、邊緣檢測、影象編碼壓縮(Huffman編碼和遊程編碼)、影象分割復原、二值影象細化等功能.記得最蛋疼的是DICOM醫學影象在Android顯示與處理花了很長時間才完成的.