MSComm 控件

来源:互联网 发布:淘宝网店新店怎么运营 编辑:程序博客网 时间:2024/05/17 07:31
MSComm控件

  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;
}
}

 

 

在VC上应用mscomm控件轻松搞定串口编程
2008-04-16 15:15

以下演示的是在MFC利用mscomm进行串口编程的例子

1。建立mfc工程,都会撒。
   将控件加进来:打开“Project->Add To Project->Components and Controls->Registered Activex Controls”,然后选择控件:Microsoft Communication Control,version 6.0插入到当前的工程中。这样就将类 CMSComm 的相关文件 mscomm.cpp 和 mscomm.h 一并加入到了工程中。编程时只需将控件对话中的 MSComm 控件拖至你的应用对话框中就OK了

2。定义串口对象:
    CMSComm      m_MSComm;

3。串口初始化:
  
DWORD style=WS_VISIBLE;
m_MSComm.Create(NULL,style,CRect(0,0,0,0),this,IDC_MSCOMM);
if(m_MSComm.GetPortOpen()) //如果串口是打开的,则行关闭串口
{
m_MSComm.SetPortOpen(FALSE);
}
m_MSComm.SetCommPort(1); //选择COM1
m_MSComm.SetInBufferSize(1024); //接收缓冲区
m_MSComm.SetOutBufferSize(1024);//发送缓冲区
m_MSComm.SetInputLen(0);//设置当前接收区数据长度为0,表示全部读取
m_MSComm.SetInputMode(1);//以二进制方式读写数据
m_MSComm.SetRThreshold(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm事件
m_MSComm.SetSettings("9600,n,8,1");//波特率9600无检验位,8个数据位,1个停止位
if(!m_MSComm.GetPortOpen())//如果串口没有打开则打开
m_MSComm.SetPortOpen(TRUE);//打开串口
else
{
m_MSComm.SetOutBufferCount(0);
AfxMessageBox("Open The Serial Port 1 Failurre!");
}


4。串口数据读写:

   MSComm 类的读写函数比较简单:GetInput()和SetOutput()。函数原形分别为VARIANT GetInput()和void SetOutput(const VARIANT newValue),均使用VARIANT类型。但PC机发送和接收数据时习惯用字符串形式。MSDN中查阅VARIANT类型,可以用BSTR表示字符 串,但所有的BSTR都包含宽字符,而只有Windows NT支持宽字符,Windows 9X并不支持。所以要完成一个适应各平台的串口应用程序必须解决这个问题。这里使用CbyteArray即可解决之。

发数据:在对话框对加入 按钮 控件并给你添加消息
   void CTest_mscommDlg::OnSend()
{
// TODO: Add your control notification handler code here
int i,Count;
CString m_SendData;
m_SendData="Hello!";
Count=m_SendData.GetLength();
CByteArray m_Array;

m_Array.RemoveAll();
m_Array.SetSize(Count);

for(int i =0; i<count; i++)
{
   m_Array.SetAt(i, m_SendData.GetAt(i));
}

m_mscomm.SetOutput(COleVariant(m_Array);

}


收数据:给串口控件添加消息
void CTest_mscommDlg::OnOnCommMscomm()
{
VARIANT m_input;
char *str,*str1;
int k,nEvent,i;
CString str2,m_RcvData;
nEvent=m_MSComm.GetCommEvent();
switch(nEvent)
{
case 2:
   k=m_MSComm.GetInBufferCount();     //接收缓冲区的字符数目
   if(k>0)
   {
    m_input=m_MSComm.GetInput();
    str=(char*)(unsigned char*)m_input.parray->pvData;
   }
   i=0;
   str1=str;
   while(i

m_disp+=m_RcvData;

UpdateData(false);



}


以上程序在vc6。0编译通过,在2个pc机上测试通过。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机qq注册号码忘了怎么办 原创头条号被限制推荐了怎么办 为什么打开app有广告怎么办 苹果手机浏览器总是弹出广告怎么办 手机上打开页面出现广告怎么办 电脑下面的任务栏变宽了怎么办 酷派手机总是出现广告怎么办 电脑弹出的热点新闻关闭不了怎么办 京东老是弹广告怎么办 电脑右下角出现无法显示网页怎么办 电脑右下角广告关不了怎么办 qq邮箱被冻结了怎么办 手机qq群自动发广告怎么办 济宁学院考研和上课冲突怎么办 考研但是大四上课多怎么办 试管促排卵泡少怎么办 京东退货卖家拒收怎么办 京东退货被卖家拒收怎么办 期货平台跑路了怎么办 浮云牧场没房了怎么办 融资股票停牌了怎么办 买入的股票停牌怎么办 淘宝抢到便宜货老板不发货怎么办 微信代购买到假货了怎么办 微信代购收到假货怎么办 苹果商店下载很慢怎么办 谷歌商店下载东西慢怎么办 买家说少发货了怎么办 人肉代购被海关扣了怎么办 韩国代购被海关扣了怎么办 爱奇艺开通自动续费忘了账号怎么办 小米手机云储存空间不足怎么办 路由器被黑了打不开网页怎么办 致人轻伤跑了怎么办 轻伤对方要30万怎么办 老公用老婆的钱怎么办 想注册个公司要怎么办 域名续费不知道找谁怎么办 代收快递弄丢了怎么办 货到付款的快递人不在怎么办 快递送货上门人不在怎么办