最近由于项目需要自学了MFC的界面设置(初学者),在基本功能设置完成之后,老大觉得并不需要了,也就没被采纳。但我觉得还是以博客的形式写出来,既能回顾一下学习过程,又能帮助大家。
开发环境
MFC的开发环境是Visual C++,也叫VC++。MFC(Microsoft Foundation Classes)是微软基础类库的简称,是一个微软实现的C++类库,主要封装大部分的Windows API函数,并且包含一个应用程序框架,以减少应用程序开发人员工作量。MFC除了是一个类库以外,还是一个框架,在vc++里新建一个MFC的工程,开发环境会自动帮你产生许多文件,同时它使用了mfcxx.dll。xx是版本,它封装了mfc内核,所以你在你的代码看不到原本的SDK编程中的消息循环等等东西,这样你就可以专心的考虑你程序的逻辑,而不是这些每次编程都要重复的东西,但是由于是通用框架,没有最好的针对性,当然也就丧失了一些灵活性和效率但是MFC的封装很浅,所以效率上损失不大,灵活性还可以,虽然也有很多缺陷,但还是一个比较好的东西。
附上vc++安装包以及其他资料
链接:https://pan.baidu.com/s/14lo6nnW7aficYnDEENWfqA
提取码:9ydy
复制这段内容后打开百度网盘手机App,操作更方便哦
控件布局与设置
解压缩完成并安装完成后,我们就开始建立MFC界面。
1.双击Visual C++,出现如下窗口。
2.关闭每日提示之后,点击file -> new(新建)会出现新建工程窗口。选择MFC AppWizard[exe],并为工程命名(例如:博客撰写),选择保存工程的位置,最后点击确定。
3.点击确定之后出现MFC应用程序向导窗口
步骤一:在您要创建的应用程序类型是:基本对话框。其余默认,然后点击下一步(也可以直接点击完成)。
步骤二:可以对对话框的标题进行修改(我这采用的默认)。其余默认,然后点击完成。(要是想看后面的步骤可以点击下一步)
步骤三:出现一个新建工程的信息,包括工程的应用类型,被创建的类型以及特点。若是有问题点击取消,若是没有点击确定。
4.点击确定之后会出现对话框。
界面上的按钮放置在如下对话框中。
可以删除上面的两个按键和一个静态文本。在控件工具栏中拖入三个静态文本框,三个编辑框,六个按钮。若是没有控件工具栏,就在菜单栏空白处右击鼠标,选择控件。布局之后的效果如下:
5.接下来就是设置每个编辑框,按钮的名称及其属性。
选中静态文本,右击鼠标->属性,在常规一项中ID不用改,标题修改为接受数据,按回车键确认。修改其余两个静态文本方法同上。效果图如下:
选中按钮1(Button 1),右击鼠标->属性,常规一项中ID修改为IDC_BtnOpen,标题修改为打开串口。按照上述方法修改其余5个按钮(ID分别为IDC_BtnSave,IDC_BtnStart,IDC_BtnStop,IDC_BtnDlt,IDC_BtnSend。标题分别为保存数据,定时发送,停止,删除数据,发送数据,ID与标题一一对应是为了编程的方便)。效果图如下:
选中接受数据静态文本框下面的编辑框,右击鼠标->属性,常规一项中ID修改为IDC_EditRxData,样式一项中选择–多行,垂直滚动,自动垂直滚动,需要返回,只读。
选中定时发送数据静态文本框下面的编辑框,右击鼠标->属性,常规一项中ID修改为IDC_EditSend,样式一项中选择–多行,垂直滚动,自动垂直滚动,需要返回。
选中发送数据静态文本框下面的编辑框,右击鼠标->属性,常规一项中ID修改为IDC_EditTxData,样式一项中选择–多行,垂直滚动,自动垂直滚动,需要返回。
效果图如下:
这些步骤完成之后,点击Build->组建或者直接点击键盘F7,编译一次,看是否出错,避免影响到后面的操作。
接下来是最重要的一步,决定了能否与单片机通讯:
对话框或者中间空白处右击鼠标->插入ActiveX控件,下拉,选择Microsoft Communication Control,ver…,就会在界面框出现黄色电话标志。效果图如下:
选中该电话右击->建立类向导。效果图如下:
在Message Maps一项, 选择IDC_BtnOpen->BN_CLICKEN->Add Function,默认函数名就行,然后点击OK。效果图如下:
设置每个控件的变量。在Member Variables一项,IDC_BtnDlt->Add Variable,会弹出Add Member Variable,在Member Variable name一栏中填写与该按键ID相同的名字,只是为了方便记忆,可以随意写。 效果图如下:
同理添加其他控件的变量,在添加在添加MSCOMM1的变量时,会出现提示,选择“是”。设置变量名为m_Comm1,点击OK,点击确定。
再次编译运行一次,确认是否有错。
代码的添加
添加代码的方式有两种:第一种,直接双击按钮,进入代码编辑区。第二种:选择左边信息栏的File View->双击CommTestDlg.cpp,在文件尾部可以看到刚刚添加的三个函数。效果图如下:
六个按钮的代码如下图:
void CTem_Dlg::OnBtnDlt()
{
// TODO: Add your control notification handler code here
if(IDYES == AfxMessageBox("是否删除数据?",MB_YESNO))
{
SetDlgItemText(IDC_EditTxData," ");
SetDlgItemText(IDC_EditRxData," ");
GetDlgItem(IDC_EditTxData)->SetFocus();
}
}
void CTem_Dlg::OnBtnOpen()
{
// TODO: Add your control notification handler code here
if(m_Comm.GetPortOpen())
m_Comm.SetPortOpen(FALSE);
m_Comm.SetCommPort(4);
m_Comm.SetInBufferSize(1024);
m_Comm.SetOutBufferSize(1024);
if(!m_Comm.GetPortOpen())
m_Comm.SetPortOpen(TRUE);
else
AfxMessageBox("cannot open serial port");
m_Comm.SetSettings("9600,n,8,1");
m_Comm.SetInputMode(1);
m_Comm.SetRThreshold(1);
m_Comm.SetInputLen(0);
m_Comm.GetInput();
}
void CTem_Dlg::OnBtnSave()
{
// TODO: Add your control notification handler code here
CString PathName,str;
CFileDialog fileDlg(FALSE,_T("txt"),NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
_T("txt Files(*.txt)|*.txt|All Files(*.*)|*.*||"),NULL);
CFile file;
int nlen;
fileDlg.m_ofn.lpstrTitle = "保存文件";
if(fileDlg.DoModal()==IDOK)
{
/*char *pLocale=_strdup(setlocale(LC_CTYPE,NULL));
setlocale(LC_CTYPE,"chs");*/
PathName = fileDlg.GetPathName();
file.Open(PathName,CFile::modeCreate|CFile::modeWrite|CFile::typeText);
nlen = GetDlgItem(IDC_EditRxData)->GetWindowTextLength();
GetDlgItemText(IDC_EditRxData,str);
file.Write(str,nlen);
file.Close();
}
}
void CTem_Dlg::OnBtnSend()
{
UpdateData(TRUE);
m_Comm.SetOutput(COleVariant(m_EditTxData));
GetDlgItem(IDC_EditTxData)->SetFocus();
}
void CTem_Dlg::OnOnCommMscomm1()
{
// TODO: Add your control notification handler code here
VARIANT variant_inp;
COleSafeArray safearray_inp;
BYTE rxdata[2048];
LONG len,k;
CString str;
if(m_Comm.GetCommEvent() == 2)
{
variant_inp=m_Comm.GetInput();
safearray_inp = variant_inp;
len = safearray_inp.GetOneDimSize();
for(k=0;k<len;k++)
{
safearray_inp.GetElement(&k,rxdata+k);
}
for(k = 0;k<len;k++)
{
BYTE bt= *(char*)(rxdata+k);
str.Format("%c",bt);
m_EditRxData += str;
UpdateData(FALSE);
CEdit *pedit = (CEdit *)GetDlgItem(IDC_EditRxData);
int nline = pedit->GetLineCount();
pedit->LineScroll(nline-1);
}
}
}
//以上为Debug版本,需要使用release版本才能无错使用。
void CTem_Dlg::OnBtnStart()
{
SetTimer(1,5000,NULL);
}
void CTem_Dlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
UpdateData(TRUE);
m_Comm.SetOutput(COleVariant(m_EditSend));
CDialog::OnTimer(nIDEvent);
}
void CTem_Dlg::OnBtnStop()
{
KillTimer(1);
GetDlgItem(IDC_EditSend)->SetFocus();
}
最终效果图如下:
PS:上述过程只是完成了上位机的工作,要最终能够发送和接收数据,还需要单片机配合工作,因此单片机还是需要下载相对应的程序。