本篇继续上篇的未完部分。前面介绍完了控制台版本下的所有例子,几乎可以涵盖训练的所有方面,本篇继续介绍MFC对话框版本的案例,通过文件系统遍历目录来解决数据文件名称的问题,即不再限定文件名称必须为数字。
6. MFC对话框版本的批量数据训练
前面描述的多个版本适用于数据来源可控的情形,然后一旦数据来源五花八门的话,再想保证目录名称和文件名称的统一、数字化,就比较困难了,因而才有了本篇内容的介绍。在通过文件系统遍历的方式下,只要数据内容没有问题即可,对目录名称和文件名称没有任何限制,可以随意命名。但是,需要提出的是,受文件系统本身的影响,这种方式的训练时间会更长,甚至会在数据量过大时导致系统不稳定,所以不建议使用,作为代替,可以使用这种方式重命名文件和重组织目录结构,然后沿用前述的控制台版本下的训练方式。
(1)创建项目并导入SDK
按照前面文章的介绍创建MFC对话框项目,详细内容请参考前面的文章。结果如下图所示:
对话框正中间的文本标签的ID为IDC_STATIC,“确定”按钮的ID为IDOK,我们简单地沿用这两个控件,文本标签用于显示所选择的数据存放目录,将“确定”按钮的Caption改为“开始训练”并用于触发神经网络的训练操作。另外,添加一个按钮控件到对话框上用于选择数据存放的目录(所有数据的根目录),将其ID改为IDC_BTN_FIND,将其Caption改为“选择目录”。调整大小、排列位置,结果如下图所示:
按照前面文章的介绍将SDK文件拷贝过来,并将Inter.h文件添加到项目中,然后在testDlg.cpp的头部添加如下代码来引入SDK:
#include "Inter.h" #pragma comment(lib, "AIWZQDll.lib")
(2)实现“选择目录”按钮
在界面设计的对话框上双击“选择目录”按钮来添加该按钮的单击事件,然后在该事件响应函数内添加代码如下:
void CtestDlg::onBnClickedBtnFind()
{
TCHAR chPath[255] = { 0 }; //用来存储路径的字符串
CString strPath;
BROWSEINFO bInfo;
ZeroMemory(&bInfo, sizeof(bInfo));
bInfo.hwndOwner = m_hWnd;
bInfo.lpszTitle = _T("请选择数据文件所在的目录");
bInfo.ulFlags = BIF_RETURNonLYFSDIRS | BIF_EDITBOX;
LPITEMIDLIST lpDlist; //用来保存返回信息的IDList
lpDlist = SHBrowseForFolder(&bInfo); //显示选择对话框
if (lpDlist != NULL) //用户按了确定按钮
{
SHGetPathFromIDList(lpDlist, chPath);//把项目标识列表转化成字符串
strPath = chPath; //将TCHAR类型的字符串转换为CString类型的字符串
((CEdit*)GetDlgItem(IDC_STATIC))->SetWindowText(strPath);
}
}
该函数先定义并初始化了一些变量,然后调用SHBrowseForFolder()函数来显示目录选择对话框,在选好目录并点击“确定”按钮之后,将所选中的目录显示在对话框的文本标签中,运行结果如下图所示:
这里所选中的目录将用于“开始训练”按钮,因此,在testDlg.h文件中添加一个类变量m_strPath来代替本函数中的strPath,以便通用。另外,还要在CtestDlg::onInitDialog()函数中将m_strPath置为空以免在目录选择之前出现干扰。如下图所示:
(3)实现“开始训练”按钮
在界面设计的对话框上双击“开始训练”按钮来添加该按钮的单击事件,然后在该事件响应函数内删除原代码并添加代码如下:
void CtestDlg::onBnClickedOk()
{
FILE* pFile = NULL;
int nPieces = 0;
int narrSteps[1000] = { 0 };
int* parrSteps = NULL;
char strName[256] = { 0 };
CFileFind objFinder;
CString strFileName;
if (objFinder.FindFile(m_strPath + _T(")
: CDialogEx(IDD_TEST_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINframe);
}
void CtestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CtestDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_FIND, &CtestDlg::OnBnClickedBtnFind)
ON_BN_CLICKED(IDOK, &CtestDlg::OnBnClickedOk)
END_MESSAGE_MAP()
// CtestDlg 消息处理程序
BOOL CtestDlg::onInitDialog()
{
CDialogEx::onInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_aboutBOX 必须在系统命令范围内。
ASSERT((IDM_aboutBOX & 0xFFF0) == IDM_aboutBOX);
ASSERT(IDM_aboutBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNamevalid;
CString straboutMenu;
bNamevalid = straboutMenu.LoadString(IDS_aboutBOX);
ASSERT(bNamevalid);
if (!straboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_aboutBOX, straboutMenu);
}
}
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
m_strPath.Empty();
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CtestDlg::onSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_aboutBOX)
{
CaboutDlg dlgabout;
dlgabout.DoModal();
}
else
{
CDialogEx::onSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CtestDlg::onPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::onPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CtestDlg::onQueryDragIcon()
{
return static_cast(m_hIcon);
}
void CtestDlg::onBnClickedBtnFind()
{
TCHAR chPath[255] = { 0 }; //用来存储路径的字符串
BROWSEINFO bInfo;
ZeroMemory(&bInfo, sizeof(bInfo));
bInfo.hwndOwner = m_hWnd;
bInfo.lpszTitle = _T("请选择数据文件所在的目录");
bInfo.ulFlags = BIF_RETURNonLYFSDIRS | BIF_EDITBOX;
LPITEMIDLIST lpDlist; //用来保存返回信息的IDList
lpDlist = SHBrowseForFolder(&bInfo); //显示选择对话框
if (lpDlist != NULL) //用户按了确定按钮
{
SHGetPathFromIDList(lpDlist, chPath);//把项目标识列表转化成字符串
m_strPath = chPath; //将TCHAR类型的字符串转换为CString类型的字符串
((CEdit*)GetDlgItem(IDC_STATIC))->SetWindowText(m_strPath);
}
}
void CtestDlg::onBnClickedOk()
{
FILE* pFile = NULL;
int nPieces = 0;
int narrSteps[1000] = { 0 };
int* parrSteps = NULL;
char strName[256] = { 0 };
CFileFind objFinder;
CString strFileName;
if (objFinder.FindFile(m_strPath + _T("
extern "C" __declspec(dllexport) bool TrainNetwork(int* pnarrData, int nPieces, int nBoardWidth, int nBoardHeight);



