【53】MFC入门到精通——MFC串口助手(二)---通信版(发送数据 、发送文件、数据转换、清空发送区、打开/关闭文件),附源码

文章目录

  • 1 完整 功能展示
  • 2 添加控件变量及声明
    • 2.1 添加控件及变量
    • 2.2 SerialPortDlg.h: 头文件
  • 3 函数实现
    • 3.1 数据发送
      • 3.1.2 写数据、字符串转
    • 3.2 发送文件
      • 3.2.1 打开文件
      • 3.2.2 发送文件
    • 3.3 清空发送区
  • 4 完整MFC项目项下载

1 完整 功能展示

串口通信助手 页面展示,功能齐全,
还增加了串口打开/关闭状态变色,发送按钮状态变色等功能。
发送/接收时,相应按钮,功能禁用/可用等保护措施。

在这里插入图片描述

2 添加控件变量及声明

串口设置等基本功能实现 教程MFC串口助手(一)—初级版(初始化、串口设置、修改参数、打开/关闭、状态显示)

本节将接着上一节教程继续实现 发送数据 、发送文件

2.1 添加控件及变量

  • 添加控件
发送数据的编辑框、按钮;
打开文件、发送文件 按钮;
显示文件路径静态文本框;清空发送区 按钮;

在这里插入图片描述
修改ID如下

发送数据
IDC_EDIT_TXDATA
IDC_BUTTON_SEND
//发送文件
IDC_BUTTON_OPEN_FILE
IDC_BUTTON_SEND_FILE
IDC_STATIC_FILE_PATH
//清空发送区
IDC_BUTTON_CLEAN_SEND
  • 添加控件变量
    (注意下下面 m_sendbutten 控件,类型添加为CButton类型,就可以了。我这里是自己写的一个可变色CCustomButton类型)

方法:选中控件,右键选择添加变量

//CButton m_sendbutten;
CCustomButton m_sendbutten;
CButton m_transfile;
CButton m_emptySendArea;
CStatic m_sfilePath;

2.2 SerialPortDlg.h: 头文件

头文件的其他 变量机函数声明
(下面是 串口助手 全部功能的头文件内容)


