Visual C++为我们提供了一种好用的ActiveX控件Microsoft Communications Control(即MSComm)来支持应用程序对串口的访问,在应用程序中插入MSComm控件后就可以较为方便地实现对通过计算机串口收发数据。

  要使用ActiveX控件MSComm,程序员必须将其添加入工程,其方法是:

  (1)单击主菜单project的子菜单Add To project的Components and Controls选项;

  (2)在弹出的"Components and Controls Gallery"对话框中选择Registered ActiveX Controls文件夹中的"Microsoft Communications Control,version 6.0"选项

  单击其中的"Insert"按钮,MSComm控件就被增加到工程中了。与此同时,类CMSComm的相关文件mscomm.h和mscomm.cpp也一并被加入Project的Header Files和Source Files中。当然,程序员可以自己修改文件名。直接分析mscomm.h头文件就可以完备地获取这个控件的使用方法(主要是public类型的接口函数),下面我们摘取了头文件的主要代码并对其关键部分给出了注释:

#if !defined(AFX_MSCOMM_H__)
#define AFX_MSCOMM_H__ 
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++

// NOTE: Do not modify the contents of this file. If this class is regenerated by
// Microsoft Visual C++, your modifications will be overwritten.

/
// CMSComm wrapper class

class CMSComm : public CWnd
{
protected:
 DECLARE_DYNCREATE(CMSComm)
public:
 CLSID const& GetClsid()
 {
  static CLSID const clsid = { 0x648a5600, 0x2c6e, 0x101b, { 0x82, 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14 } };
  return clsid;
 }
 virtual BOOL Create(LPCTSTR lpszClassName,
   LPCTSTR lpszWindowName, DWORD dwStyle,
   const RECT& rect,
   CWnd* pParentWnd, UINT nID,
   CCreateContext* pContext = NULL)
 { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID); }

 BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle,
   const RECT& rect, CWnd* pParentWnd, UINT nID,
   CFile* pPersist = NULL, BOOL bStorage = FALSE,
   BSTR bstrLicKey = NULL)
 { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID,
  pPersist, bStorage, bstrLicKey); }

  // Attributes
 public:

  // Operations
 public:
  void SetCDHolding(BOOL bNewValue);
  BOOL GetCDHolding();
  void SetCommID(long nNewValue);
  long GetCommID();
  void SetCommPort(short nNewValue);
  //设置端口号,如nNewValue =1表示COM1
  short GetCommPort();
  void SetCTSHolding(BOOL bNewValue);
  BOOL GetCTSHolding();
  void SetDSRHolding(BOOL bNewValue);
  BOOL GetDSRHolding();
  void SetDTREnable(BOOL bNewValue);
  BOOL GetDTREnable();
  void SetHandshaking(long nNewValue);
  long GetHandshaking();
  void SetInBufferSize(short nNewValue);
  short GetInBufferSize();
  void SetInBufferCount(short nNewValue);
  short GetInBufferCount();
  void SetBreak(BOOL bNewValue);
  BOOL GetBreak();
  void SetInputLen(short nNewValue);
  short GetInputLen();
  void SetNullDiscard(BOOL bNewValue);
  BOOL GetNullDiscard();
  void SetOutBufferSize(short nNewValue);
  short GetOutBufferSize();
  void SetOutBufferCount(short nNewValue);
  short GetOutBufferCount();
  void SetParityReplace(LPCTSTR lpszNewValue);
  CString GetParityReplace();
  void SetPortOpen(BOOL bNewValue);
  //打开或关闭串口,TRUE:打开,FALSE:关闭
  BOOL GetPortOpen();
  //串口是否已打开,TRUE:打开,FALSE:关闭
  void SetRThreshold(short nNewValue);
  //如果设置为1,表示一接收到字符就发送2号事件
  short GetRThreshold();
  void SetRTSEnable(BOOL bNewValue);
  //硬件握手使能?
  BOOL GetRTSEnable();
  void SetSettings(LPCTSTR lpszNewValue);
  //Settings由4部分组成,其格式为:"BBBB,P,D,S",即"波特率,是否奇偶校验,数据位 //个数,停止位",如设置为:"9600,n,8,1"
  CString GetSettings();
  void SetSThreshold(short nNewValue); 
  //如果保持缺省值0不变,则表示发送数据的过程中串口上不发生事件
  short GetSThreshold();
  void SetOutput(const VARIANT& newValue);
  //一个非常重要的函数,用于写串口,注意其接收的输入参数为VARIANT类型对象, 
  //我们需要将字符串转化为VARIANT类型对象
  VARIANT GetOutput();
  void SetInput(const VARIANT& newValue);
  VARIANT GetInput();
  //一个非常重要的函数,用于读串口,注意其返回的是VARIANT类型对象,我们需要
  //将其转化为字符串
  void SetCommEvent(short nNewValue);
  short GetCommEvent();
  //一个非常重要的函数,获得串口上刚发生的事件("事件"可以理解为软件意义上的
  //"消息"或硬件意义上的"中断"),事件的发送会导致OnComm消息的诞生!
  void SetEOFEnable(BOOL bNewValue);
  BOOL GetEOFEnable();
  void SetInputMode(long nNewValue);
  long GetInputMode();
 };

 //{{AFX_INSERT_LOCATION}}
 // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif

  分析上述源代码可知,基本上,MSComm的诸多接口可以分为如下几类:

  (1)打开与设置串口接口函数;

  (2)获得串口设置和串口状态接口函数;

  (3)设置串口发送数据方式、缓冲区接口及发送数据接口函数;

  (4)设置串口接收数据方式、缓冲区接口及接收数据接口函数;

  (5)设置与获取串口上发生的事件接口函数。

