原文地址::https://www.jianshu.com/p/5c54338b67b2

相关文章

1、解决Win10中MSCOMM32.ocx没注册问题----https://blog.csdn.net/mylovepwy/article/details/50239103

2、解决在win10 64位下无法注册mscomm32.ocx的控件问题----https://www.cnblogs.com/iotrookie/p/6076656.html

前言 & 吐槽

前几天重装了系统,然后之前写的用MsComm控件(Microsoft Communications Control)进行串口通信的程序无法运行了,用VS打开项目进入资源视图,发现打不开包含MsComm控件的对话框资源,提示未在此计算机上注册ActiveX控件。而VS工具箱提供的COM组件里也没有MsComm控件。
根本原因是这个ActiveX控件根本不是win10安装自带的,高版本VS也不会自带的,你要写这种串口通信程序,要么用底层API,要么用微软大力支持的.Net系语言,而不是MFC这个非常非常过时的破东西了,然而就这个破东西,很多时候还是被迫得写,嗯,前几天才看到2018年的二级C/C++上机环境终于从万年不变的VC6变成了VS2010,简直了。

注册MsComm控件

首先给下载地址,其实谷歌MsComm.ocx第一条就是
https://www.ocxme.com/files/mscomm32_ocx
当然国内用百度的多,一堆文章全部都指向了CSDN花几个积分的下载链接,好点的有百度盘链接,不过天知道过段时间会不会被和谐。还是这种专门的免费下载站更舒心。
下完解压后就是MSCOMM32.OCX,然后需要注意(我踩了这个坑),对于64位系统需要把它放在C:\Windows\SysWOW64目录下,32位系统才是C:\Windows\system32目录。之前我放在system32目录然后注册出了问题。
然后右键管理员权限打开cmd窗口,进入对应目录输入指令regsvr32 MSCOMM32.OCX即可(如下图所示)

网上有些教程还有一步是修改注册表,不过我发现regsvr32命令已经修改了注册表,无需手动修改。

为何使用MsComm控件?

其实直接用底层API进行串口编程未尝不可,MSDN也给出了示例,但是事件回调的步骤得自己写,如果不是时间充裕用来学习/练手的情况,没必要重复造轮子。
网上也可以搜到不少包装好的C++类,但是串口这东西本来就是古老物了,搜到的代码还是很多年前的,代码风格不一定很好。而且有的接口已经和现代C++标准不兼容了。
比如之前师兄用了一个简单小巧的库(只包含1个头文件和1个源文件,添加进工程即可)提供了这样的接口

    void        WriteToPort(char* string);

然而C++11标准在近几个版本的VS里已经得到了支持,字符串字面值是不能直接转换成char*类型的,也就是说实际调用的时候得像这样 xxx.WriteToPort((char*)"hello")xxx.WriteToPort(const_cast<char*>("hello"))
然后错误信息字符串操作全都是基于char*的,MFC默认Unicode,而且方便移植的代码应该都对TCHAR*来操作,直接编译会出错的,需要一个个用宏_T()把字符串包含起来。当然,会正则表达式的话起来替换相对会比较轻松。
我对MsComm控件不甚了解,但是明显这也是古老物了,毕竟还不支持64位程序,VS里用Debug或Release x64来编译的话会失败。
但是好处在于,这个控件是官方的,值得信赖,不像很多开源库那样缺乏大量测试。

为何不使用MsComm控件?

这篇文章是2018-01-17发布的,我在2018-02-01完成课题程序时发现了问题。正如上文所言,MsComm控件是古老物了,只适用于32位的程序。如果程序必须编译成64位的,那么MsComm控件无法派上用场。我的程序里需要用到OpenCV和一个第三方库,两者刚好都只提供了64位的lib和dll,所以只有使用MsComm控件,后来使用了上文提到的CSerialPort,才发现这个古老版本原来国内有不少人进行了维护,现在还是非常好用的,强力推荐。

添加MsComm控件

首先需要在VS中添加该控件到工具箱中

按上述操作点确定即可
PS:可以看到版本才1.1,还是version 6.0,目测从VC6之后再也没更新过……
然后在对话框资源编辑框中右键,插入ActiveX控件

不同于常规的界面控件,MsComm控件不会显示出来,所以随便拖到哪个位置都可以。
拖了控件之后就是为控件添加变量了

这一步,VS会自动生成一对.h和.cpp文件,然后在xxxDlg.h中添加成员变量
CMscomm1 m_comm1;
并在xxxDlg.cpp中添加数据交换操作

void CTestDlg::DoDataExchange(CDataExchange* pDX)
{CDialog::DoDataExchange(pDX);DDX_Control(pDX, IDC_MSCOMM1, m_comm1);
}

可以发现和使用其他控件一样的套路。

从串口发送和接收字节

文本框/复选框这种自定义参数输入的控件就不祥述了,以我的需求为例