// SerialPortDlg.h: 头文件
//#pragma once#include "CCustomButton.h"//UINT ComProce(LPVOID pParam);// CSerialPortDlg 对话框
class CSerialPortDlg : public CDialogEx
{
// 构造
public:CSerialPortDlg(CWnd* pParent = nullptr);	// 标准构造函数//变量=====================================================================================
public://自定义变量HANDLE			m_hCom;					//串口句柄volatile int	m_bConnected;		//串口连接成功指示BOOL			m_COMStatu;				//串口状态指示long			m_rxlen;				//接收数据个数long			m_txlen;				//发送数据个数//列表框变量CComboBox	m_Combo_Com;				//列表框:串口CComboBox	m_Combo_Baud;				//列表框:波特率CComboBox	m_Combo_Check;				//列表框:校验位CComboBox	m_Combo_Data;				//列表框:数据位CComboBox	m_Combo_Stop;				//列表框:停止位//字符变量CString		m_Str_Com;					//字符变量:串口CString		m_Str_Baud;					//字符变量:波特率CString		m_Str_Check;				//字符变量:校验位CString		m_Str_Data;					//字符变量:数据位CString		m_Str_Stop;					//字符变量:停止位//函数=====================================================================================
public://串口相关函数BOOL InitComm();								    //打开串口(不创建线程)BOOL OpenComm(int Num);								//打开串口BOOL SetCommParameter();							//设置串口参数void DisplayStatus();								//显示串口状态void CloseConnection();								//关闭串口//按钮函数afx_msg void OnBnClickedOpencomButton();			//串口状态显示//列表框函数afx_msg void OnCbnSelchangeComboCom();				//更改串口afx_msg void OnCbnSelchangeComboBaud();				//更改波特率afx_msg void OnCbnSelchangeComboCheck();			//更改校验位afx_msg void OnCbnSelchangeComboData();				//更改数据位afx_msg void OnCbnSelchangeComboStop();				//更改停止位// 对话框数据
#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_SERIALPORT_DIALOG };
#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持void OnOK();afx_msg LRESULT OnRecvMsg(WPARAM dwEvent, LPARAM dwLen);
// 实现
protected:HICON m_hIcon;// 生成的消息映射函数virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()//函数=====================================================================================
public://读缓冲区int ReadBlock(BYTE* abIn, int MaxLength);//串口消息处理BOOL ProcessCOMMNotification(UINT wParam, long lParam);	 //串口消息处理//打开串口,创建工作线程(失败)BOOL OpenComm2(int Num);								//打开串口//打开串口,创建工作线程(监听线程,当有数据到达串口时响应)BOOL OpenComm3(int Num);								//打开串口//写串口int WriteBlock(char* abOut, int MaxLength);			//写串口//字符串转十六进制int String2Hex(CString str, char* SendOut);//转十六进制char ConvertHexData(char ch);//显示当前时间int Current_Time();//发送数据afx_msg void OnBnClickedButtonSend();afx_msg void OnTimer(UINT_PTR nIDEvent);//变量=====================================================================================
public://根据代码中报错未定义的变量,自己补充的,有些类型可能错误CString m_savefilename;// = _T("D:\\Projects\\MFC\\SerialPort-2\\test.txt");//十六进制显示和保存到文件控件,添加控件变量CButton m_writetofile;CButton m_ctrlHexDisplay;//给IDC_EDIT_RXDATA编辑框,添加控件变量和值变量CString m_strRXData;CEdit m_EditRXData;CButton m_cHexSend;OVERLAPPED m_osWrite;OVERLAPPED m_osRead;//发送按钮,添加控件变量// 发送数据、文件//CButton m_sendbutten;CCustomButton m_sendbutten;CButton m_transfile;CButton m_emptySendArea;CStatic m_sfilePath;CButton m_emptyReceiveArea;CMFCButton m_button_ComOpenStatus;afx_msg void OnBnClickedButtonCleanSend();afx_msg void OnBnClickedButtonCleanReceive();//发送文件afx_msg void OnBnClickedButtonOpenFile();afx_msg void OnBnClickedButtonSendFile();afx_msg void OnBnClickedButtonClearCount();afx_msg void OnBnClickedCheckSvaeFile();afx_msg void OnBnClickedButtonSavePath();
};

3 函数实现

#define MAXBLOCK 1024

3.1 数据发送

//数据发送函数
void CSerialPortDlg::OnBnClickedButtonSend()
{// TODO: 在此添加控件通知处理程序代码char abOut[MAXBLOCK];int OutNum, length;if (!m_bConnected){AfxMessageBox(_T("串口未打开!"));return;}//发送触发后,发送、清空按钮 禁用,等待发送完毕后恢复可用m_sendbutten.EnableWindow(FALSE);m_transfile.EnableWindow(FALSE);m_emptyReceiveArea.EnableWindow(FALSE);m_emptySendArea.EnableWindow(FALSE);memset(abOut, 0, MAXBLOCK);//判断是否文件写,若是则打开文件并写入缓冲区//读文本框内容CString str;CString strtest;GetDlgItem(IDC_EDIT_TXDATA)->GetWindowText(str);char SendOut[MAXBLOCK];int len = str.GetLength();for (int i = 0; i < len; i++){abOut[i] = str.GetAt(i);//strtest.Format(_T("%c"),abOut[i]);//AfxMessageBox(strtest);}if (m_cHexSend.GetCheck()){CString StrHexData;abOut[len] = NULL;StrHexData = CString(abOut);len = String2Hex(StrHexData, SendOut);length = WriteBlock(SendOut, len);}elselength = WriteBlock(abOut, len);m_txlen += length;if(!length)AfxMessageBox(_T("无数据能写入缓冲区!"));//发送完毕,发送、清空按钮 恢复可用m_sendbutten.EnableWindow(TRUE);m_transfile.EnableWindow(TRUE);m_emptyReceiveArea.EnableWindow(TRUE);m_emptySendArea.EnableWindow(TRUE);DisplayStatus();return;
}

