1. 程式人生 > >用MFC的對話方塊製作一個簡易的圖片瀏覽器

用MFC的對話方塊製作一個簡易的圖片瀏覽器

環境:VS2012,OpenCV 2.4.9

功能描述:

功能1:點選OPEN按鈕,選擇圖片並開啟,下方顯示圖片的資訊;

功能2:把圖片拖曳到OPEN按鈕上,也可以實現開啟功能,支援多檔案同時開啟

意義:MFC練手程式,涉及一些知識點

過程:

1、前期工作

建立MFC工程,命名“showPicture”,取消unicode,選擇對話方塊,其它預設;

選擇Release;

新增opencv的包含目錄和庫目錄,新增依賴項。

2、對話方塊編輯

a.刪除“TODO: 在此放置對話方塊控制元件。”控制元件,把“確認”和“取消”控制元件的“Visible”屬性設為False;

b.新增Button控制元件,修改以下屬性:

ID:IDC_BUTTON_OPEN

Acccept Files:True

Caption:OPEN

c.新增Group Box 控制元件,Caption屬性改為information;

d.新增5個Static Text控制元件,Caption屬性依次改為filename、format、depth、h、w;

e.每個Static Text控制元件對應新增一個Edit Contral控制元件,ID依次為IDC_EDIT_filename、IDC_EDIT_FORMAT、IDC_EDIT_DEPTH、IDC_EDIT_H、IDC_EDIT_W,全部的Read Only屬性設為True,依次新增成員變數Edit_filename、Edit_format、Edit_depth、Edit_h、Edit_w

f.對文字框左對齊和頂端對齊

如圖:

3、編碼實現功能1

a.新增標頭檔案image.h

#pragma once

#pragma comment(lib,"opencv_highgui249.lib")
#pragma comment(lib,"opencv_core249.lib")
#pragma comment(lib,"opencv_imgproc249.lib")

#include <opencv2/opencv.hpp>

#define EPS  2.2204E-16

using namespace std;
using namespace cv;

class image
{
public:
	image(void);
	~image(void);

public:
	Mat img;
};

b.為OPEN按鈕新增事件處理程式OnBnClickedButtonOpen()

void CshowPictureDlg::OnBnClickedButtonOpen()
{
	// TODO: 在此新增控制元件通知處理程式程式碼

	CFileDialog fDlg(TRUE, _TEXT("*"), NULL, 4|2,  
        _TEXT("全部檔案(*.*)|*.*|全部檔案(*.*)|*.*||"));  
  
    // 呼叫 DoModal() 方法來開啟對話方塊  
    if (fDlg.DoModal() == IDOK)  
    {  
        // 設定編輯框1的內容為選擇檔案的路徑  
        // GetPathName() --> 返回選定檔案的完整路徑  
		CString path;
        path = fDlg.GetPathName(); 

		if(!path.IsEmpty())
		{
			img = imread((LPCSTR)path,CV_LOAD_IMAGE_ANYCOLOR);

			CString imageName; 
			imageName = path;
			imageName.MakeReverse();
			int index=imageName.Find('\\');
			imageName = imageName.Left(index);
			imageName.MakeReverse();

			//顯示影象資訊
			CString info;
			
			info.Format("%d",img.rows);
			Edit_h.SetWindowText(info);

			info.Format("%d",img.cols);
			Edit_w.SetWindowText(info);

			int depth;
			switch(img.depth())
			{
			case 0 :;
			case 1 :depth=8;break;
			case 2 :;
			case 3 :depth=16;break;				
			}
			info.Format("%d",depth);
			Edit_depth.SetWindowText(info+"bits");

			index = imageName.Find('.');
			info = imageName.Right(imageName.GetLength()-index-1);
			Edit_format.SetWindowText(info);

			info = imageName;
			Edit_filename.SetWindowText(info);

			//顯示影象
			namedWindow((LPCSTR)imageName, CV_WINDOW_NORMAL);
			resizeWindow((LPCSTR)imageName,img.cols,img.rows);
			imshow((LPCSTR)imageName,img);
		}
	}

}
showPictureDlg.h中新增
#include "image.h"
以及新增成員變數
private:
	Mat img;

至此,執行程式可以實現功能1。

4、編碼實現功能2

在3的基礎上繼續;

a.用類嚮導新增一個MFC類,基類為CButton,類名為CFileButton,該類用於實現拖曳檔案至OPEN按鈕並開啟的功能;

b.為CFileButton新增ON_WM_DROPFILES訊息,並編輯訊息函式

// CFileButton 訊息處理程式