波特率: 9600 停止位: 1 传送位数: 8位 奇偶校验: 无
串口协议是7个字节表示1个数据包
MsComm控件类型为CMscomm_las,变量名为m_commLaser

  1. 打开/关闭串口
        m_commLaser.put_CommPort("COM1");m_commLaser.put_InputMode(CMscomm_las::comInputModeBinary);m_commLaser.put_InBufferSize(512);  // 接收缓冲区大小m_commLaser.put_OutBufferSize(512);  // 发送缓冲区大小m_commLaser.put_Settings(_T("9600,n,8,1"));if (!m_commLaser.get_PortOpen()){try {m_commLaser.put_PortOpen(TRUE);  // 打开串口}catch (CException* e) {TCHAR error_msg[1024];e->GetErrorMessage(error_msg, 1024);MessageBox(error_msg);return;}m_commLaser.put_RThreshold(7);  // 每当接收缓冲区有7个字符时则接收串口数据m_commLaser.put_InputLen(0);m_commLaser.get_Input();}else{MessageBox(_T("打开端口失败!"));}

注意put_Settings的参数,n代表无奇偶校验,是DCB结构的Parity成员的可选取值NOPARITY的缩写,同理,奇校验ODDPARITY是o,偶校验EVENPARITY是e。
打开串口是put_PortOpen(TRUE),关闭串口自然就是put_PortOpen(FALSE)。

  1. 发送字节序列
    void put_Output(VARIANT newValue)
    直接调用上述方法即可,问题来了,VARIANT类型是什么?这就是ActiveX控件的蛋疼之处,它的数据交换必须用Ole那一套来。
    正常来说,发送给串口的都是字节序列,即uint8_t或BYTE数组。因此这里只需要知道怎么转换成VARIANT类型即可。
    MFC是上古时期的产物,那个时候C++98标准都没确立,因此微软弄了一堆自定义的容器类,虽然除了CString外几乎都被C++标准库的STL取代了。但在这里,MFC的CByteArray刚好能直接用来构造COleVariant对象,COleVariant继承自VARIANT(C结构体的typedef别名),仅仅是增加了若干方法,可以隐式类型转换。
    比如发送3个字节0x01 0x02 0x04给串口的代码如下
    CByteArray m_baSend;m_baSend.Add(0x01);m_baSend.Add(0x02);m_baSend.Add(0x04);m_commLaser.put_Output(COleVariant(m_baSend));
  1. 接收字节序列
    给MsComm控件添加OnComm事件处理程序即可

    和其他控件一样,MsComm控件也是事件驱动,在后台接收数据,然后处理不同的事件

enum
{comEvSend = 1,comEvReceive = 2,comEvCTS = 3,comEvDSR = 4,comEvCD = 5,comEvRing = 6,comEvEOF = 7
}OnCommConstants

接收数据只需要处理comEvReceive事件即可,其他几个事件等真正有需求的时候再去处理。下面给出我接收7个字节的代码

