MSComm 控件
来源:互联网 发布:淘宝网店新店怎么运营 编辑:程序博客网 时间:2024/05/17 03:50
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;
}
}
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机上测试通过。
- MSComm 控件
- MSComm控件
- MSComm控件
- MSComm 控件
- MSComm 控件
- MSComm 控件
- MSComm 控件
- MSComm 控件
- MSComm控件
- MSComm 控件
- MSComm 控件
- MSCOMM控件的属性
- MSComm控件 License 注册
- MSComm控件使用详解
- MSComm控件的属性
- MSComm控件使用详解
- VC7 注册 MSCOMM控件
- MSComm 控件详细资料
- linux 2.6内核epoll用法举例说明(续)--给echo服务器增加读线程池
- SSH面试题总结.doc
- Handle Classes: The Smart Pointer
- C#取word中某控件值的方法
- 多进程服务器中,epoll的创建应该在创建子进程之后
- MSComm 控件
- string、wstring、cstring、 char、 tchar、int、dword转换方法
- MSComm 控件
- MSComm 控件
- Handle Classes: The Smart Pointer
- JVM 调优总结
- Android之PreferenceActivity
- bootload启动流程(二)----Eboot的主要流程
- 进一步学习PV操作——统一于生产者消费者问题