跟着下文一步一步来,就能做出来整个可以运行的应用程序
准备工作:
->删去自带的确定取消等按钮;
->点击主对话框,在属性栏中找到Caption,修改为“串口调试助手”;
->摆放文本及下拉列表:Static Text和Comb Box控件,同样找到Caption,修改其名称,在Comb Box控件的属性列表中,将Sort改为False(填入数据之后不让系统给我们自动排序),将type改为下拉列表,同时为了方便起见将其ID改为IDC_COMBO_Port;
->选中这两个控件,按住CTRL向下拖拽,复制五份,只需修改控件名称和ID即可;
->在框里放一个按钮,将Caption设置为“打开”,ID修改为IDC_BUTTON_OPEN,在打开的左边有一个指示是否打开的Picture Control控件,将其ID设为IDC_PIC_INDICATOR,为了能让其加载图片,将其Type属性修改为Bitmap,接下来将两个状态图片的image文件夹保存到项目所在文件夹中,并在资源视图中右键Com.rc–添加资源–Bitmap–导入–image文件夹–最下面栏里选择所有文件–选中图片–打开,在资源视图中选择图片,将其ID修改为IDB_BITMAP_GREEN和IDB_BITMAP_RED,接下来选择Picture Control控件的Image属性,选择IDB_BITMAP_RED(串口未打开之前为红灯)
->为了便于美观便于紧凑,放置一个Group Box,将上面几组控件框起来,并将Caption写为“串口设置”;
->接下来对接收区进行布局:首先是16进制的显示,选择Check Box控件,将其ID修改为IDC_CHECK_HEX_RECEIVE,Caption设置为“十六进制显示”,两个按钮:保存数据 IDC_BUTTON_SAVE_FILE和IDC_BUTTON_CLEAR_RECEIVE,为了美观,同样用一个Group Box控件,并将其Caption修改为接受区设置;
->接下来对发送区进行布局:先CTRL接收区向下拖动,修改对应的ID和Caption,之后再添加一个定时发送的Check Box,将其ID修改为IDC_CHECK_TIMER,再选择一个Edit Control控件及Static Text控件设置名字为ms,ID为IDC_EDIT_TIMER。
->接下来设置Comb Box控件中的值,点击控件–属性中选择Data–以第一个为例,输入:COM1;COM2;COM3;COM4;COM5;COM6;COM7;COM8;之后依次类推;
->放置发送区和接收区:选择两个Edit Control,把属性中的Multiline(多行显示,不可能只显示一行)设为TRUE,Want Return设置为TRUE,Vertical Scrollbar(滚动条)设置为TRUE,ID分别为IDC_EDIT_SEND和IDC_EDIT_REVEIVE;再选择一个按钮,ID为IDC_BUTTON_SEND,Caption设为发送,为了美观同样再添加两个Group Box即数据接收区和数据发送区。
布局完成的界面如图所示:
显示默认设置
通俗点说,control就是对应这个控件的,value只对应这个控件的值
->选中串口号对应的下拉列表右键->添加变量->变量名:m_cboPort,默认类型都为CComboBox
->选中波特率对应的下拉列表右键->添加变量->变量名:m_cboBaudRate ,类型为CComboBox,类别为Control的变量,除此之外还要添加一个CString类型,Value类别的变量,变量名:m_strBaudRate(直接操纵这个变量可以获取控件的值)
->选中校验位对应的下拉列表右键->添加变量->变量名:m_cboCheckBit,类型为CComboBox,类别为Control的变量,除此之外还要添加一个CString类型,Value类别的变量,变量名:m_strCheckBit
->选中数据位对应的下拉列表右键->添加变量->变量名:m_cboDateBit,类型为CComboBox,类别为Control的变量,除此之外还要添加一个CString类型,Value类别的变量,变量名:m_strDataBit
->选中停止位对应的下拉列表右键->添加变量->变量名:m_cboStopBit,类型为CComboBox,类别为Control的变量,除此之外还要添加一个CString类型,Value类别的变量,变量名:m_strStopBit
->之后打开Dlg.cpp文件找到初始化函数OnInitDialog(),添加如下代码,在对话框一加载出来的时候就显示默认的值:
// TODO: 在此添加额外的初始化代码
m_cboPort.SetCurSel(0);//cursel默认选择 set 设置 参数:索引第几个 COM1
m_cboBaudRate.SetCurSel(2);//9600
m_cboCheckBit.SetCurSel(0);//NONE
m_cboDateBit.SetCurSel(3);//8
m_cboStopBit.SetCurSel(0);//1
->给两个收发的Edit Control添加变量,变量名为m_editSend,类别为Control,变量名为m_strSend,类别为value,和已有选项的下拉列表控件不一样,在Dlg.cpp文件中的CComDlg::CComDlg写入一条语句,操作m_strSend这个变量就代表操作这个控件当中的数据:
->将剩余控件全部添加变量:
右键红灯–添加变量–变量名m_picIndicator,类型Control;
打开 按钮–添加变量–变量名m_btnOpen,类型Control;
十六进制显示–添加变量–变量名m_chkHexReceive,类型Control;
十六进制发送–添加变量–变量名m_chkHexSend,类型Control;
定时发送–添加变量–变量名m_chkTimer,类型Control;
毫秒旁边的文本框–添加变量–变量名m_editTimer,类型Control,变量名m_uiSec,类型Value,变量类型UINT;
接受框–添加变量–变量名m_editReceive,类型Control,变量名m_strReceive,类型Value,变量类型CString;
接下来添加串口类型的控件
在这之前你需要在度娘上下载一个64位的MSCOMM32.OCX文件,把下载的MSCOMM32.OCX拷贝到C:\Windows\SysWOW64目录,以管理员权限打开DOS命令行窗口:
regsvr32 C:\Windows\SysWOW64\MSCOMM32.OCX
注意:一定要以管理员身份运行cmd,否则成功不了
在主对话框空白地方右击,插入ActiveX控件,选择Microsoft Communications Control,version 6.0(SP6).将其ID修改为IDC_MSCOMM,为控件添加变量,类型 CMscomm,变量名 m_mscomm,类别Control,当变量名添加完之后,就会多一个头文件和.cpp文件。
为“打开”按钮添加消息响应函数
选择上方项目–属性–配置属性(常规)–字符集改为多字节这样就不会在程序中遇到中文之后,插件提示你报错了
首先,在Dlg.cpp文件中插入一个对话框类的函数并在.h文件中声明:
//因为校验位是字符串数据,而我们需要读一位字符,做一个数据转换函数
CString CComDlg::getCheckBit()
{
CString strCheckBit;
switch(m_cboCheckBit.GetCurSel)//获得控件当前的选择索引
{
case 0:strCheckBit = "n"; break;
case 1:strCheckBit = "o"; break;
case 2:strCheckBit = "e"; break;
}
return strCheckBit;
}
在打开按钮的响应函数中写如下代码:
void CComDlg::OnBnClickedButtonOpen()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//将控件中的数据更新到变量中 这样的话操作变量就相当于操作控件
CString strOpen;
GetDlgItemText(IDC_BUTTON_OPEN,strOpen);//把打开按钮的值获取到字符串当中
if (strOpen == "打开")
{
//执行打开串口操作
m_mscomm.put_InBufferSize(1024);//设置接收缓冲区大小
m_mscomm.put_OutBufferSize(1024);//设置发送缓冲区大小
m_mscomm.put_InputLen(0);//全部读取接收缓冲区的数据
m_mscomm.put_InputMode(CMscomm::comInputModeBinary);//二进制方式读写数据
m_mscomm.put_RThreshold(1);//接收缓冲区中有1个或1个以上字符时读取
//获取我们界面中的设置
CString strCheckBit = getCheckBit();
CString strSettings = m_strBaudRate + strCheckBit + m_strDataBit + m_strStopBit;
//"9600 无校验位 8位 1位停止位"
m_mscomm.put_Settings(strSettings);//串口通信时串口参数的设置
m_mscomm.put_CommPort(m_cboPort.GetCurSel()+1);//获取串口号 索引时是从0开始的 所以要加上1
//真正的打开串口
try
{
m_mscomm.put_PortOpen(TRUE);
}
catch (CException* e)
{
MessageBox("端口不存在","打开串口",MB_ICONERROR);//内容 标题 弹出对话框样式
return;//不让程序继续向下走
}
SetDlgItemText(IDC_BUTTON_OPEN,"关闭");//串口打开之后设置按钮显示为“关闭”
CBitmap bitmap;//加载位图
bitmap.LoadBitmap(IDB_BITMAP_GREEN);//打开绿色的图标
HBITMAP hBmp;
hBmp = (HBITMAP)bitmap.GetSafeHandle();//获取句柄
m_picIndicator.SetBitmap(hBmp);//将红灯改为绿灯
}
else
{
//执行关闭串口操作
m_mscomm.put_PortOpen(FALSE);//关闭串口
SetDlgItemText(IDC_BUTTON_OPEN,"打开");//将按钮改为打开
CBitmap bitmap;//加载位图
bitmap.LoadBitmap(IDB_BITMAP_RED);
HBITMAP hBmp;
hBmp = (HBITMAP)bitmap.GetSafeHandle();//获取句柄
m_picIndicator.SetBitmap(hBmp);//将绿灯改为红灯
}
}
碰到这种情况怎么办:
解决办法:在对话框中点击一下该控件右边的向下的小箭头,会弹出几个顶点,用鼠标点住下面最中间的那个向下拖动即可,尽量把对话框中的都拖一下。
注:在C++中,当函数抛出一个返回值时,即使不用try和catch语句,异常还是会被处理的,系统会自动调用默认处理函数unexpected来执行
处理发送和接受
先处理接受:添加事件处理函数
选中MSComm控件–右侧属性选择控件事件(闪电符号)–再OnComm中选择addOnCommMSComm,事件响应函数如下:
void CComDlg::OnCommMscomm()//事件相应函数,任何一个事件都会调用(当接受到数据,自动执行)
{
// TODO: 在此处添加消息处理程序代码
UpdateData(TRUE);
byte rxdata[1024];//char 和BYTE 一个是无符号的,一个是有符号的,占用空间一样大
switch (m_mscomm.get_CommEvent())//获取串口控件上的事件
{
case CMscomm::comEvReceive://如果是我们接收到了数据就执行下面的操作
//1.从串口缓冲区读取数据
m_mscomm.put_InputMode(CMscomm::comInputModeBinary);//以二进制格式读取
VARIANT variant_inp = m_mscomm.get_Input();//将数据读出来
COleSafeArray safearray_inp = variant_inp;//进行变量类型的转换 这两句是固定写法,这么用就行
//2.获取数据的有效长度
long len = safearray_inp.GetOneDimSize();
for (long i = 0;i < len;i++)
{
//3.将读取数据的每一个字符放入到rxdata数组中
safearray_inp.GetElement(&i,rxdata + i);
//将数据显示到接收区的文本框里面
CString strtemp = "";
if (m_chkHexReceive.GetCheck() == 1)//如果十六进制选中
{
//以十六进制显示
strtemp.Format("%02X",rxdata[i]);
m_strReceive = m_strReceive + strtemp + " ";//加个空格
}
else
{
strtemp.Format("%c",rxdata[i]);//以字符格式接收
m_strReceive = m_strReceive + strtemp;
}
}
break;
}
UpdateData(FALSE);//将变量中的数据更新到控件显示
m_editReceive.LineScroll(m_editReceive.GetLineCount());//实现显示窗自动滚动到最后一行
}
发送按钮响应函数如下:
void CComDlg::OnBnClickedButtonSend()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//将控件中的数据更新到变量中
CString strSend;
GetDlgItemText(IDC_BUTTON_SEND,strSend);
if (strSend == "发送")
{
//执行串口发送操作
try
{
if(m_chkHexSend.GetCheck() == 1)//看十六进制有没有被选中
{
//以十六进制发送
CByteArray hexToSend;//定义一个byte数组
hexToSend.RemoveAll();//清空一下
//十六进制格式41 42 43 44
for (int i = 0; i < m_strSend.GetLength(); i+=3)// 41空格为一组
{
CString strtemp = m_strSend.Mid(i,2);//只有前两个才代表十六进制
char *p=strtemp.GetBuffer(2);//CString转char *
hexToSend.Add(strtol(p,NULL,16));//add的是如 41转换为十六进制的一个数
}
m_mscomm.put_Output((COleVariant)hexToSend);
}
else
{
//以字符格式发送
m_mscomm.put_Output((COleVariant)m_strSend);//字符格式发送
}
}
catch (CException* e)
{
MessageBox("端口未打开","发送",MB_ICONERROR);
return;
}
}
如此就可以执行发送功能,我们找到一个USB转RS232的接口,将输入输出两个引脚用杜邦线短接,之后再设备管理器查找到系统自动分配的端口,在我们的软件里打开,执行发送任务:
选择十六进制发送 自动转换对话框的数据
双击十六进制发送控件:
void CComDlg::OnBnClickedCheckHexSend()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//把控件数据更新到变量
if (m_chkHexSend.GetCheck() == 1)//判断有没有被选中
{
//将字符格式转换为十六进制
//为什么使用GetBuffer: vc开发中,在进行字符串参数传递的时候,经常需要使用非常量指针
//而我们通常得到的mfc字符串是CString,之后后需要先进行转换才能进行传递。
char *p = m_strSend.GetBuffer(m_strSend.GetLength());//指向字符串当前内容的指针 移交控制权 参数:修改指针指向的缓冲区长度
m_strSend.ReleaseBuffer();//CString字符串收回控制权
//ReleaseBuffer函数是用来告诉CString对象,你的GetBuffer所引用的内存已经使用完毕,现在必须对它进行封口,
//否则 CString将不会知道它现在所包含的字符串的长度
int length = m_strSend.GetLength();
CString str = "";
for (int i = 0; i < length ; i++)
{
CString strtemp;
strtemp.Format("%02X",p[i]);//转换为十六进制 不足两位,,前面补0输出,如果超过两位,则以实际输出
str = str + strtemp + " ";
}
m_strSend = str.TrimRight(" ");//把最右侧的空格去掉
}
else
{
//将十六进制转换为字符格式
int length = m_strSend.GetLength();
CString str;
for (int i = 0;i < length; i+=3)
{
CString strtemp = m_strSend.Mid(i,2);//空格不取 从第i个索引位置开始,取两个字符
char *p = strtemp.GetBuffer(2);
int num = strtol(p,NULL,16);//把十六进制转换成长整数的形式 参数二:为第一个不能转换的字符的指针
strtemp.Format("%c",num);
str += strtemp;
}
m_strSend = str;
}
UpdateData(FALSE);//把变量数据更新到控件
}
双击十六进制显示控件:
void CComDlg::OnBnClickedCheckHexReceive()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//把控件数据更新到变量
if (m_chkHexReceive.GetCheck() == 1)//判断有没有被选中
{
//将字符格式转换为十六进制
//为什么使用GetBuffer: vc开发中,在进行字符串参数传递的时候,经常需要使用非常量指针
//而我们通常得到的mfc字符串是CString,之后后需要先进行转换才能进行传递。
char *p = m_strReceive.GetBuffer(m_strReceive.GetLength());//指向字符串当前内容的指针 移交控制权 参数:修改指针指向的缓冲区长度
m_strReceive.ReleaseBuffer();//CString字符串收回控制权
//ReleaseBuffer函数是用来告诉CString对象,你的GetBuffer所引用的内存已经使用完毕,现在必须对它进行封口,
//否则 CString将不会知道它现在所包含的字符串的长度
int length = m_strReceive.GetLength();
CString str = "";
for (int i = 0; i < length ; i++)
{
CString strtemp;
strtemp.Format("%02X",p[i]);//转换为十六进制 不足两位,,前面补0输出,如果超过两位,则以实际输出
str = str + strtemp + " ";
}
m_strReceive = str.TrimRight(" ");//把最右侧的空格去掉
}
else
{
//将十六进制转换为字符格式
int length = m_strReceive.GetLength();
CString str;
for (int i = 0;i < length; i+=3)
{
CString strtemp = m_strReceive.Mid(i,2);//空格不取 从第i个索引位置开始,取两个字符
char *p = strtemp.GetBuffer(2);
int num = strtol(p,NULL,16);//把十六进制转换成长整数的形式 参数二:为第一个不能转换的字符的指针
strtemp.Format("%c",num);
str += strtemp;
}
m_strReceive = str;
}
UpdateData(FALSE);//把变量数据更新到控件
}
实现定时发送功能
添加定时器:
类视图–单击CComDlg–属性中选择消息–WM_TIMER–ADD
定时的时间一到,就会执行该函数
void CComDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
switch(nIDEvent)
{
case 1: //如果是定时器1
if (m_chkHexSend.GetCheck() == 1)//判断是十六进制定时发送还是字符格式定时发送
{
//十六进制定时发送
m_mscomm.put_Output((COleVariant)hexToSend);
}
else
{
//字符格式定时发送
m_mscomm.put_Output((COleVariant)strToSend);
}
break;
default:
break;
}
CDialogEx::OnTimer(nIDEvent);
}
同时为了方便起见,我们在ComDlg.h文件里定义两个成员变量:
CByteArray hexToSend;
CString strToSend;
同时我们的发送按钮的响应函数进行修改:
void CComDlg::OnBnClickedButtonSend()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//将控件中的数据更新到变量中
CString strSend;
GetDlgItemText(IDC_BUTTON_SEND,strSend);
if (strSend == "发送")
{
//执行串口发送操作
try
{
if(m_chkHexSend.GetCheck() == 1)//看十六进制有没有被选中
{
//以十六进制发送
// CByteArray hexToSend;//定义一个byte数组
hexToSend.RemoveAll();//清空一下
//十六进制格式41 42 43 44
for (int i = 0; i < m_strSend.GetLength(); i+=3)// 41空格为一组
{
CString strtemp = m_strSend.Mid(i,2);//只有前两个才代表十六进制
char *p=strtemp.GetBuffer(2);//CString转char *
hexToSend.Add(strtol(p,NULL,16));//add的是如 41转换为十六进制的一个数
}
m_mscomm.put_Output((COleVariant)hexToSend);
}
else
{
//以字符格式发送
strToSend = m_strSend;
m_mscomm.put_Output((COleVariant)strToSend);//字符格式发送
}
if (m_chkTimer.GetCheck() == 1)//判断定时发送按钮是否被选中
{
//开始定时发送
SetTimer(1,m_uiSec,NULL);//启动ID为1的定时器 时间间隔为m_uiSec
SetDlgItemText(IDC_BUTTON_SEND,"停止发送");//将发送按钮改为停止发送
m_editSend.SetReadOnly(TRUE);//不允许点击了
m_btnLoadFile.EnableWindow(FALSE);//不允许点击了
m_btnClearSend.EnableWindow(FALSE);
m_btnSaveFile.EnableWindow(FALSE);
m_chkTimer.EnableWindow(FALSE);
m_editTimer.EnableWindow(FALSE);
m_cboPort.EnableWindow(FALSE);
m_cboBaudRate.EnableWindow(FALSE);
m_cboCheckBit.EnableWindow(FALSE);
m_cboDateBit.EnableWindow(FALSE);
m_cboStopBit.EnableWindow(FALSE);
}
}
catch (CException* e)
{
MessageBox("端口未打开","发送",MB_ICONERROR);
return;
}
}
else//不是发送
{
//停止定时发送
KillTimer(1);//关闭定时器
SetDlgItemText(IDC_BUTTON_SEND,"发送");//将发送按钮改为停止发送
m_editSend.SetReadOnly(FALSE);//不允许点击了
m_btnLoadFile.EnableWindow(TRUE);//不允许点击了
m_btnClearSend.EnableWindow(TRUE);
m_btnSaveFile.EnableWindow(TRUE);
m_chkTimer.EnableWindow(TRUE);
m_editTimer.EnableWindow(TRUE);
m_cboPort.EnableWindow(TRUE);
m_cboBaudRate.EnableWindow(TRUE);
m_cboCheckBit.EnableWindow(TRUE);
m_cboDateBit.EnableWindow(TRUE);
m_cboStopBit.EnableWindow(TRUE);
}
}
实时的显示发送和接受的字节数
在.h文件中定义变量 CStatusBarCtrl m_status;
unsigned long m_ulSendNum; 发送的数目
unsigned long m_ulReceiveNum; 接受的数目
在.cpp文件中的OnInitDialog函数里添加:
m_status.Create(WS_CHILD | WS_VISIBLE | SBT_OWNERDRAW, CRect(0,0,0,0), this,0);//创建StatusBar
int partDim[3] = {
300,450,-1};//第一部分大小/第二部分右侧距离最左侧的大小/剩余控件分配给第三部分
m_status.SetParts(3,partDim);//分的是三个部分
m_status.SetText("",0,0);
m_status.SetText("发送:0",1,0);
m_status.SetText("接受:",2,0);
在发送按钮的响应函数中 catch上面添加代码端(截取一部分之前的方便定位):
m_cboDateBit.EnableWindow(FALSE);
m_cboStopBit.EnableWindow(FALSE);
}
CString strSendNum;//发送的数目
if (m_chkHexSend.GetCheck() == 1)
{
//16进制发送
m_ulSendNum += hexToSend.GetCount();
}
else
{
//字符发送
m_ulSendNum += strToSend.GetLength();
}
strSendNum.Format("%d",m_ulSendNum);
strSendNum = "发送:"+strSendNum;
m_status.SetText(strSendNum,1,0);//显示到状态栏
}
再将其拷贝到定时发送中:
void CComDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
switch(nIDEvent)
{
case 1: //如果是定时器1
{
if (m_chkHexSend.GetCheck() == 1)//判断是十六进制定时发送还是字符格式定时发送
{
//十六进制定时发送
m_mscomm.put_Output((COleVariant)hexToSend);
}
else
{
//字符格式定时发送
m_mscomm.put_Output((COleVariant)strToSend);
}
CString strSendNum;//发送的数目
if (m_chkHexSend.GetCheck() == 1)
{
//16进制发送
m_ulSendNum += hexToSend.GetCount();
}
else
{
//字符发送
m_ulSendNum += strToSend.GetLength();
}
strSendNum.Format("%d",m_ulSendNum);
strSendNum = "发送:"+strSendNum;
m_status.SetText(strSendNum,1,0);//显示到状态栏
break;
}
default:
break;
}
CDialogEx::OnTimer(nIDEvent);
}
对接收的代码段添加:
COleSafeArray safearray_inp = variant_inp;//进行变量类型的转换 这两句是固定写法,这么用就行
//2.获取数据的有效长度
long len = safearray_inp.GetOneDimSize();
CString strReveiveNum;
m_ulSendNum += len;
strReveiveNum.Format("%d",m_ulReceiveNum);
strReveiveNum = "接收:" + strReveiveNum;
m_status.SetText(strReveiveNum,2,0);
for (long i = 0;i < len;i++)
{
//3.将读取数据的每一个字符放入到rxdata数组中
safearray_inp.GetElement(&i,rxdata + i);
运行结果如图:
文件载入功能的实现
双击文件载入按钮:
void CComDlg::OnBnClickedButtonLoadFile()
{
// TODO: 在此添加控件通知处理程序代码
m_strSend = "";//清空数据发送区
TCHAR szFilter[] = _T("文本文件(*.txt) | *.txt | 所有文件(*.*) | *.*||");
CFileDialog fileDlg(FALSE, _T("txt"),NULL,0,szFilter,this);//创建一个打开文件的对话框 很好用
//参数一:右上角为打开 参数二 默认打开txt扩展名文件 参数三 默认的文件名 参数四 风格默认0 参数五 参数五 打开所有文件 参数六 指向父窗口
if (fileDlg.DoModal() == IDOK)//判断选择的是打开还是取消 domodal就是关闭的时候是选择的打开还是取消
{
//获取文件路径
CString strFilePath = fileDlg.GetPathName();
CFile file;
char readBuffer[2048];
if (file.Open(strFilePath,CFile ::modeRead))//以只读方式打开文件
{
int nRet = file.Read(readBuffer,2048);//接收数据的缓存区指针/从文件中读取的字节数
for (int i = 0;i < nRet ; i++)
{
CString str;
str.Format("%c",readBuffer[i]);
m_strSend += str;
}
}
UpdateData(FALSE);//从变量更新到控件
}
}
实现保存文件的功能
双击保存数据:
void CComDlg::OnBnClickedButtonSaveFile()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);
TCHAR szFilter[] = _T("文本文件(*.txt) | *.txt | 所有文件(*.*) | *.*||");//设置一个文件过滤器
CFileDialog fileDlg(FALSE, _T("txt"),_T("InitFileName"),OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter,this);//创建一个打开文件的对话框 很好用
//参数一:右上角为打开 参数二 默认打开txt扩展名文件 参数三 默认的文件名 参数四 风格默认0 参数五 参数五 打开所有文件 参数六 指向父窗口
if (fileDlg.DoModal() == IDOK)//判断选择的是打开还是取消 domodal就是关闭的时候是选择的打开还是取消
{
//获取文件路径
CString strFilePath = fileDlg.GetPathName();
CFile file;
if (file.Open(strFilePath,CFile ::modeReadWrite| CFile :: modeCreate))//以读写方式打开文件 | 创建新文件
{
char *p = m_strReceive.GetBuffer(m_strReceive.GetLength());
file.Write(p,m_strReceive.GetLength());//写入数据的指针/写入数据的长度
file.Close();
}
}
}