2.例程

  程序的功能和界面(如下图)都与本文连载三中《基于WIN32 API的串口编程》相同,不同的只是连载三的串口通信以API实现,而本节的串口通信则以MSComm控件实现。

  使用第1节的方法将控件添加入工程并添加mscomm.h和mscomm.cpp文件后,为了使用控件,我们将控件拖入对话框内任意一个位置(运行时"电话"图标会隐藏),其操作如下图:

  有趣而极富人性化的是我们可以直接右键单击这个"电话",来设置串口的属性,如下图:

  接着,我们需要为控件添加一个对应的成员变量m_mscom,其对应的变量类型为CMSComm,如下图:

  这样就建立了m_mscom和IDC_MSCOMM1控件的相互映射:

void CSerialPortActivexDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CSerialPortActivexDlg)
  DDX_Text(pDX, IDC_RECV_EDIT, m_recv);
  DDX_Text(pDX, IDC_SEND_EDIT, m_send);
  DDX_Control(pDX, IDC_MSCOMM1, m_mscom);
 //}}AFX_DATA_MAP
}

  同时,在对话框的头文件也会由"MFC类向导"自动定义CSerialPortActivexDlg类的CMSComm型成员变量m_mscom:

CMSComm m_mscom;

  在对话框初始化时(即在CSerialPortActivexDlg::OnInitDialog函数中)打开串口1:

BOOL CSerialPortActivexDlg::OnInitDialog()
{
 CDialog::OnInitDialog();

 // Add "About..." menu item to system menu.

 // IDM_ABOUTBOX must be in the system command range.
 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 ASSERT(IDM_ABOUTBOX < 0xF000);

 CMenu* pSysMenu = GetSystemMenu(FALSE);
 if (pSysMenu != NULL)
 {
  CString strAboutMenu;
  strAboutMenu.LoadString(IDS_ABOUTBOX);
  if (!strAboutMenu.IsEmpty())
  {
   pSysMenu->AppendMenu(MF_SEPARATOR);
   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, 
   strAboutMenu);
  }
 }

 // Set the icon for this dialog. The framework does this automatically
 // when the application's main window is not a dialog
 SetIcon(m_hIcon, TRUE); // Set big icon
 SetIcon(m_hIcon, FALSE); // Set small icon

 // TODO: Add extra initialization here
 m_mscom.SetCommPort(1); //串口1
 m_mscom.SetInBufferSize(1024); //设置输入缓冲区的大小,Bytes 
 m_mscom.SetOutBufferSize(512); //设置输入缓冲区的大小,Bytes 
 if(!m_mscom.GetPortOpen()) //打开串口
 {
  m_mscom.SetPortOpen(true); 
 }
 m_mscom.SetInputMode(1); //设置输入方式为二进制方式 
 m_mscom.SetSettings("9600,n,8,1"); //设置波特率等参数 
 m_mscom.SetRThreshold(1); //为1表示有一个字符即引发事件 
 m_mscom.SetInputLen(0);

 return TRUE; // return TRUE unless you set the focus to a control
}

  最核心的发送串口数据函数("发送"按钮单击事件)如下:

