用户自定义协议之串口发送与接收
效果图:
开发过程:
一、数据发送端程序讲解
1、规定协议规范,利用虚拟串口工具VSPD来模拟两个串口com2与com3。
2、制作对话框界面,如上左图所示。并为控件添加相应的变量及函数。
3、在工程中插入MSComm控件,并为其绑定CMSComm类的变量m_Comm。
4、为对话框类添加一个bool型变量,用于标识串口是否打开,进而对某些按钮进行使能处理。这里需要添加函数:
1: void CSDataSenderProDlg::UpdateButton(void)
2: {
3: GetDlgItem(IDC_BUTTON_OPEN) ->EnableWindow(m_bIsPortOpen==FALSE);
4: GetDlgItem(IDC_BUTTON_CLOSE) ->EnableWindow(m_bIsPortOpen==TRUE);
5: GetDlgItem(IDC_BUTTON_SEND) ->EnableWindow(m_bIsPortOpen==TRUE);
6: }
5、为打开串口按钮添加函数。双击即可,其实就是串口的初始化函数。
1: void CSDataSenderProDlg::OnBnClickedButtonOpen()
2: {
3: // TODO: 在此添加控件通知处理程序代码
4: m_Comm.put_CommPort(2);
5: m_Comm.put_InputMode(1);
6: m_Comm.put_Settings(_T("9600,n,8,1"));
7: m_Comm.put_InBufferSize(1024);
8: m_Comm.put_OutBufferSize(512);
9: if(!m_Comm.get_PortOpen())
10: {
11: m_Comm.put_PortOpen(TRUE);
12: }
13: m_Comm.put_RThreshold(1);
14: m_Comm.put_InputLen(0);
15: m_Comm.get_Input();
16: m_bIsPortOpen = TRUE;//标识串口打开与否的状态
17: UpdateButton();//更新按钮状态
18:
19: }
6、为关闭串口按钮添加函数。
1: void CSDataSenderProDlg::OnBnClickedButtonClose()
2: {
3: // TODO: 在此添加控件通知处理程序代码
4: if(m_Comm.get_PortOpen()) //如果串口是打开的,手动关闭之
5: {
6: m_Comm.put_PortOpen(FALSE);
7: }
8: m_bIsPortOpen = FALSE;
9: UpdateButton();
10: }
7、为MSComm控件的OnComm事件添加处理代码,用来接收发送端回传回来的数据,与上面的进行验证,到底传的对不对。
相当于一次握手。
1: void CSDataSenderProDlg::OnCommMscomm1()
2: {
3: // TODO: 在此处添加消息处理程序代码
4: VARIANT variant_inp;
5: COleSafeArray safearray_inp;
6: LONG len,k;
7: BYTE rxdata[2048];
8: CString strtemp;
9: if(m_Comm.get_CommEvent() == 2)
10: {
11: variant_inp = m_Comm.get_Input();
12: safearray_inp = variant_inp;
13: len = safearray_inp.GetOneDimSize();
14: for(k = 0; k < len; k++)
15: {
16: safearray_inp.GetElement(&k,rxdata+k);
17: }
18: for(k = 0; k < len; k++)
19: {
20: BYTE bt = *(char *)(rxdata + k);
21: strtemp.Format(_T("%c"),bt);
22: m_strRXData += strtemp;
23: }
24: }
25: CString temp = _T("\r\n");
26: m_strRXData += temp;
27: UpdateData(FALSE);//把值传给控件并显示。
28: }
8、为发送数据按钮添加消息处理代码。这是本程序核心部分。在这个程序里面实现了函数的打包过程。
1: void CSDataSenderProDlg::OnBnClickedButtonSend()
2: {
3: // TODO: 在此添加控件通知处理程序代码
4: CString strSend = _T("$");
5: for(int i = 1; i <= 8; i++)
6: {
7: if(GetSwitchStatus(i))
8: {
9: strSend += _T("1");
10: }
11: else
12: {
13: strSend += _T("0");
14: }
15: }
16: strSend += _T("*");
17: m_Comm.put_Output(COleVariant(strSend)); //发送到此已经成功
18: m_strTXData.Format(_T("要发送的数据为:%s"),strSend);
19: UpdateData(FALSE); //这一步,主要是为了显示要发送的内容
20: }
21:
22:
23: bool CSDataSenderProDlg::GetSwitchStatus(UINT i)//辅助函数,用于判断复选框的状态,并返回TRUE或者FALSE;
24: {
25: bool bStatus = FALSE;
26: switch(i)
27: {
28: case 1:
29: bStatus = ((CButton *)GetDlgItem(IDC_CHECK1)) -> GetCheck();break;
30: case 2:
31: bStatus = ((CButton *)GetDlgItem(IDC_CHECK2)) -> GetCheck();break;
32: case 3:
33: bStatus = ((CButton *)GetDlgItem(IDC_CHECK3)) -> GetCheck();break;
34: case 4:
35: bStatus = ((CButton *)GetDlgItem(IDC_CHECK4)) -> GetCheck();break;
36: case 5:
37: bStatus = ((CButton *)GetDlgItem(IDC_CHECK5)) -> GetCheck();break;
38: case 6:
39: bStatus = ((CButton *)GetDlgItem(IDC_CHECK6)) -> GetCheck();break;
40: case 7:
41: bStatus = ((CButton *)GetDlgItem(IDC_CHECK7)) -> GetCheck();break;
42: case 8:
43: bStatus = ((CButton *)GetDlgItem(IDC_CHECK8)) -> GetCheck();break;
44: default:
45: break;
46: }
47:
48: return bStatus;
49: }
9、整个程序代码如下所示:
SDataSenderProDlg.h文件
1:
2: // SDataSenderProDlg.h : 头文件
3: //
4:
5: #pragma once
6: #include "mscomm1.h"
7:
8:
9: // CSDataSenderProDlg 对话框
10: class CSDataSenderProDlg : public CDialogEx
11: {
12: // 构造
13: public:
14: CSDataSenderProDlg(CWnd* pParent = NULL); // 标准构造函数
15:
16: // 对话框数据
17: enum { IDD = IDD_SDATASENDERPRO_DIALOG };
18:
19: protected:
20: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
21:
22:
23: // 实现
24: protected:
25: HICON m_hIcon;
26:
27: // 生成的消息映射函数
28: virtual BOOL OnInitDialog();
29: afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
30: afx_msg void OnPaint();
31: afx_msg HCURSOR OnQueryDragIcon();
32: DECLARE_MESSAGE_MAP()
33: public:
34: CString m_strTXData;
35: CMscomm1 m_Comm;
36: DECLARE_EVENTSINK_MAP()
37: void OnCommMscomm1();
38: CString m_strRXData;
39: bool m_bIsPortOpen;
40: void UpdateButton(void);
41: afx_msg void OnBnClickedButtonOpen();
42: afx_msg void OnBnClickedButtonClose();
43: afx_msg void OnBnClickedButtonSend();
44: bool GetSwitchStatus(UINT i);
45: };
Resource.h文件:
1: //{{NO_DEPENDENCIES}}
2: // Microsoft Visual C++ generated include file.
3: // Used by SDataSenderPro.rc
4: //
5: #define IDM_ABOUTBOX 0x0010
6: #define IDD_ABOUTBOX 100
7: #define IDS_ABOUTBOX 101
8: #define IDD_SDATASENDERPRO_DIALOG 102
9: #define IDR_MAINFRAME 128
10: #define IDC_CHECK1 1000
11: #define IDC_CHECK2 1001
12: #define IDC_CHECK3 1002
13: #define IDC_CHECK4 1003
14: #define IDC_CHECK5 1004
15: #define IDC_CHECK6 1005
16: #define IDC_CHECK7 1006
17: #define IDC_CHECK8 1007
18: #define IDC_EDIT1 1008
19: #define IDC_BUTTON_OPEN 1009
20: #define IDC_BUTTON_CLOSE 1010
21: #define IDC_BUTTON_SEND 1011
22: #define IDC_EDIT2 1012
23: #define IDC_MSCOMM1 1013
24:
25: // Next default values for new objects
26: //
27: #ifdef APSTUDIO_INVOKED
28: #ifndef APSTUDIO_READONLY_SYMBOLS
29: #define _APS_NEXT_RESOURCE_VALUE 133
30: #define _APS_NEXT_COMMAND_VALUE 32771
31: #define _APS_NEXT_CONTROL_VALUE 1014
32: #define _APS_NEXT_SYMED_VALUE 101
33: #endif
34: #endif
SDataSenderProDlg.cpp文件:
1:
2: // SDataSenderProDlg.cpp : 实现文件
3: //
4:
5: #include "stdafx.h"
6: #include "SDataSenderPro.h"
7: #include "SDataSenderProDlg.h"
8: #include "afxdialogex.h"
9: #include "Resource.h"
10: #ifdef _DEBUG
11: #define new DEBUG_NEW
12: #endif
13:
14:
15: // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
16:
17: class CAboutDlg : public CDialogEx
18: {
19: public:
20: CAboutDlg();
21:
22: // 对话框数据
23: enum { IDD = IDD_ABOUTBOX };
24:
25: protected:
26: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
27:
28: // 实现
29: protected:
30: DECLARE_MESSAGE_MAP()
31: };
32:
33: CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
34: {
35: }
36:
37: void CAboutDlg::DoDataExchange(CDataExchange* pDX)
38: {
39: CDialogEx::DoDataExchange(pDX);
40: }
41:
42: BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
43: END_MESSAGE_MAP()
44:
45:
46: // CSDataSenderProDlg 对话框
47:
48:
49:
50:
51: CSDataSenderProDlg::CSDataSenderProDlg(CWnd* pParent /*=NULL*/)
52: : CDialogEx(CSDataSenderProDlg::IDD, pParent)
53: , m_strTXData(_T(""))
54: , m_strRXData(_T(""))
55: , m_bIsPortOpen(false)
56: {
57: m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
58: }
59:
60: void CSDataSenderProDlg::DoDataExchange(CDataExchange* pDX)
61: {
62: CDialogEx::DoDataExchange(pDX);
63: DDX_Text(pDX, IDC_EDIT1, m_strTXData);
64: DDX_Control(pDX, IDC_MSCOMM1, m_Comm);
65: DDX_Text(pDX, IDC_EDIT2, m_strRXData);
66:
67: }
68:
69: BEGIN_MESSAGE_MAP(CSDataSenderProDlg, CDialogEx)
70: ON_WM_SYSCOMMAND()
71: ON_WM_PAINT()
72: ON_WM_QUERYDRAGICON()
73: ON_BN_CLICKED(IDC_BUTTON_OPEN, &CSDataSenderProDlg::OnBnClickedButtonOpen)
74: ON_BN_CLICKED(IDC_BUTTON_CLOSE, &CSDataSenderProDlg::OnBnClickedButtonClose)
75: ON_BN_CLICKED(IDC_BUTTON_SEND, &CSDataSenderProDlg::OnBnClickedButtonSend)
76: END_MESSAGE_MAP()
77:
78:
79: // CSDataSenderProDlg 消息处理程序
80:
81: BOOL CSDataSenderProDlg::OnInitDialog()
82: {
83: CDialogEx::OnInitDialog();
84:
85: // 将“关于...”菜单项添加到系统菜单中。
86:
87: // IDM_ABOUTBOX 必须在系统命令范围内。
88: ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
89: ASSERT(IDM_ABOUTBOX < 0xF000);
90:
91: CMenu* pSysMenu = GetSystemMenu(FALSE);
92: if (pSysMenu != NULL)
93: {
94: BOOL bNameValid;
95: CString strAboutMenu;
96: bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
97: ASSERT(bNameValid);
98: if (!strAboutMenu.IsEmpty())
99: {
100: pSysMenu->AppendMenu(MF_SEPARATOR);
101: pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
102: }
103: }
104:
105: // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
106: // 执行此操作
107: SetIcon(m_hIcon, TRUE); // 设置大图标
108: SetIcon(m_hIcon, FALSE); // 设置小图标
109:
110: // TODO: 在此添加额外的初始化代码
111:
112: return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
113: }
114:
115: void CSDataSenderProDlg::OnSysCommand(UINT nID, LPARAM lParam)
116: {
117: if ((nID & 0xFFF0) == IDM_ABOUTBOX)
118: {
119: CAboutDlg dlgAbout;
120: dlgAbout.DoModal();
121: }
122: else
123: {
124: CDialogEx::OnSysCommand(nID, lParam);
125: }
126: }
127:
128: // 如果向对话框添加最小化按钮,则需要下面的代码
129: // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
130: // 这将由框架自动完成。
131:
132: void CSDataSenderProDlg::OnPaint()
133: {
134: if (IsIconic())
135: {
136: CPaintDC dc(this); // 用于绘制的设备上下文
137:
138: SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
139:
140: // 使图标在工作区矩形中居中
141: int cxIcon = GetSystemMetrics(SM_CXICON);
142: int cyIcon = GetSystemMetrics(SM_CYICON);
143: CRect rect;
144: GetClientRect(&rect);
145: int x = (rect.Width() - cxIcon + 1) / 2;
146: int y = (rect.Height() - cyIcon + 1) / 2;
147:
148: // 绘制图标
149: dc.DrawIcon(x, y, m_hIcon);
150: }
151: else
152: {
153: CDialogEx::OnPaint();
154: }
155: }
156:
157: //当用户拖动最小化窗口时系统调用此函数取得光标
158: //显示。
159: HCURSOR CSDataSenderProDlg::OnQueryDragIcon()
160: {
161: return static_cast<HCURSOR>(m_hIcon);
162: }
163:
164: BEGIN_EVENTSINK_MAP(CSDataSenderProDlg, CDialogEx)
165: ON_EVENT(CSDataSenderProDlg, IDC_MSCOMM1, 1, CSDataSenderProDlg::OnCommMscomm1, VTS_NONE)
166: END_EVENTSINK_MAP()
167:
168:
169: void CSDataSenderProDlg::OnCommMscomm1()
170: {
171: // TODO: 在此处添加消息处理程序代码
172: VARIANT variant_inp;
173: COleSafeArray safearray_inp;
174: LONG len,k;
175: BYTE rxdata[2048];
176: CString strtemp;
177: if(m_Comm.get_CommEvent() == 2)
178: {
179: variant_inp = m_Comm.get_Input();
180: safearray_inp = variant_inp;
181: len = safearray_inp.GetOneDimSize();
182: for(k = 0; k < len; k++)
183: {
184: safearray_inp.GetElement(&k,rxdata+k);
185: }
186: for(k = 0; k < len; k++)
187: {
188: BYTE bt = *(char *)(rxdata + k);
189: strtemp.Format(_T("%c"),bt);
190: m_strRXData += strtemp;
191: }
192: }
193: CString temp = _T("\r\n");
194: m_strRXData += temp;
195: UpdateData(FALSE);//把值传给控件并显示。
196: }
197:
198:
199: void CSDataSenderProDlg::UpdateButton(void)
200: {
201: GetDlgItem(IDC_BUTTON_OPEN) ->EnableWindow(m_bIsPortOpen==FALSE);
202: GetDlgItem(IDC_BUTTON_CLOSE) ->EnableWindow(m_bIsPortOpen==TRUE);
203: GetDlgItem(IDC_BUTTON_SEND) ->EnableWindow(m_bIsPortOpen==TRUE);
204: }
205:
206:
207: void CSDataSenderProDlg::OnBnClickedButtonOpen()
208: {
209: // TODO: 在此添加控件通知处理程序代码
210: m_Comm.put_CommPort(2);
211: m_Comm.put_InputMode(1);
212: m_Comm.put_Settings(_T("9600,n,8,1"));
213: m_Comm.put_InBufferSize(1024);
214: m_Comm.put_OutBufferSize(512);
215: if(!m_Comm.get_PortOpen())
216: {
217: m_Comm.put_PortOpen(TRUE);
218: }
219: m_Comm.put_RThreshold(1);
220: m_Comm.put_InputLen(0);
221: m_Comm.get_Input();
222: m_bIsPortOpen = TRUE;//标识串口打开与否的状态
223: UpdateButton();//更新按钮状态
224:
225: }
226:
227:
228: void CSDataSenderProDlg::OnBnClickedButtonClose()
229: {
230: // TODO: 在此添加控件通知处理程序代码
231: if(m_Comm.get_PortOpen()) //如果串口是打开的,手动关闭之
232: {
233: m_Comm.put_PortOpen(FALSE);
234: }
235: m_bIsPortOpen = FALSE;
236: UpdateButton();
237: }
238:
239:
240: void CSDataSenderProDlg::OnBnClickedButtonSend()
241: {
242: // TODO: 在此添加控件通知处理程序代码
243: CString strSend = _T("$");
244: for(int i = 1; i <= 8; i++)
245: {
246: if(GetSwitchStatus(i))
247: {
248: strSend += _T("1");
249: }
250: else
251: {
252: strSend += _T("0");
253: }
254: }
255: strSend += _T("*");
256: m_Comm.put_Output(COleVariant(strSend)); //发送到此已经成功
257: m_strTXData.Format(_T("要发送的数据为:%s"),strSend);
258: UpdateData(FALSE); //这一步,主要是为了显示要发送的内容
259: }
260:
261:
262: bool CSDataSenderProDlg::GetSwitchStatus(UINT i)
263: {
264: bool bStatus = FALSE;
265: switch(i)
266: {
267: case 1:
268: bStatus = ((CButton *)GetDlgItem(IDC_CHECK1)) -> GetCheck();break;
269: case 2:
270: bStatus = ((CButton *)GetDlgItem(IDC_CHECK2)) -> GetCheck();break;
271: case 3:
272: bStatus = ((CButton *)GetDlgItem(IDC_CHECK3)) -> GetCheck();break;
273: case 4:
274: bStatus = ((CButton *)GetDlgItem(IDC_CHECK4)) -> GetCheck();break;
275: case 5:
276: bStatus = ((CButton *)GetDlgItem(IDC_CHECK5)) -> GetCheck();break;
277: case 6:
278: bStatus = ((CButton *)GetDlgItem(IDC_CHECK6)) -> GetCheck();break;
279: case 7:
280: bStatus = ((CButton *)GetDlgItem(IDC_CHECK7)) -> GetCheck();break;
281: case 8:
282: bStatus = ((CButton *)GetDlgItem(IDC_CHECK8)) -> GetCheck();break;
283: default:
284: break;
285: }
286:
287: return bStatus;
288: }
二、数据接收端程序讲解
1、建立项目,并在对话框中加入需要的控件。
2、插入MSComm控件,并绑定变量m_Comm。
3、为对话框添加一个bool型变量,标识串口的打开与否,以此来使能某个按钮控件。
函数如下:
1: void CSDataReceiverProDlg::UpdateButton(void)
2: {
3: GetDlgItem(IDC_BUTTON_OPEN) ->EnableWindow(m_bIsPortOpen == FALSE);
4: GetDlgItem(IDC_BUTTON_CLOSE) ->EnableWindow(m_bIsPortOpen == TRUE);
5: }
4、为打开串口按钮添加函数:
1: void CSDataReceiverProDlg::OnBnClickedButtonOpen()
2: {
3: // TODO: 在此添加控件通知处理程序代码
4: m_Comm.put_CommPort(3);
5: m_Comm.put_InputMode(1);
6: m_Comm.put_InBufferSize(1024);
7: m_Comm.put_OutBufferSize(512);
8: m_Comm.put_Settings(_T("9600,n,8,1"));
9: if(!m_Comm.get_PortOpen())
10: {
11: m_Comm.put_PortOpen(TRUE);
12: }
13: m_Comm.put_RThreshold(1); //收到一个字符
14: //m_Comm.put_SThreshold(1);
15: m_Comm.put_InputLen(0);
16: m_Comm.get_Input();
17: m_bIsPortOpen = TRUE;
18: UpdateButton();
19: }
5、为关闭串口按钮添加函数:
1: void CSDataReceiverProDlg::OnBnClickedButtonClose()
2: {
3: // TODO: 在此添加控件通知处理程序代码
4: if(m_Comm.get_PortOpen())
5: {
6: m_Comm.put_PortOpen(FALSE);
7: }
8: m_bIsPortOpen = FALSE;
9: UpdateButton();
10: }
6、为OnComm消息处理程序添加接收数据处理函数,其实就是一个拆包的过程。里面用到了CString里面的截取函数Mid等。并用自定义的函数,实现转变PICTURE控件的状态。
另外对于回传的数据的显示汉字部分,个人建议通过串口传递非字符不可取,我们可以在另一方自己手动加上汉字显示部分。没必要将汉字也发过去,当然我们可以发送字母,这个没有问题,发送汉字在另一方会出现乱码,这个不可取。所以,个人建议假如要发送汉字,就不要发了。在另一方加上汉字,其实效果一样。
函数如下:
1: void CSDataReceiverProDlg::OnCommMscomm1()
2: {
3: // TODO: 在此处添加消息处理程序代码
4: VARIANT variant_inp;
5: COleSafeArray safearray_inp;
6: BYTE rxdata[1024];
7: LONG len,k;
8: CString strtemp;
9: if(m_Comm.get_CommEvent()==2)
10: {
11: m_strRXData.Empty();//接收字符清空
12: variant_inp = m_Comm.get_Input();
13: safearray_inp = variant_inp;
14: len = safearray_inp.GetOneDimSize();
15: if(len != 10) //协议要求数据长度为10
16: {
17: MessageBox(_T("不符合协议的数据格式"),_T("提示"));
18: return;
19: }
20: for(k = 0; k < len; k++)
21: {
22: safearray_inp.GetElement(&k,rxdata+k);
23: }
24: for(k = 0; k< len; k++)
25: {
26: BYTE bt = *(char *)(rxdata + k); //获得字符数组中每个字符的内容
27: strtemp.Format(_T("%c"),bt);
28: m_strRXData += strtemp;
29: }
30: //对接收到的数据进行处理
31: if(rxdata[0] == '$' && rxdata[len-1] == '*')//对数据包头与包尾进行判断
32: {
33: CString strSwitch,strBack;
34: strSwitch = m_strRXData.Mid(1,8);//mid函数截取字符串的特定字串
35: for(int i = 0; i < 8; i++)
36: {
37: if(strSwitch.Mid(i,1) == '1')
38: SetSwitchStatus(i+1,TRUE);//自定义函数,用于更新界面
39: else
40: SetSwitchStatus(i+1,FALSE);
41: }
42: strBack = _T("string back:"); //给发送端回传数据
43: strBack += strSwitch;
44: m_Comm.put_Output(COleVariant(strBack));
45: }
46: UpdateData(FALSE);//更新界面,显示控件数据。这句话就是将变量值交给控件去显示
47: }
48: }
49:
50:
51: void CSDataReceiverProDlg::SetSwitchStatus(UINT i, bool bStatus)
52: {
53: if (bStatus)
54: {
55: switch(i)
56: {
57: case 1: //GetDlgItem的返回类型为CWnd,必须强制转换为CStatic类型然后才能调用后面的函数。
58: ((CStatic*)GetDlgItem(IDC_STATIC1))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
59: break;
60: case 2:
61: ((CStatic*)GetDlgItem(IDC_STATIC2))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
62: break;
63: case 3:
64: ((CStatic*)GetDlgItem(IDC_STATIC3))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
65: break;
66: case 4:
67: ((CStatic*)GetDlgItem(IDC_STATIC4))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
68: break;
69: case 5:
70: ((CStatic*)GetDlgItem(IDC_STATIC5))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
71: break;
72: case 6:
73: ((CStatic*)GetDlgItem(IDC_STATIC6))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
74: break;
75: case 7:
76: ((CStatic*)GetDlgItem(IDC_STATIC7))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
77: break;
78: case 8:
79: ((CStatic*)GetDlgItem(IDC_STATIC8))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
80: break;
81: default:
82: break;
83: }
84:
85:
86: }
87: else
88: {
89: switch(i)
90: {
91: case 1:
92: ((CStatic*)GetDlgItem(IDC_STATIC1))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
93: break;
94: case 2:
95: ((CStatic*)GetDlgItem(IDC_STATIC2))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
96: break;
97: case 3:
98: ((CStatic*)GetDlgItem(IDC_STATIC3))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
99: break;
100: case 4:
101: ((CStatic*)GetDlgItem(IDC_STATIC4))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
102: break;
103: case 5:
104: ((CStatic*)GetDlgItem(IDC_STATIC5))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
105: break;
106: case 6:
107: ((CStatic*)GetDlgItem(IDC_STATIC6))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
108: break;
109: case 7:
110: ((CStatic*)GetDlgItem(IDC_STATIC7))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
111: break;
112: case 8:
113: ((CStatic*)GetDlgItem(IDC_STATIC8))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
114: break;
115: default:
116: break;
117: }
118:
119: }
120: }
7、整个函数代码如下:
SDataReceiverProDlg.h 文件:
1:
2: // SDataReceiverProDlg.h : 头文件
3: //
4:
5: #pragma once
6: #include "mscomm1.h"
7:
8:
9: // CSDataReceiverProDlg 对话框
10: class CSDataReceiverProDlg : public CDialogEx
11: {
12: // 构造
13: public:
14: CSDataReceiverProDlg(CWnd* pParent = NULL); // 标准构造函数
15:
16: // 对话框数据
17: enum { IDD = IDD_SDATARECEIVERPRO_DIALOG };
18:
19: protected:
20: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
21:
22:
23: // 实现
24: protected:
25: HICON m_hIcon;
26:
27: // 生成的消息映射函数
28: virtual BOOL OnInitDialog();
29: afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
30: afx_msg void OnPaint();
31: afx_msg HCURSOR OnQueryDragIcon();
32: DECLARE_MESSAGE_MAP()
33: public:
34: CString m_strRXData;
35: bool m_bIsPortOpen;
36: void UpdateButton(void);
37: afx_msg void OnBnClickedButtonOpen();
38: CMscomm1 m_Comm;
39: afx_msg void OnBnClickedButtonClose();
40: DECLARE_EVENTSINK_MAP()
41: void OnCommMscomm1();
42: void SetSwitchStatus(UINT i, bool bStatus);
43: };
Resource.h 文件:
1: //{{NO_DEPENDENCIES}}
2: // Microsoft Visual C++ generated include file.
3: // Used by SDataReceiverPro.rc
4: //
5: #define IDM_ABOUTBOX 0x0010
6: #define IDD_ABOUTBOX 100
7: #define IDS_ABOUTBOX 101
8: #define IDD_SDATARECEIVERPRO_DIALOG 102
9: #define IDR_MAINFRAME 128
10: #define IDI_OPEN 131
11: #define IDI_CLOSE 132
12: #define IDC_BUTTON_OPEN 1000
13: #define IDC_BUTTON_CLOSE 1001
14: #define IDC_STATIC1 1002
15: #define IDC_STATIC2 1003
16: #define IDC_STATIC3 1004
17: #define IDC_STATIC4 1005
18: #define IDC_STATIC5 1006
19: #define IDC_STATIC6 1007
20: #define IDC_STATIC7 1008
21: #define IDC_STATIC8 1009
22: #define IDC_EDIT1 1010
23: #define IDC_MSCOMM1 1011
24:
25: // Next default values for new objects
26: //
27: #ifdef APSTUDIO_INVOKED
28: #ifndef APSTUDIO_READONLY_SYMBOLS
29: #define _APS_NEXT_RESOURCE_VALUE 130
30: #define _APS_NEXT_COMMAND_VALUE 32771
31: #define _APS_NEXT_CONTROL_VALUE 1012
32: #define _APS_NEXT_SYMED_VALUE 101
33: #endif
34: #endif
SDataReceiverProDlg.cpp文件:
1:
2: // SDataReceiverProDlg.cpp : 实现文件
3: //
4:
5: #include "stdafx.h"
6: #include "SDataReceiverPro.h"
7: #include "SDataReceiverProDlg.h"
8: #include "afxdialogex.h"
9: #include "Resource.h"
10:
11: #ifdef _DEBUG
12: #define new DEBUG_NEW
13: #endif
14:
15:
16: // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
17:
18: class CAboutDlg : public CDialogEx
19: {
20: public:
21: CAboutDlg();
22:
23: // 对话框数据
24: enum { IDD = IDD_ABOUTBOX };
25:
26: protected:
27: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
28:
29: // 实现
30: protected:
31: DECLARE_MESSAGE_MAP()
32: };
33:
34: CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
35: {
36: }
37:
38: void CAboutDlg::DoDataExchange(CDataExchange* pDX)
39: {
40: CDialogEx::DoDataExchange(pDX);
41: }
42:
43: BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
44: END_MESSAGE_MAP()
45:
46:
47: // CSDataReceiverProDlg 对话框
48:
49:
50:
51:
52: CSDataReceiverProDlg::CSDataReceiverProDlg(CWnd* pParent /*=NULL*/)
53: : CDialogEx(CSDataReceiverProDlg::IDD, pParent)
54: , m_strRXData(_T(""))
55: , m_bIsPortOpen(false)
56: {
57: m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
58: }
59:
60: void CSDataReceiverProDlg::DoDataExchange(CDataExchange* pDX)
61: {
62: CDialogEx::DoDataExchange(pDX);
63: DDX_Text(pDX, IDC_EDIT1, m_strRXData);
64: DDX_Control(pDX, IDC_MSCOMM1, m_Comm);
65: }
66:
67: BEGIN_MESSAGE_MAP(CSDataReceiverProDlg, CDialogEx)
68: ON_WM_SYSCOMMAND()
69: ON_WM_PAINT()
70: ON_WM_QUERYDRAGICON()
71: ON_BN_CLICKED(IDC_BUTTON_OPEN, &CSDataReceiverProDlg::OnBnClickedButtonOpen)
72: ON_BN_CLICKED(IDC_BUTTON_CLOSE, &CSDataReceiverProDlg::OnBnClickedButtonClose)
73: END_MESSAGE_MAP()
74:
75:
76: // CSDataReceiverProDlg 消息处理程序
77:
78: BOOL CSDataReceiverProDlg::OnInitDialog()
79: {
80: CDialogEx::OnInitDialog();
81:
82: // 将“关于...”菜单项添加到系统菜单中。
83:
84: // IDM_ABOUTBOX 必须在系统命令范围内。
85: ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
86: ASSERT(IDM_ABOUTBOX < 0xF000);
87:
88: CMenu* pSysMenu = GetSystemMenu(FALSE);
89: if (pSysMenu != NULL)
90: {
91: BOOL bNameValid;
92: CString strAboutMenu;
93: bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
94: ASSERT(bNameValid);
95: if (!strAboutMenu.IsEmpty())
96: {
97: pSysMenu->AppendMenu(MF_SEPARATOR);
98: pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
99: }
100: }
101:
102: // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
103: // 执行此操作
104: SetIcon(m_hIcon, TRUE); // 设置大图标
105: SetIcon(m_hIcon, FALSE); // 设置小图标
106:
107: // TODO: 在此添加额外的初始化代码
108:
109: return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
110: }
111:
112: void CSDataReceiverProDlg::OnSysCommand(UINT nID, LPARAM lParam)
113: {
114: if ((nID & 0xFFF0) == IDM_ABOUTBOX)
115: {
116: CAboutDlg dlgAbout;
117: dlgAbout.DoModal();
118: }
119: else
120: {
121: CDialogEx::OnSysCommand(nID, lParam);
122: }
123: }
124:
125: // 如果向对话框添加最小化按钮,则需要下面的代码
126: // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
127: // 这将由框架自动完成。
128:
129: void CSDataReceiverProDlg::OnPaint()
130: {
131: if (IsIconic())
132: {
133: CPaintDC dc(this); // 用于绘制的设备上下文
134:
135: SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
136:
137: // 使图标在工作区矩形中居中
138: int cxIcon = GetSystemMetrics(SM_CXICON);
139: int cyIcon = GetSystemMetrics(SM_CYICON);
140: CRect rect;
141: GetClientRect(&rect);
142: int x = (rect.Width() - cxIcon + 1) / 2;
143: int y = (rect.Height() - cyIcon + 1) / 2;
144:
145: // 绘制图标
146: dc.DrawIcon(x, y, m_hIcon);
147: }
148: else
149: {
150: CDialogEx::OnPaint();
151: }
152: }
153:
154: //当用户拖动最小化窗口时系统调用此函数取得光标
155: //显示。
156: HCURSOR CSDataReceiverProDlg::OnQueryDragIcon()
157: {
158: return static_cast<HCURSOR>(m_hIcon);
159: }
160:
161:
162:
163: void CSDataReceiverProDlg::UpdateButton(void)
164: {
165: GetDlgItem(IDC_BUTTON_OPEN) ->EnableWindow(m_bIsPortOpen == FALSE);
166: GetDlgItem(IDC_BUTTON_CLOSE) ->EnableWindow(m_bIsPortOpen == TRUE);
167: }
168:
169:
170: void CSDataReceiverProDlg::OnBnClickedButtonOpen()
171: {
172: // TODO: 在此添加控件通知处理程序代码
173: m_Comm.put_CommPort(3);
174: m_Comm.put_InputMode(1);
175: m_Comm.put_InBufferSize(1024);
176: m_Comm.put_OutBufferSize(512);
177: m_Comm.put_Settings(_T("9600,n,8,1"));
178: if(!m_Comm.get_PortOpen())
179: {
180: m_Comm.put_PortOpen(TRUE);
181: }
182: m_Comm.put_RThreshold(1); //收到一个字符
183: //m_Comm.put_SThreshold(1);
184: m_Comm.put_InputLen(0);
185: m_Comm.get_Input();
186: m_bIsPortOpen = TRUE;
187: UpdateButton();
188: }
189:
190:
191: void CSDataReceiverProDlg::OnBnClickedButtonClose()
192: {
193: // TODO: 在此添加控件通知处理程序代码
194: if(m_Comm.get_PortOpen())
195: {
196: m_Comm.put_PortOpen(FALSE);
197: }
198: m_bIsPortOpen = FALSE;
199: UpdateButton();
200: }
201: BEGIN_EVENTSINK_MAP(CSDataReceiverProDlg, CDialogEx)
202: ON_EVENT(CSDataReceiverProDlg, IDC_MSCOMM1, 1, CSDataReceiverProDlg::OnCommMscomm1, VTS_NONE)
203: END_EVENTSINK_MAP()
204:
205:
206: void CSDataReceiverProDlg::OnCommMscomm1()
207: {
208: // TODO: 在此处添加消息处理程序代码
209: VARIANT variant_inp;
210: COleSafeArray safearray_inp;
211: BYTE rxdata[1024];
212: LONG len,k;
213: CString strtemp;
214: if(m_Comm.get_CommEvent()==2)
215: {
216: m_strRXData.Empty();//接收字符清空
217: variant_inp = m_Comm.get_Input();
218: safearray_inp = variant_inp;
219: len = safearray_inp.GetOneDimSize();
220: if(len != 10) //协议要求数据长度为10
221: {
222: MessageBox(_T("不符合协议的数据格式"),_T("提示"));
223: return;
224: }
225: for(k = 0; k < len; k++)
226: {
227: safearray_inp.GetElement(&k,rxdata+k);
228: }
229: for(k = 0; k< len; k++)
230: {
231: BYTE bt = *(char *)(rxdata + k); //获得字符数组中每个字符的内容
232: strtemp.Format(_T("%c"),bt);
233: m_strRXData += strtemp;
234: }
235: //对接收到的数据进行处理
236: if(rxdata[0] == '$' && rxdata[len-1] == '*')//对数据包头与包尾进行判断
237: {
238: CString strSwitch,strBack;
239: strSwitch = m_strRXData.Mid(1,8);//mid函数截取字符串的特定字串
240: for(int i = 0; i < 8; i++)
241: {
242: if(strSwitch.Mid(i,1) == '1')
243: SetSwitchStatus(i+1,TRUE);//自定义函数,用于更新界面
244: else
245: SetSwitchStatus(i+1,FALSE);
246: }
247: strBack = _T("string back:"); //给发送端回传数据
248: strBack += strSwitch;
249: m_Comm.put_Output(COleVariant(strBack));
250: }
251: UpdateData(FALSE);//更新界面,显示控件数据。这句话就是将变量值交给控件去显示
252: }
253: }
254:
255:
256: void CSDataReceiverProDlg::SetSwitchStatus(UINT i, bool bStatus)
257: {
258: if (bStatus)
259: {
260: switch(i)
261: {
262: case 1: //GetDlgItem的返回类型为CWnd,必须强制转换为CStatic类型然后才能调用后面的函数。
263: ((CStatic*)GetDlgItem(IDC_STATIC1))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
264: break;
265: case 2:
266: ((CStatic*)GetDlgItem(IDC_STATIC2))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
267: break;
268: case 3:
269: ((CStatic*)GetDlgItem(IDC_STATIC3))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
270: break;
271: case 4:
272: ((CStatic*)GetDlgItem(IDC_STATIC4))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
273: break;
274: case 5:
275: ((CStatic*)GetDlgItem(IDC_STATIC5))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
276: break;
277: case 6:
278: ((CStatic*)GetDlgItem(IDC_STATIC6))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
279: break;
280: case 7:
281: ((CStatic*)GetDlgItem(IDC_STATIC7))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
282: break;
283: case 8:
284: ((CStatic*)GetDlgItem(IDC_STATIC8))->SetIcon(AfxGetApp()->LoadIconW(IDI_OPEN));
285: break;
286: default:
287: break;
288: }
289:
290:
291: }
292: else
293: {
294: switch(i)
295: {
296: case 1:
297: ((CStatic*)GetDlgItem(IDC_STATIC1))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
298: break;
299: case 2:
300: ((CStatic*)GetDlgItem(IDC_STATIC2))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
301: break;
302: case 3:
303: ((CStatic*)GetDlgItem(IDC_STATIC3))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
304: break;
305: case 4:
306: ((CStatic*)GetDlgItem(IDC_STATIC4))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
307: break;
308: case 5:
309: ((CStatic*)GetDlgItem(IDC_STATIC5))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
310: break;
311: case 6:
312: ((CStatic*)GetDlgItem(IDC_STATIC6))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
313: break;
314: case 7:
315: ((CStatic*)GetDlgItem(IDC_STATIC7))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
316: break;
317: case 8:
318: ((CStatic*)GetDlgItem(IDC_STATIC8))->SetIcon(AfxGetApp()->LoadIconW(IDI_CLOSE));
319: break;
320: default:
321: break;
322: }
323:
324: }
325: }