本文转自:https://www.cnblogs.com/rockyhm/p/3434200.html
最近做一个B/S的项目,需要读取电子秤的值,之前一直没做过,也没有经验,于是在网上找到很多 大致分两种
- 使用ActiveX控件,JS调用MSCOMM32.dll的串口控件对串口进行控制
- 使用C#语言的控件对串口进行控制,然后使用JS+AJAX与C#进行交互获得串口数据
详情见 使用JS获得串口数据 http://blog.csdn.net/xuing/article/details/6688306 但是小弟用这两种办法都获取到数据
串口配置如下:
1 serialPort1.PortName = "COM1"; //端口名称 2 serialPort1.BaudRate = 1200; //波特率 3 serialPort1.Parity = Parity.None; //奇偶效验 4 serialPort1.StopBits = StopBits.One; //效验 5 serialPort1.DataBits = 8; //每个字节的数据位长度
最后换种思路:使用C#写一个ActiveX控件(吉日老师提醒)最后嵌入网页中读取数据 如下:
- 第一步:新建项目,如下图,选择windows下的类库项目。
- 在项目中添加一个类:IObjectSafety.cs
- IObjectSafety.cs代码如下:
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace MyActive { //Guid唯一,不可变更,否则将无法通过IE浏览器的ActiveX控件的安全认证 [ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IObjectSafety { [PreserveSig] void GetInterfacceSafyOptions(int riid,out int pdwSupportedOptions,out int pdwEnabledOptions); } }
- 添加一个用户控件 MyActiveXControl.cs
- 修改 MyActiveXControl.cs 代码,让其继承IObjectSafety,定义相应的Guid,该Guid就是ActiveX的classid
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace MyActiveX { [Guid("218849AF-1B2C-457B-ACD5-B42AC8D17EB7"), ComVisible(true)] public partial class MyActiveXControl : UserControl,IObjectSafety { public MyActiveXControl() { InitializeComponent(); } #region IObjectSafety 成员 用于ActiveX控件安全信任 public void GetInterfacceSafyOptions(int riid, out int pdwSupportedOptions, out int pdwEnabledOptions) { pdwSupportedOptions = 1; pdwEnabledOptions = 2; } public void SetInterfaceSafetyOptions(int riid, int dwOptionsSetMask, int dwEnabledOptions) { throw new NotImplementedException(); } #endregion } }
至此 Active控件制作完毕 下面我们添加文本框、按钮、SerialPort、Timer控件进行测试
- 添加响应的事件代码如下
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.IO.Ports; using System.Text; using System.Threading; using System.Windows.Forms; using System.Runtime.InteropServices; using MyActive; namespace MyActiveX { //不可改变 [Guid("218849AF-1B2C-457B-ACD5-B42AC8D17EB7"), ComVisible(true)] public partial class MyActiveXControl : UserControl, IObjectSafety { public MyActiveXControl() { InitializeComponent(); } public delegate void HandleInterfaceUpdataDelegate(string text);//定义一个委托 private HandleInterfaceUpdataDelegate interfaceUpdataHandle;//声明 bool isClose = false;//是否关闭 #region IObjectSafety 成员 用于ActiveX控件安全信任 public void GetInterfacceSafyOptions(int riid, out int pdwSupportedOptions, out int pdwEnabledOptions) { pdwSupportedOptions = 1; pdwEnabledOptions = 2; } public void SetInterfaceSafetyOptions(int riid, int dwOptionsSetMask, int dwEnabledOptions) { throw new NotImplementedException(); } #endregion private void button1_Click(object sender, EventArgs e) { try { interfaceUpdataHandle = new HandleInterfaceUpdataDelegate(UpdateTextBox);//实例化委托对象 serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived); if (!serialPort1.IsOpen) { serialPort1.Open(); } button2.Enabled = true; button1.Enabled=false; } catch (Exception ex) { MessageBox.Show(ex.Message); return; } timer1.Enabled = true; } /// <summary> /// 控件加载事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void MyActiveXControl_Load(object sender, EventArgs e) { setOrgComb(); } /// <summary> /// 初始化串口 /// </summary> private void setOrgComb() { serialPort1.PortName = "COM1"; //端口名称 serialPort1.BaudRate = 1200; //波特率 serialPort1.Parity = Parity.None; //奇偶效验 serialPort1.StopBits = StopBits.One; //效验 serialPort1.DataBits = 8; //每个字节的数据位长度 } /// <summary> /// 更新数据 /// </summary> /// <param name="text"></param> private void UpdateTextBox(string text) { //richTextBox1.Text = text + "\n\t" + richTextBox1.Text; richTextBox1.Text = text; } /// <summary> /// 接收数据是发生 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { //获取接收缓冲区中数据的字节数 if (serialPort1.BytesToRead > 5) { string strTemp = serialPort1.ReadExisting();//读取串口 double weight = -1;//获取到的重量 foreach (string str in strTemp.Split('='))//获取稳定的值 { double flog = 0; //数据是否正常 if(double.TryParse(str, out flog)&&str.IndexOf('.')>0&&str[str.Length-1]!='.') { //数据转换 串口获取到的数据是倒叙的 因此进行反转 char[] charArray = str.ToCharArray(); Array.Reverse(charArray); string left = new string(charArray).Split('.')[0]; string right = new string(charArray).Split('.')[1]; if (right.Length==2) { weight = int.Parse(left) + int.Parse(right) / 100.0; } } } if(weight>=0) { //在拥有控件的基础窗口句柄的线程上,用指定的参数列表执行指定委托。 this.Invoke(interfaceUpdataHandle, weight.ToString());//取到数据 更新 } } } private void button2_Click(object sender, EventArgs e) { try { button1.Enabled = true; button2.Enabled = false; serialPort1.Close(); timer1.Enabled = false; } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void timer1_Tick(object sender, EventArgs e) { if (isClose) { return; } try { string send = "" + (char)(27) + 'p'; send = serialPort1.ReadExisting(); } catch (Exception ex) { MessageBox.Show(ex.Message); button2_Click(null, null); } } } }
- 至此读取串口数据的Active控件制作完毕 下面我们来制作一个安装包,新建一个安装项目
- 在安装项目的文件系统中添加刚才之前我们制作的ActiveX的DLL:MyActiveX.dll
(特别注意:在文件添加进来后,右击文件选择属性,设置其属性Register值为:vsdraCOM)
9. 生成安装程序,在项目MyActiveX\Setup1\Debug下找到Setup1.msi,双击安装它。
然后在该目录下新建一个html文件(test.html)用于测试我们的ActiceX控件。HTML代码如下:
<html> <title>Powered by yyzq.net Email:[email protected]</title> <head> </head> <body> <div> <object id="yyzq" classid="clsid:218849AF-1B2C-457B-ACD5-B42AC8D17EB7" width="320" height="240" codebase="Setup1.msi"> </object> </div> </body> </html>
在IE浏览器下打开test.html,点击start 开始监听