void CSerialPortActivexDlg::OnSendButton() 
{
 // TODO: Add your control notification handler code here
 UpdateData(true);

 CByteArray sendArr; 
 WORD wLength;

 wLength = m_send.GetLength();
 sendArr.SetSize(wLength);
 for(int i =0; i<wLength; i++)
 {
  sendArr.SetAt(i, m_send.GetAt(i));
 }
 m_mscom.SetOutput(COleVariant(sendArr));
}

  为了处理接收事件,我们需要为MScomm控件添加对应的消息处理函数。如下图,我们通过"MFC类向导"添加了CSerialPortActivexDlg 类的成员函数OnCommMscomm1():

  这样,在对话框的头文件中就会自动增加下面两句:

afx_msg void OnCommMscomm1();//函数声明
DECLARE_EVENTSINK_MAP()

  来自AFX_MSG部分:

// Generated message map functions
//{{AFX_MSG(CSerialPortActivexDlg)
 virtual BOOL OnInitDialog();
 afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
 afx_msg void OnPaint();
 afx_msg HCURSOR OnQueryDragIcon();
 afx_msg void OnClearButton();
 afx_msg void OnSendButton();
 afx_msg void OnCommMscomm1();
 DECLARE_EVENTSINK_MAP()
//}}AFX_MSG

  同时在对话框的.cpp文件中会增加下列代码实现串口消息映射:

BEGIN_EVENTSINK_MAP(CSerialPortActivexDlg, CDialog)
//{{AFX_EVENTSINK_MAP(CSerialPortActivexDlg)
 ON_EVENT(CSerialPortActivexDlg, IDC_MSCOMM1, 1 /* OnComm */, 
 OnCommMscomm1, VTS_NONE)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()

  我们定义CSerialPortActivexDlg::OnCommMscomm1()函数主要处理数据的接收,其源代码为:

void CSerialPortActivexDlg::OnCommMscomm1() 
{
 // TODO: Add your control notification handler code here
 UpdateData(true);

 VARIANT variant_inp;
 COleSafeArray safearray_inp;

 long i = 0;
 int len;
 char rxdata[1000];
 CString tmp;
 switch (m_mscom.GetCommEvent())
 {
  case 2:
  //表示接收缓冲区内有字符
  {
   variant_inp = m_mscom.GetInput();
   safearray_inp = variant_inp;
   len = safearray_inp.GetOneDimSize();
   for (i = 0; i < len; i++)
   {
    safearray_inp.GetElement(&i, &rxdata[i]); 
   } 
   rxdata[i] = '\0';
  }
  m_recv += rxdata;
  UpdateData(false);
  break;
  default:
   break;
}
}

  最后,与连载三类似,再次借助"串口调试助手"以实例验证了本程序的正确性,如下图:

  最后,需要特别提示的是:如果要在基于"文档/视图"的框架结构程序而非对话框程序中使用串口控件,我们不能轻松地使用"MFC类向导",这时候必须手动地添加相关代码。

  在MainFrm.h头文件中加入:

afx_msg void OnCommMscomm(); 
DECLARE_EVENTSINK_MAP()

  并定义CMSComm成员变量:

CMSComm m_ComPort;

  在MainFrm.cpp文件中添加

BEGIN_EVENTSINK_MAP(CMainFrame, CFrameWnd)
ON_EVENT(CMainFrame,ID_COMMCTRL,1,OnCommMscomm,VTS_NONE)
//映射ACTIVEX控件的事件
END_EVENTSINK_MAP()

  在MainFrm.cpp文件的OnCreate(LPCREATESTRUCT lpCreateStruct)函数中添加:

ComPort.Create(NULL, WS_VISIBLE | WS_CHILD, CRect(0,0,0,0),this, ID_COMMCTRL);

  以创建CMSComm控件。

  此后,我们就可以在CMainFrame类的函数中使用串口控件对应的ComPort控件成员变量。

