【52】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/914969.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/914969.shtml

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

相关文章

笔试——Day12

文章目录第一题题目思路代码第二题题目&#xff1a;思路代码第三题题目&#xff1a;思路代码第一题 题目 删除公共字符 思路 模拟&#xff1a; 遇到需要删除的字符&#xff0c;则不添加到结果中 代码 第二题 题目&#xff1a; 两个链表的第一个公共结点 思路 模拟&#x…

SpringMVC @ResponseBody注解详解

概要ResponseBody是 Spring MVC 中的一个重要注解&#xff0c;用于指示方法的返回值应该直接作为 HTTP 响应体返回&#xff0c;而不是解析为视图名称。基本功能ResponseBody主要用于将Java对象转换为HTTP响应体&#xff08;通常是JSON或XML&#xff09;绕过视图解析器直接返回数…

剑指offer——模拟:顺时针打印矩阵

模拟vector.size返回的是矩阵的行数&#xff0c;vector[0].size返回的是矩阵的列数先排除传入的矩阵是空矩阵先计算上下左右的边界只要边界不重合&#xff0c;就不停止输出&#xff0c;完成一个部分的打印&#xff0c;就将当前的一个边界回收不可以在for循环结束的时候一起判断…

electron-vite实践成品项目

羊驼的工具箱 项目地址 推荐使用该版本 并且使用yarn进行安装 node版本:v22.16.0 技术栈&#xff1a;electron vue3 vite pinia vuetify3 sequelize sqlite Q:为什么vue3要用 vue2的写法 A:其实是因为刚开始用vue3的写法感觉超级恶心 对属性的赋值和方法的管理可观性…

自学中医笔记(一)

我的中医自学笔记 Q&A 自学原因&#xff1a;最开始我也不太信中医&#xff0c;我室友也说中医太玄学了。由于我从小一直都很瘦&#xff0c;吃饭每次都吃得少&#xff0c;上大学那会儿171cm最多也才101斤&#xff0c;而且一年胃病要犯好几次&#xff0c;后来无意中收获了一篇…

3.1 WPF画折线图、直方图、饼状图

本文看了博客WPF编程&#xff0c;Live Charts使用说明&#xff08;2&#xff09;——使用_func<chartpoint, string> labelpoint-CSDN博客&#xff0c;这里作为笔记用。 1.前端代码 前端XAML文件代码如下&#xff1a; <Window x:Class"livechart1.MainWindow&…

如何通过ATS/HTTPS数据防篡改来加密视频?

文章目录前言一、什么是ATS/HTTPS数据防篡改&#xff1f;二、ATS/HTTPS数据防篡改的实现原理三、如何零代码实现ATS/HTTPS数据防篡改来加密视频总结前言 未经保护的视频流极易在传输途中遭遇窃听、拦截或恶意篡改&#xff0c;不仅损害内容价值&#xff0c;更可能引发严重的安全…

Python并发模型:多线程与多进程的优劣对比与实战应用

文章目录多线程基础概念多进程基础概念多线程的优劣势多进程的优劣势实战应用&#xff1a;网络爬虫实战应用&#xff1a;图像处理Python作为一门功能强大的编程语言&#xff0c;提供了多种并发模型&#xff0c;使得我们能够在同一时间执行多个任务&#xff0c;从而提高程序的执…

Spring Boot 整合 Nacos 实战教程:服务注册发现与配置中心详解

Spring Boot 整合 Nacos 教程&#xff08;3000字&#xff09; 一、Nacos 简介 Nacos 是阿里巴巴开源的一个动态服务发现、配置管理和服务管理平台&#xff0c;致力于帮助开发者更轻松地构建云原生应用。它支持多种注册中心协议&#xff08;如 Dubbo、Spring Cloud、Kubernete…

VMware 虚拟机装 Linux Centos 7.9 保姆级教程(附资源包)

安装 VMware 17.5.1 centos 7.9 ​ 1、下载资源包&#xff08;虚拟机镜像&#xff09; VMware-17.5.1 安装包秘钥.zipLinux Centos 7.9 镜像 2、centos 7.9 下载地址 1、Centos 官网 2、阿里巴巴镜像站 3、查看网络命令 ifconfig 或 ip addr 4、登陆服务器 ssh stark192.168.3…