void CMsCommDemoDlg::OnCommMscommLas()
{if (m_commLaser.get_CommEvent() == CMscomm_las::comEvReceive){// 读取串口的接收缓冲区(之前打开串口时设置过缓冲区大小)COleSafeArray safearray_obj = m_commLaser.get_Input();// 填充数据到自定义缓冲区中const int BUFF_SIZE = 7;BYTE buffer[BUFF_SIZE];for (long i = 0; i < BUFF_SIZE; i++){safearray_obj.GetElement(&i, &buffer[i]);}// TODO: 处理缓冲区buffer[]的数据}
}

这里就和发送数据反过来了,接收的数据类型是VARIANT,需要转换成BYTE数组来处理。套路就是借助COleSafeArray这个中间物及其GetElement方法。

总结

其实这个程序是我几周之前写的Demo,最近要重新写了,照着我的代码写下来,自己也梳理了用MsComm控件的步骤。
控件方面,由于这东西实在太古老了而被抛弃了,而官方也没给C++提供什么替代品,于是得手动引入

  1. 注册MSCOMM32.OCX
  2. 在VS工具箱的COM组件中找到MsComm控件添加进来
  3. 像使用其他MFC控件一样使用它(添加关联的控件变量/事件处理函数)

代码方面,虽然COM接口的实现看起来非常复杂且蛋疼,但是其实接口很清晰,都是一堆put(设置)和get(获取)方法,注意打开/关闭串口也是通过putxxx来执行的,相当于设置串口的连接状态。
难点在于数据交换格式都是VARIANT,因此需要借用MFC专门提供的类来转换成方便处理的BYTE数组。大致过程如下

BYTE[] -> CByteArray -> COleVariant -> VARIANT
VARIANT -> COleSafeArray -> BYTE[]

小礼物走一走,来简书关注我

作者:哈莉_奎茵
链接:https://www.jianshu.com/p/5c54338b67b2
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

win10注册MSCOMM32控件及简单使用相关推荐

  1. win10注册ocx控件的步骤(包含错误处理方法0x80040200)

    最近在测试一个加载ocx控件的C++程序,运行前要先注册ocx控件. 1.用运行命令提示符或者PowerShell. 2.利用命令进入到ocx文件所在的目录下输入注册命令 注册命令:regsvr32 ...

  2. win10下注册MSCOMM32控件

    我用的是64位WIN10.VS2013,估计对于win7也同样适用.下面说一下方法: 1.在网上手动下载MSCOMM32套件,包括MSCOMM32.ocx,MSCOMM32.dep,MSCOMM.sr ...

  3. MSCOMM32控件注册的两种办法

    当我们在VC或者VB或者VS环境下基于MSCOMM控件开发的软件发布后,是不是有种很爽的感觉,可以拿到别人的电脑上运行下你的软件,可是当你移植过去后却发现软件无法点击的动(别笑,我在开发C#软件时就是 ...

  4. 注册ActiveX控件简单方法及控件未被正确授权解决方案

    最近编程的时候发现有些电脑上部分控件没有被注册,先把注册ActiveX控件的方法简单记录一下: 1.首先要确定你要缺少什么控件,需要注册: 2.在http://www.dll1.cn/ 下载相应的控件 ...

  5. 用C#编写ActiveX控件,开发浏览器控件,注册ActiveX 控件

    用C#编写ActiveX控件,开发浏览器控件,注册ActiveX 控件 用C#编写ActiveX控件 开发浏览器控件这是本控件开发完成后的一个简单应用.我们可以利用它以本地文件夹为单位来批量更新服务器 ...

  6. 验证控件的使用:一步一步学注册——RangeValidator控件

    ™RangeValidator检查指定范围 上一篇博客: 验证控件的使用:一步一步学注册--CompareValidator控件 上篇博客说道要继续学习检查指定范围的验证控件RangeValidato ...

  7. vs2010串口开发(mscomm控件)_未在此计算机上注册ActiveX控件

    1.简介 在vs2010做串口开发时,当使用mscomm控件时,如果没有注册MSCOMM32.OCX,在运行工程时会弹出"未在此计算机上注册ActiveX控件"这个警告,解决方法如 ...

  8. 未能实例化2个ActiveX控件,请重新安装或注册这些控件并重试

    vs2017或vs2015mfc双击dialog的ui界面出现:未能实例化2个ActiveX控件,请重新安装或注册这些控件并重试 实际解决方法: 1:下载MScomm控件,我把文件上传到了百度空间,地 ...

  9. Win7 64位系统 注册 ocx控件

    32位系统注册ocx就不谈了.网上一搜一大把.下面说下win7 64位 旗舰版下如果注册ocx控件 1.首先复制 XXXX.OCX文件到"C:\Windows\SysWOW64"目 ...

最新文章

  1. 只知道TF和PyTorch还不够,快来看看怎么从PyTorch转向自动微分神器JAX
  2. java 生成二维码 QRCode、zxing 两种方式
  3. AutoLayout(自动布局)详细教程
  4. SAP云平台CloudFoundry上部署了一个应用的技术明细
  5. synchronized不能锁静态变量_面试官:请说一下对象锁和类锁的区别
  6. GitHub | 周志华《机器学习》手推笔记正式开源!可打印版本附pdf下载链接
  7. webpack+ES6+Sass搭建多页面应用
  8. 三星a9s参数_三星A9s配置怎么样 三星A9s参数配置介绍
  9. 公司员工考勤系统Java代码
  10. python关键词排名批量查排名_Python批量查询百度排名
  11. 孕妇睡眠质量差怎么办?如何提高睡眠质量?
  12. 在地址栏直接使用Google“手气不错”功能
  13. 2021-01-04
  14. 高等概率论 Chapter 6 Construction of a Probability Measure
  15. 微信个人订阅号简单实现在线收款
  16. Python开发爬虫之动态网页抓取篇:爬取博客评论数据——通过浏览器审查元素解析真实网页地址...
  17. 为什么pLC工程师如此年轻,他们的经验毫无价值?
  18. c语言编程订单统计,C语言课程设计订单管理系统.pdf
  19. 华为视频会议TE40
  20. 嵌入式STM32深入之RTOS编程

热门文章

  1. 三种POSS材料(乙烯基POSS、氨基POSS和苯基POSS)
  2. 深蓝色固体Cyanine5-Azide,Cy5-N3,Cy5 Azide,菁染料CY5叠氮
  3. 程序中unsigned char 类型的意义
  4. java实现程序等待一段时间的代码
  5. 分享29个超赞的响应式Web设计
  6. 高等数学拾遗 矢量分析
  7. Parallels Desktop 16 网络初始化失败和不能连接USB设备解决方法
  8. Django REST Framework中的Serializer relations
  9. 区块链是新的 Linux 而非新的互联网
  10. CentOS7上安装Snipe-IT4.6.3详细过程及注意事项