3.1.2 写数据、字符串转

数据发送中涉及两个函数 :WriteBlock、WriteBlock

//写串口
int CSerialPortDlg::WriteBlock(char* abOut, int MaxLength)
{BOOL JudgeWrite;//写入串行端口数据操作的返回值COMSTAT ComStat;//通信状态缓冲区的指针DWORD dwErrorFlags, dwLength, lentest;//接收错误代码变量的指针,要写的字节数,被写入的字节数的变量地址m_osWrite.Offset = 0;ClearCommError(m_hCom, &dwErrorFlags, &ComStat);//清除串行端口错误或读取串行端口现在的状态==>//串口句柄,接收错误代码变量的指针,通信状态缓冲区的指针if (dwErrorFlags > 0) //如果接收到错误代码{AfxMessageBox(_T("写串口错!请检查参数设置。"));PurgeComm(m_hCom, PURGE_TXABORT | PURGE_TXCLEAR); //清空缓冲区==>return 0;}dwLength = MaxLength;//要写的字节数lentest = 0;//实际字节数的指针置0JudgeWrite = WriteFile(m_hCom, abOut, dwLength, &lentest, &m_osWrite); //写入串行端口数据==>//句柄,预发送的数据,写入的字节数,被写入的字节数的变量地址,OVERLAPPED结构体指针(不使用异步传输设为null)if (!JudgeWrite)//写失败{if (GetLastError() == ERROR_IO_PENDING) //重叠 I/O 操作在进行中。{GetOverlappedResult(m_hCom, &m_osWrite, &lentest, TRUE);//返回重叠操作结果==>//句柄;重叠结构的指针;实际字节数的指针;TRUE,那么只有当操作完成才会返回}elselentest = 0;//实际字节数的指针置0}return lentest;//返回字节数的指针
}
//字符串转十六进制
int CSerialPortDlg::String2Hex(CString str, char* SendOut)
{int hexdata, lowhexdata;int hexdatalen = 0;int len = str.GetLength();//SendOut.SetSize(len/2);for (int i = 0; i < len;){char lstr, hstr = str[i];if (hstr == ' ' || hstr == '\r' || hstr == '\n'){i++;continue;}i++;if (i >= len)break;lstr = str[i];hexdata = ConvertHexData(hstr);lowhexdata = ConvertHexData(lstr);if ((hexdata == 16) || (lowhexdata == 16))break;elsehexdata = hexdata * 16 + lowhexdata;i++;SendOut[hexdatalen] = (char)hexdata;hexdatalen++;}//senddata.SetSize(hexdatalen);return hexdatalen;
}

3.2 发送文件

3.2.1 打开文件

//打开文件
void CSerialPortDlg::OnBnClickedButtonOpenFile()
{// TODO: 在此添加控件通知处理程序代码// 设置过滤器TCHAR szFilter[] = _T("文本文件(*.txt)|*.txt|所有文件(*.*)|*.*||");// 构造打开文件对话框 (TRUE创建打开文件对话框)CFileDialog fileDlg(TRUE, _T("txt"), NULL, 0, szFilter, this);CString strFilePath;// 显示打开文件对话框if (IDOK == fileDlg.DoModal()){// 如果点击了文件对话框上的“打开”按钮,则将选择的文件路径显示到编辑框里strFilePath = fileDlg.GetPathName();SetDlgItemText(IDC_STATIC_FILE_PATH, strFilePath);}
}

3.2.2 发送文件

