最近做一個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:yq@yyzq.net</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 開始監聽