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