//发送文件
void CSerialPortDlg::OnBnClickedButtonSendFile()
{// TODO: 在此添加控件通知处理程序代码CString filepath = _T("");       //文件路径char abOut[MAXBLOCK];int OutNum, length;if (!m_bConnected){AfxMessageBox(_T("串口未打开!"));return;}else {// 如果串口连接成功,串口打开按钮 显示绿色,关闭串口m_button_ComOpenStatus.m_bTransparent = FALSE;m_button_ComOpenStatus.m_bDontUseWinXPTheme = TRUE;//消除黑圈//m_button_ComOpenStatus.m_bDrawFocus = FALSE;//消除边框m_button_ComOpenStatus.m_nFlatStyle = CMFCButton::BUTTONSTYLE_NOBORDERS;//设置颜色m_button_ComOpenStatus.SetFaceColor(RGB(0, 255, 0), true);//串口打开状态下,显示绿色,关闭串口m_button_ComOpenStatus.SetWindowTextW(_T("关闭串口"));}//发送触发后,发送、清空按钮 禁用,等待发送完毕后恢复可用m_sendbutten.EnableWindow(FALSE);m_transfile.EnableWindow(FALSE);m_emptyReceiveArea.EnableWindow(FALSE);m_emptySendArea.EnableWindow(FALSE);m_sfilePath.GetWindowText(filepath);memset(abOut, 0, MAXBLOCK);//判断是否文件写,若是则打开文件并写入缓冲区if (!filepath.IsEmpty()){CFile fsendout;CFileException e;fsendout.Open(filepath, CFile::modeRead, &e);OutNum = fsendout.Read(abOut, MAXBLOCK);while (OutNum)//执行循环后,文件已读完。{//如果选择了十六进制发送,则转换为字符形式发送出去,否则直接发送字符数组if (m_cHexSend.GetCheck())//十六进制发送复选框选中时{//如果读到的字符中最后有个单独的数据,则将读取长度退回一if (abOut[OutNum - 1] == ' ' || abOut[OutNum - 1] == '\r\n')OutNum--;if (!OutNum){AfxMessageBox(_T("读十六进制文件出错,请检查格式!"));return;}//将十六进制字符串转换为CString类,为十六进制转换成字符的函数作准备CString StrHexData;abOut[OutNum] = NULL;StrHexData = CString(abOut);char SendOut[MAXBLOCK];int len = String2Hex(StrHexData, SendOut);length = WriteBlock(SendOut, len);}elselength = WriteBlock(abOut, OutNum);m_txlen += OutNum;OutNum = fsendout.Read(abOut, MAXBLOCK);//准备下一次循环//continue;}//while(OutNum)fsendout.Close();if (!length){AfxMessageBox(_T("已写完!"));m_sendbutten.EnableWindow(TRUE);//发送完毕,发送、清空按钮 恢复可用m_sendbutten.EnableWindow(TRUE);m_transfile.EnableWindow(TRUE);m_emptyReceiveArea.EnableWindow(TRUE);m_emptySendArea.EnableWindow(TRUE);DisplayStatus();return;}}//发送完毕,发送、清空按钮 恢复可用m_sendbutten.EnableWindow(TRUE);m_transfile.EnableWindow(TRUE);m_emptyReceiveArea.EnableWindow(TRUE);m_emptySendArea.EnableWindow(TRUE);DisplayStatus();return;
}

3.3 清空发送区

最简单的方法直接让,你编辑框里的内容置为空;

void CSerialPortDlg::OnBnClickedButtonCleanSend()
{// TODO: 在此添加控件通知处理程序代码//GetDlgItem(IDC_EDIT_TXDATA)->SetWindowText(_T("")); //获取端口对话框的句柄并清除SetDlgItemText(IDC_EDIT_TXDATA,_T("")); //获取端口对话框的句柄并清除
}

或者给编辑框添加一个控件变量,

	m_strTXData.Empty();m_EditTXData.SetWindowText(m_strRXData);