VC++ 6.0之MSComm控件安装、使用相关推荐

  1. vc++6.0使用串口控件例程

    vc++6.0使用串口控件例程 1.建立项目: 打开VC++6.0,建立一个基于对话框的MFC应用程序SCommTest; 2.在项目中插入MSComm控件 选择Project菜单下Add To Pr ...

  2. 怎样把vc6的MSComm控件接受的数据实时的显示在编辑框,并把数据实时惠存txt文件中

    怎样把vc6的MSComm控件接受的数据实时的显示在编辑框,并把数据实时存入txt文件中 我在做一个基于VC6的MSComm控件的电机上位机控制,数据帧格式采用9600bps,8位数据位,奇校验,1位 ...

  3. VS2010如何安装MSComm控件

    VS2010在默认情况下是不包含MSComm控件的,MSComm是在VC6.0中的控件,据说MSComm控件有些缺陷,看来微软是打算放弃此控件了.不过对于已经熟悉使用此控件的人来说还是不太方便,我是那 ...

  4. VC基于MSCOMM控件串口通讯

    在mfc中进行串口通讯最简单的方法莫过于在对话框中使用MSCOMM控件了,MSComm通信控件提供了一系列标准通信命令的接口,它允许建立串口连接,可以连接到其他通信设备(如Modem). 还可以发送命 ...

  5. 【GIS开发】VB6.0下MO控件的安装:安装教程及MO破解教程(MapObjects2.x)

    [GIS开发]VB6.0下MO控件的安装:安装教程及MO破解教程(MapObjects2.x) 基于MO和VB的GIS开发过程中,普遍使用的还是2.0及以上版本,ESRI公司早已不再对MO组件进行更新 ...

  6. 串口通讯mscomm控件下载

    串口通讯mscomm控件下载 大家知道,当我们安装VC++6.0/VB6.0时,如果选择了ACtiveX控件项(自定义安装),MSComm控件就会自动安装在计算机上了,并在系统文件夹下多了3个文件:M ...

  7. VB6.0 怎样启用控件comdlg32.ocx

    VB6.0 怎样启用控件comdlg32.ocx 怎样启用控件comdlg32.ocx 2008-10-08 09:32 提问者: nefu_20061617 |浏览次数:1502次 vbs文件中有代 ...

  8. 用VC开发串口通信dll控件

    VC串口通信技术网<VC串口上位机编程方法简介>介绍了串口编程的常见方法,其中就有使用串口dll控件的方法,dll是一种动态链接库,使用起来非常方便. 本文利用VC编程工具,对Window ...

  9. VS2008下用MFC 的MSComm控件编写串口程序

    可以在:http://download.csdn.net/detail/plutus_lee/4525446 下载详细文档. 首先感谢网络资源吧,作为一个自动化专业出身的,不懂串口实在让我有点无奈,本 ...

最新文章

  1. Nginx 五大常见应用场景,Linux运维请收藏~
  2. shell数组中“和@的妙用
  3. protocol(协议) 和 delegate(委托)也叫(代理)---辨析
  4. dairy-20110419-每日总结
  5. PostgreSQL的checkpoint能否并行
  6. 7K字面经 | 百度金融、蚂蚁金服、易贷网、金蛋科技等互联网金融公司面试经验...
  7. 二元函数连续性知识点总结
  8. CAD中怎么管理线缆CAD图层?
  9. java微信开发之--更换背景图片
  10. 内地酒量排行榜山东居首 东北三省无一进前三
  11. intellIj idea修改英文字体解决大写的“I”和小写的“l”显示冲突问题
  12. 防水蓝牙耳机哪个好?防水音质好的蓝牙耳机推荐
  13. 计算机什么是符号健,键盘数字健1-8的标点符号的名称什么
  14. sysvol 域控制器 文件_重建SYSVOL和NETLOGON共享(解决域安全策略和域控制器安全策略不能打开)...
  15. 域名策略服务器未运行,谈一谈网站突然无法访问的原因及解决策略
  16. struts2 ajax json 中文乱码的问题
  17. vue ie浏览器兼容
  18. 什么是Web应用防火墙
  19. GitHub项目、代码搜索、使用等技巧
  20. java开发社交网站_(转)强烈推荐:著名社交网站LinkedIn的Java架构技术

热门文章

  1. AS | 中大丁涛/田国宝等揭示口腔菌群的差异化输入塑造了与健康状况相关的两种肺型...
  2. 一维条形码识别的整个过程原理通俗易懂讲解
  3. CF983E NN country
  4. k-最近邻聚类k-Nearest Neighbor
  5. Uni-app 小程序使用腾讯云IM实时通讯
  6. Dell台式机安装ubuntu系统
  7. Android UI开发——Material Design界面设计【详细】
  8. vb6调用webservice
  9. 后缀001,002,003等的文件解压
  10. 树莓派使用排线摄像头和远程视频监控