void CFileButton::OnDropFiles(HDROP hDropInfo)
{
	// TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值

	destroyAllWindows();

	char *lpszFileName=new char[512]; 
	int nFileCount,i; 

	nFileCount=::DragQueryFile   
		(hDropInfo,0xFFFFFFFF,NULL,512); 

	CString   path;
	UINT   nChars;
	Mat img;

	for   (i=0;i <   nFileCount;i++) 
	{ 
	
		nChars=::DragQueryFile 
						(hDropInfo,i,&lpszFileName[0],512); 
		path = lpszFileName;
		path = path.Left(nChars);

		if(!path.IsEmpty())
		{
			img = imread((LPCSTR)path,CV_LOAD_IMAGE_ANYCOLOR);

			if(!img.empty())
			{
				CString imageName; 
				imageName = path;
				imageName.MakeReverse();
				int index=imageName.Find('\\');
				imageName = imageName.Left(index);
				imageName.MakeReverse();

				//顯示影象資訊		
				HWND   hWnd   =   ::FindWindow(NULL,"showPicture"); 

				info.h.Format("%d",img.rows);
				info.w.Format("%d",img.cols);
				int depth;
				switch(img.depth())
				{
				case 0 :;
				case 1 :depth=8;break;
				case 2 :;
				case 3 :depth=16;break;				
				}
				info.depth.Format("%d",depth);
				index = imageName.Find('.');
				info.format = imageName.Right(imageName.GetLength()-index-1);
				info.filename = imageName;
				 
				HWND   hEdit   =   ::GetDlgItem(hWnd,IDC_EDIT_H); // 取得控制元件的指標
				::SendMessage(hEdit,WM_SETTEXT,0,(LPARAM)(LPCSTR)(info.h));
				hEdit   =   ::GetDlgItem(hWnd,IDC_EDIT_W); // 取得控制元件的指標
				::SendMessage(hEdit,WM_SETTEXT,0,(LPARAM)(LPCSTR)(info.w));
				hEdit   =   ::GetDlgItem(hWnd,IDC_EDIT_DEPTH); // 取得控制元件的指標
				::SendMessage(hEdit,WM_SETTEXT,0,(LPARAM)(LPCSTR)(info.depth));
				hEdit   =   ::GetDlgItem(hWnd,IDC_EDIT_FORMAT); // 取得控制元件的指標
				::SendMessage(hEdit,WM_SETTEXT,0,(LPARAM)(LPCSTR)(info.format));
				hEdit   =   ::GetDlgItem(hWnd,IDC_EDIT_filename); // 取得控制元件的指標
				::SendMessage(hEdit,WM_SETTEXT,0,(LPARAM)(LPCSTR)(info.filename));

				//顯示影象
				namedWindow((LPCSTR)imageName, CV_WINDOW_NORMAL);
				resizeWindow((LPCSTR)imageName,img.cols,img.rows);
				imshow((LPCSTR)imageName,img);
			}
			else
			{
				MessageBox("fail to open!");
				return;
			}
		}
		else
		{
			MessageBox("path is invalid!");
			return;
		}
	} 

	::DragFinish   (hDropInfo);       //釋放記憶體 
	i=0; 
	delete   []lpszFileName; 
}

FileButton.h中新增成員變數

public:
        struct info
	{
		CString depth;
		CString format;
		CString filename;
		CString h;
		CString w;
	}info;
並新增
#include "image.h"
c.把CFileButton類繫結到OPEN按鈕

修改showPictureDlg.h

新增成員變數

public:
           CFileButton m_FileButton;
新增標頭檔案
#include "FileButton.h"

修改showPictureDlg.cpp

改寫對話方塊的DoDataExchange函式

void CshowPictureDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDIT_H, Edit_h);					
	DDX_Control(pDX, IDC_EDIT_W, Edit_w);					
	DDX_Control(pDX, IDC_EDIT_FORMAT, Edit_format);			
	DDX_Control(pDX, IDC_EDIT_DEPTH, Edit_depth);			
	DDX_Control(pDX, IDC_EDIT_filename, Edit_filename);		
	DDX_Control(pDX, IDC_BUTTON_OPEN, m_FileButton);//增加了這一句
}

至此,執行程式可以實現功能2和功能1。

附:涉及的知識點

1、CString的使用,例如字串的提取、型別轉換

參考:

2、拖曳檔案的功能

參考:

3、SendMessage向控制元件傳送訊息。為什麼要用這種方式?在對話方塊原本的cpp裡是不需要這麼麻煩的,但因為這裡自定義了一個CFileButton類,不能通過Edit控制元件的成員變數來傳值,只能用這種方法。

參考:

4、擴充套件控制元件功能的一種辦法。這裡通過新建一個CFileButton類,使Button控制元件支援檔案拖曳的功能。很奇怪的一點:Button控制元件有一個接受檔案的屬性,但為什麼就沒有一個類似OnDropFiles的事件處理程式?或者是我不知道而已。

還有一種方法是自定義控制元件,但感覺挺麻煩的。這裡要實現的功能比較簡單,可能這種方式可用於實現一些複雜的功能。