4 完整MFC项目项下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/915197.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/915197.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法学习笔记:27.堆排序(生日限定版)——从原理到实战,涵盖 LeetCode 与考研 408 例题

堆排序&#xff08;Heap Sort&#xff09;是一种基于二叉堆数据结构的高效排序算法&#xff0c;由计算机科学家 J. W. J. Williams 于 1964 年提出。它结合了选择排序的思想和二叉堆的特性&#xff0c;具有时间复杂度稳定&#xff08;O (nlogn)&#xff09;、原地排序&#xff…

I/O 多路复用select,poll

目录 I/O多路复用的介绍 多进程/多线程模型的弊端 网络多路复用如何解决问题&#xff1f; 网络多路复用的常见实现方式 常见的开源网络库 select详细介绍 select函数介绍 套接字可读事件,可写事件,异常事件 fd_set类型介绍 select的两次拷贝&#xff0c;两次遍历 se…

最终分配算法【论文材料】

文章目录一、最终分配算法1.1 平衡的情况1.2 不平衡的情况1.3 TDM 约束一、最终分配算法 上一步合法化后&#xff0c;group 的 TDM 情况大致分为两类&#xff0c;一类是平衡的&#xff0c;最大的一些 group 的 TDM 比较接近。另外一种情况就是不平衡的&#xff0c;最大的 group…

《大数据技术原理与应用》实验报告七 熟悉 Spark 初级编程实践

目 录 一、实验目的 二、实验环境 三、实验内容与完成情况 3.1 Spark读取文件系统的数据。 3.2 编写独立应用程序实现数据去重。 3.3 编写独立应用程序实现求平局值问题。 四、问题和解决方法 五、心得体会 一、实验目的 1. 掌握使用 Spark 访问本地文件和 HDFS 文件的…

机器学习漫画小抄 - 彩图版

斯坦福机器学习漫画小抄&#xff0c;中文版来啦&#xff01; 下载地址&#xff1a; 通过网盘分享的文件&#xff1a;机器学习知识点彩图版.pdf 链接: https://pan.baidu.com/s/1-fH9OpC_u_OrTqWy6gVUCA 提取码: 246r

1.初始化

业务模块核心技术栈业务&#xff08;亮点&#xff09;解决方案课程安排01 认识Vue3为什么需要学Vue3?Vue3组合式API体验Vue3更多的优势2 使用create-vue搭建Vue3项目认识 create-vue使用create-vue创建项目3 熟悉项目目录和关键文件项目目录和关键文件4 组合式API - setup选项…

Milvus分布式数据库工作职责

主导腾讯云Milvus服务化项目&#xff0c;设计多租户隔离方案&#xff0c;支撑日均10亿向量请求&#xff0c;延迟降低40%。优化IVF_PQ索引构建流程&#xff0c;通过量化编码压缩使内存占用减少60%&#xff0c;QPS提升35%。开发基于Kubernetes的Milvus Operator&#xff0c;实现自…

FMEA-CP-PFD三位一体数字化闭环:汽车部件质量管控的速效引擎

FMEA-CP-PFD三位一体数字化闭环&#xff1a;汽车部件质量管控的速效引擎 全星FMEA软件系统通过​​FMEA&#xff08;失效模式分析&#xff09;、CP&#xff08;控制计划&#xff09;、PFD&#xff08;过程流程图&#xff09;三大工具的一体化协同管理​​&#xff0c;为汽车部件…

VUE2 学习笔记1

目录 VUE特点 文档tips 开发者工具 从一个Hello world开始 hello world Demo 容器和实例的对应关系 差值语法{{}} VUE特点 构建用户界面&#xff1a;可以用来把数据构建成用户界面。 渐进式&#xff1a;自底向上&#xff0c;可以先从一个非常轻量级的框架开始&#xf…

嵌入式学习系统编程(四)进程

