zoukankan      html  css  js  c++  java
  • 用户自定义协议之串口发送与接收

    效果图:

    image

    开发过程:

    一、数据发送端程序讲解

    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("
    ");
      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("
    ");
     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:  }
  • 相关阅读:
    [转载] kill命令
    [转载] Linux的Top命令解析
    json互相转换
    C# 13位时间戳(unix时间戳)
    第八篇:cx_Oracle出现的问题
    linux:eth网卡对应的物理网口判断
    ls显示前几行或后几行数据
    第七篇:suds.TypeNotFound: Type not found: '(string, http://schemas.xmlsoap.org/soap/encoding/, )'
    第六篇:python中numpy.zeros(np.zeros)的使用方法
    第五篇:selenium调用IE问题(Protected Mode settings are not the same for all zones)
  • 原文地址:https://www.cnblogs.com/zhuxuekui/p/3552352.html
Copyright © 2011-2022 走看看