【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
英文地址,請注明出處:http://en.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 啟用…