目录 一、进程 1.程序和进程 2.进程的八种状态 3. 几个状态 4.关于进程常用命令 二、关于进程的函数 1.fork 2.面问 3.孤儿进程 后台进程 2. exec函数族 (只保留父子关系&#xff0c;做新的事情) strtok函数 三、进程的结束 1.分类 exit和_exit的区别 wait函数…

Linux中添加重定向(Redirection)功能到minishell

前言&#xff1a;在谈论添加minishell之前&#xff0c;我再重谈一下重定向的具体实现等大概思想&#xff01;&#xff01;&#xff01;方便自己回顾&#xff01;&#xff01;&#xff01; 目录 一、重定向&#xff08;Redirection&#xff09;原理详解 1、文件描述符基础 2、…

Django由于数据库版本原因导致数据库迁移失败解决办法

在django开发中&#xff0c;一般我们初始化一个项目之后&#xff0c;创建应用一般就会生成如下的目录&#xff1a;django-admin startproject myproject python manage.py startapp blogmyproject/ ├── manage.py └── myproject/ | ├── __init__.py | ├── se…

C++STL系列之vector

前言 vector是变长数组&#xff0c;有点像数据结构中的顺序表&#xff0c;它和list也是经常被拿出作对比的&#xff0c; vector使用动态分配数组来存储它的元素。当新元素插入时候&#xff0c;这个数组需要被重新分配大小&#xff0c;如果扩容&#xff0c;因为要开一个新数组把…

Functional C++ for Fun Profit

Lambda Conf上有人讲C函数式编程。在Functional Conf 2019上&#xff0c;就有主题为“Lambdas: The Functional Programming Companion of Modern C”的演讲。演讲者介绍了现代C中函数式编程相关内容&#xff0c;讲解了如何使用Lambda表达式编写符合函数式编程原则的C代码&…

Python基础理论与实践:从零到爬虫实战

引言Python如轻舟&#xff0c;载你探寻数据宝藏&#xff01;本文从基础理论&#xff08;变量、循环、函数、模块&#xff09;启航&#xff0c;结合requests和BeautifulSoup实战爬取Quotes to Scrape&#xff0c;适合零基础到进阶者。文章聚焦Python基础&#xff08;变量、循环、…

ThingJS开发从入门到精通:构建三维物联网可视化应用的完整指南

文章目录第一部分&#xff1a;ThingJS基础入门第一章 ThingJS概述与技术架构1.1 ThingJS平台简介1.2 技术架构解析1.3 开发环境配置第二章 基础概念与核心API2.1 核心对象模型2.2 场景创建与管理2.3 对象操作基础第三章 基础开发实战3.1 第一个ThingJS应用3.2 事件系统详解3.3 …

关于list

1、什么是listlist是一个带头结点的双向循环链表模版容器&#xff0c;可以存放任意类型&#xff0c;需要显式定义2、list的使用有了前面学习string和vector的基础&#xff0c;学习和使用list会方便很多&#xff0c;因为大部分的内容依然是高度重合的。与顺序表不同&#xff0c;…

Mysql 查看当前事务锁

在 MySQL 中查看事务锁&#xff08;锁等待、锁持有等&#xff09;&#xff0c;可以使用以下方法&#xff1a; 一、查看当前锁等待情况&#xff08;推荐&#xff09; SELECTr.trx_id AS waiting_trx_id,r.trx_mysql_thread_id AS waiting_thread,r.trx_query AS waiting_query,b…

【Keil5-map文件】

Keil5-map文件■ map文件■ map文件

k8s 基本架构

基于Kubernetes(K8s)的核心设计&#xff0c;以下是其关键基本概念的详细解析。这些概念构成了K8s容器编排系统的基石&#xff0c;用于自动化部署、扩展和管理容器化应用。### 一、K8s核心概念概览 K8s的核心对象围绕容器生命周期管理、资源调度和服务发现展开&#xff0c;主要包…