STM32超声波模块

一&#xff1a;超声波模块1&#xff1a;工作原理采用IO触发测距&#xff0c;给至少10us的高电平信号。 模块自动发送8个40KHz的方波&#xff0c;自动检测是否有信号返回。 有信号返回&#xff0c;通过IO输出一高电平&#xff0c;高电平持续时间就是超声波从发射到返回的时间声波…

RK3568项目(十一)--linux驱动开发之mipi屏幕调试

目录 一、引言 二、MIPI DSI 屏幕 ------>2.1、MIPI联盟 ------------>2.1.1、多媒体部分 ------------>2.1.2、硬件协议 ------------>2.1.3、D-PHY功能模式及速率 ------------>2.1.4、分辨率计算 ------>2.2、MIPI-DSI硬件连接 ------>2.3、传…

C语言小游戏——飞机大战

目录 引言 开发环境与工具准备 1. 开发环境配置 2. 资源文件准备 游戏设计与架构 1. 游戏核心数据结构 2. 游戏全局变量 游戏核心功能实现 1. 游戏初始化 2. 游戏主循环 3. 游戏渲染 4. 游戏状态更新 关键游戏机制实现 1. 敌机生成系统 2. 碰撞检测系统 3. 敌机…

SQLite的可视化界面软件的安装

1、如下图所示&#xff0c;DB Browser软件&#xff0c;在压缩包中。2、首先解压到一个文件夹中。例如&#xff08;D:\\DB Browser&#xff09;文件夹。解压后的内容如下图。3、将解压后的DB Browser文件夹&#xff0c;剪切到D:\Program Files\目录中。如下两图。win10操作系统下…

基于 STM32H743VIT6 的边缘 AI 实践:猫咪叫声分类 CNN 网络部署实战(已验证)中一些bug总结

前言前面发了一篇文章基于 STM32H743VIT6 的边缘 AI 实践&#xff1a;猫咪叫声分类 CNN 网络部署实战&#xff08;已验证&#xff09;。这里面有一些我遇到过的bug&#xff0c;当时基本都花了很长的时间才解决。这里将这些bug总结一下方便后续查阅。1.使用cubemx插件解析AI模型…

【机器学习】突破分类瓶颈:用逻辑回归与Softmax回归解锁多分类世界

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

Android gradle plugin agp8.6.1发布时间

Android gradle plugin agp8.6.1发布时间 Android Gradle Plugin (AGP) 的版本 8.6.1 是在2023年发布的。具体来说&#xff0c;它是在2023年4月发布的。这个版本的更新包括了多个重要的改进和修复&#xff0c;旨在提升开发者在Android开发过程中的体验和效率。 主要更新包括&am…

闭包的两种设计模式

闭包设计模式 概述 闭包是 JavaScript 中的一个重要概念&#xff0c;它允许内层函数访问外层函数的变量。在实际开发中&#xff0c;闭包经常被用于实现特定的设计模式&#xff0c;主要包括辅助函数模式和工厂模式。 1. 辅助函数模式&#xff08;Helper Function Pattern&#x…

力扣119:杨辉三角Ⅱ

力扣119:杨辉三角Ⅱ题目思路代码题目 给定一个非负索引 rowIndex&#xff0c;返回「杨辉三角」的第 rowIndex 行。 思路 杨辉三角的规律&#xff1a; 第n行有n1个数&#xff0c;n从0开始每行的第一个数和最后一个数都是1。除了第一行的数其他的数都是由它左上角和右上角的…

@Linux自建证书 Nginx+HTTPS

文章目录Linux自建证书并配置Nginx HTTPS1. 准备工作2. 安装必要的工具3. 自建证书脚本3.1 创建CA根证书&#xff08;可选&#xff0c;用于自签名证书链&#xff09;3.2 创建服务器证书脚本4. 证书文件说明5. 配置Nginx使用HTTPS5.1 创建证书存放目录5.2 配置Nginx站点5.3 启用…