在上一篇博客中我們已經繪制了MFC界面,在這篇博客中我們將添加響應代碼,為MFC框架添加一個最基本的功能:打開一個文件夾。
一、添加相關頭文件
這里頭文件主要包含三類:opencv頭文件、批量讀取文件相關的頭文件、CvvImage。這里需要強調CvvImage這個頭文件,這個是用來關聯OpenCv和picture控件,并且這個頭文件是隸屬于OpenCv1.x的,在2.x版本中已經將這個類移除,因此需要手動下載這兩個文件(CvvImage.h和CvvImage.cpp),下載地址:[CvvImage](http://download.csdn.net/detail/u013088062/9395566)。下載后將這兩個文件放在工程目錄下:

然后在VS的解決方案資源管理器窗口中,右擊該工程,在快捷菜單中選擇“添加->現有項”:

將這兩個文件添加到當前工程中:

添加完成后,可以在代碼中添加響應的頭文件了,建議將include命令添加在GenderRecognitionMFCDlg.h頭文件中:
~~~
#include <iostream>
#include <sstream>
#include <fstream>
#include <opencv2\opencv.hpp>
#include "CvvImage.h"
using namespace std;
using namespace cv;
~~~
這里有兩點需要強調:
(1)#include語句包含兩種形式,“ #include<> ”和“ #include“” ”。這兩種格式的區別在于優先搜索路徑的不同,“ #include<> ”默認優先按照系統路徑進行搜索,“ #include“” ”默認優先搜索當前的工程目錄。
(2)include語句的位置。大型工程中的include語句要注意避免一個重復包含的問題,即要保證每條include語句只執行一次,否則就會出現重定義類型的錯誤。C++提供兩種機制來確保include語句執行的唯一性,一是通過“ifndef”宏來包圍include代碼塊,二是通過“#pragma once”宏來實現,這里默認使用第二種,因此所有的include語句應該位于“#pragma once”語句之后。
二、添加控件響應函數
由于讀取顯示圖片的操作是通過“圖像文件夾”按鈕來控制的,因此需要為這個按鈕添加響應的事件響應函數,方法非常簡單,在資源視圖窗口中雙擊對應控件即可,VS將自動添加響應函數:

三、打開文件夾,讀取圖片路徑
接下來為OnBnClickedButtonImagefile()函數添加批量讀取圖片的代碼。我們這里選用SHBrowseForFolder方法。關于這個方法我之前曾寫過一篇博客來專門介紹,具體參見[一種批量讀取文件的方法——SHBrowseForFolder](http://blog.csdn.net/u013088062/article/details/39137809)。注意一點,在SHBrowseForFolder方法中需要用到dir目錄相關的操作函數(如opendir等),這算是Linux的移植版,因此需要借用dirent.h頭文件,不過我們已經在之前下載的資源中提供了這個文件,只需依據之前CvvImage文件的配置方法,添加到當前工程中即可:

接下來,向CGenderRecognitionMFCDlg類中添加若干成員變量,用以記錄讀取的文件夾以及文件的路徑及屬性,具體需要添加以下四個成員變量,分別是CString m_Path(圖像文件路徑)、char* m_ImageDir(文件結構)、DIR *m_pDir(目錄結構)、struct dirent *m_pEnt(目錄結構),這里以m_pEnt為例,介紹VS中添加類成員變量的方法。在類視圖中,右擊CGenderRecognitionMFCDlg類,在快捷菜單中選擇“添加->添加變量”:

在彈出的向導窗口中,指定變量的屬性,然后單擊“完成”按鈕:

同理,添加其他三個成員變量(注意變量類型):

變量添加完成后,即可向OnBnClickedButtonImagefile()函數中添加相應代碼:
~~~
/**********初始化變量**********/
CString str; //存儲圖像路徑
BROWSEINFO bi; //用來存儲用戶選中的目錄信息
TCHAR name[MAX_PATH]; //存儲路徑
ZeroMemory(&bi,sizeof(BROWSEINFO)); //清空目錄對應的內存
bi.hwndOwner = GetSafeHwnd(); //得到窗口句柄
bi.pszDisplayName = name;
/**********設置對話框并讀取目錄信息**********/
BIF_BROWSEINCLUDEFILES;
bi.lpszTitle = _T("Select folder"); //對話框標題
bi.ulFlags = 0x80; //設置對話框形式
LPITEMIDLIST idl = SHBrowseForFolder(&bi); //返回所選中文件夾的ID
SHGetPathFromIDList(idl,str.GetBuffer(MAX_PATH)); //將文件信息格式化存儲到對應緩沖區中
str.ReleaseBuffer(); //與GerBuffer配合使用,清空內存
m_Path=str; //將路徑存儲在m_path中
if(str.GetAt(str.GetLength()-1)!='\\')
m_Path += "\\";
UpdateData(FALSE);
IMalloc * imalloc = 0;
if (SUCCEEDED(SHGetMalloc(&imalloc)))
{
imalloc->Free (idl);
imalloc->Release();
}
/**********獲取該路徑下的第一個文件**********/
m_ImageDir = (LPSTR)(LPCTSTR)m_Path;
m_pDir = opendir(m_ImageDir);
for (int i = 0; i < 1; i ++) //過濾目錄 .. 和 .
{
m_pEnt = readdir(m_pDir);
}
~~~
有關SHBrowseForFolder的方法介紹,除了之前給出的那篇博客之外,這里再推薦兩篇更為詳細的博客:[文件夾瀏覽(SHBrowseForFolder)](http://www.cnblogs.com/Clingingboy/archive/2011/04/16/2018284.html)以及[使用SHBrowseForFolder函數打開文件目錄對話框](http://www.cppblog.com/franksunny/archive/2010/12/30/137754.html)。
四、簡單調試
完成上面那段代碼之后,進行一下簡單調試。首先按下F7對工程進行編譯,在編譯過程中注意將調試器版本設置為X64(64位)。編譯通過后,設置斷點,按下F5進行調試運行。此時單擊“圖像文件夾”按鈕,將彈出打開文件夾對話框:

選擇一個文件夾,然后查看各個變量的情況:

可見,m_Path保存了當前選擇的文件夾路徑。在下一篇博文中我們將通過這個變量來完成對應文件夾目錄下圖像文件的遍歷和顯示。
?