用戶自定義協議之串口發送與接收


 

效果圖:

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("\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:  }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM