Cipherlab CPT9300手持扫描枪开发体验
设备:Cipherlab CPT9300
OS :WinCE 6 R2
主要功能:一维、二维条码扫描。
用途: 大型仓库收发货识别扫描。
资源: 厂家有SDK提供,.net可外部调用的3个Dll及pdf开发手册(英文)。
开发: vs2008 + .Net CF 3.5
调试: 直接连接设备,未使用仿真机。
编码过程:
1、主界面及代码,详细请看注释。
代码:
using System; using System.Linq; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Reflection; using Cipherlab.SystemAPI; using System.Threading; namespace CF35_9300Demo { public partial class DemoMainForm : Form { //SysInfo 是WinCe系统信息的结构体,比如操作系统版本号、设备ID等 private Member.SysInfo m_DeviceSysInfo; /// <summary> /// 重写Text为了让主界面响应扫描结果而已 /// </summary> public override string Text { get { return base.Text; } set { base.Text = value; if (value.IndexOf("SDK") == -1) { MessageBox.Show(value, "Scan Result", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1); } } } public DemoMainForm() { InitializeComponent(); string tmp = string.Empty; Member.GetAPIVersion(ref tmp); tmp = string.Format("API Ver:{0}",tmp); Text += tmp; //.PadLeft(20,(char)32); Member.GetSysInfo(ref m_DeviceSysInfo); webBrowser1.Navigate(new Uri("http://datacool.cnblogs.com")); } /// <summary> /// 测试GDI直接绘制文字到指定位置,奇怪的是界面上Y轴,也就是Form的Top0-28这段区域会被遮挡。看起来那里有个光标,那行被挡住了。 /// </summary> /// <param name="e"></param> protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); e.Graphics.DrawString("App Builded By DataCool." + Environment.NewLine + "CopyRight By DataCool© 2012.", this.Font,new SolidBrush(Color.Red),new Rectangle(this.Left+2,this.Top+28,this.Width-40,60)); } /// <summary> /// 测试调用WCF服务,看起来是使用WebService方式,.Net CF 3.5工程里面没有“添加服务引用”. /// 获取远程数据库服务器的系统时间,修改本地WinCE的系统时间。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e) { CF35_9300Demo.QxTransQuery.QxTransQryService queryServiceProxy = new CF35_9300Demo.QxTransQuery.QxTransQryService(); var ds = queryServiceProxy.SDNA_Store_QueryData("select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual","qixuan520"); if (ds != null) { button1.Text = ds.Tables[0].Rows[0][0].ToString(); var dt = DateTime.Parse(button1.Text); var sysdt = new SystemTime(); sysdt.wYear = (short)dt.Year; sysdt.wMonth = (short)dt.Month; sysdt.wDay = (short)dt.Day; sysdt.wHour = (short)dt.Hour; sysdt.wMinute = (short)dt.Minute; sysdt.wSecond = (short)dt.Second; Win32API.SetLocalTime(ref sysdt); MessageBox.Show("系统时间已经更改为:"+button1.Text+"。", "Result", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1); } } /// <summary> /// 测试 Linq To Object /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { int[] buffer = new int[] { 1, 3, 5, 67 }; button2.Text = buffer.FirstOrDefault().ToString() + @"\" + buffer.Where(v => v > 5).FirstOrDefault().ToString(); } private void button3_Click(object sender, EventArgs e) { StringBuilder sb = new StringBuilder(); sb.AppendLine(string.Format("OS版本:{0}。 ", m_DeviceSysInfo.OsVer)); sb.AppendLine(string.Format("设备名称:{0}。 ", m_DeviceSysInfo.DevDesc)); sb.AppendLine(string.Format("设备ID:{0}。 ", m_DeviceSysInfo.SerialNum)); sb.AppendLine(string.Format("WiFi Mac:{0}。 ", m_DeviceSysInfo.WiFiAddress)); sb.AppendLine(string.Format("出厂日期:{0}。 ", m_DeviceSysInfo.ManuDate)); sb.AppendLine(string.Format("MicroPVer:{0}。", m_DeviceSysInfo.MicroPVer)); textBox1.Text = sb.ToString(); StringBuilder sb2 = new StringBuilder(); foreach (string p in m_DeviceSysInfo.PropsValueToStringArray()) { sb2.AppendLine(p); } textBox1.Text += sb2.ToString(); } private void button5_Click(object sender, EventArgs e) { MsgForm testFrm = new MsgForm(this); //初始化激光扫描组件,要1、2秒。只需要调用一次 int b1 = Reader.ReaderEngineAPI.InitReader(); } } /// <summary> /// 扩展结构体Member.SysInfo,将所有属性和值ToString(). /// 有谁知道如何使用反射简化这个写法,因为是结构体不是类。试过反射不出来 /// </summary> public static class SysInfoExt { public static string[] PropsValueToStringArray(this Member.SysInfo info) { string[] result = new string[] { string.Join(":", new string[] { "BootloaderVer", info.BootloaderVer}), string.Join(":", new string[] { "BTAddress", info.BTAddress}), string.Join(":", new string[] { "DevCFG", info.DevCFG}), string.Join(":", new string[] { "DevDesc", info.DevDesc}), string.Join(":", new string[] { "IMEI", info.IMEI}), string.Join(":", new string[] { "ManuDate", info.ManuDate}), string.Join(":", new string[] { "Manufactory", info.Manufactory}), string.Join(":", new string[] { "MicroPVer", info.MicroPVer}), string.Join(":", new string[] { "SerialNum", info.SerialNum}), string.Join(":", new string[] { "SerialNumPCBA", info.SerialNumPCBA}), string.Join(":", new string[] { "SerialNumReadOnly", info.SerialNumReadOnly}), string.Join(":", new string[] { "WiFiAddress", info.WiFiAddress}) }; return result; } } }
2、激光扫描相关编码(Reader)
using System; using System.Linq; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using Microsoft.WindowsCE.Forms; using System.Runtime.InteropServices; using Cipherlab.SystemAPI; namespace CF35_9300Demo { public struct SystemTime { public short wYear; public short wMonth; public short wDayOfWeek; public short wDay; public short wHour; public short wMinute; public short wSecond; public short wMilliseconds; } public class MsgForm : MessageWindow { public UInt32 decodeMsg = 0; int b1 = 0; byte[] lpbuf = new byte[25]; string tmp; public Form msgform; public MsgForm(Form msgFrm) { msgform = msgFrm; decodeMsg = Win32API.RegisterWindowMessage("WM_DECODEDATA"); } protected override void WndProc(ref Message m) { if (m.Msg == decodeMsg) { if (m.WParam.ToInt32().Equals(7)) { b1 = Reader.ReaderEngineAPI.GetDecodeData(ref tmp); msgform.Text = tmp; } } base.WndProc(ref m); } } /// <summary> /// Win32API,WinCE自带 /// </summary> public class Win32API { [DllImport("coredll.dll", SetLastError = true)] public static extern uint RegisterWindowMessage(string lpString); [DllImport("coredll.dll", SetLastError = true)] public static extern int SetLocalTime(ref SystemTime lpSystemTime); } }
SDK接口方式是使用Window Message方式,程序和接口(DLL)进行通信,程序先注册自定义消息"WM_DECODEDATA",然后按键进行扫描Dll扫描到条码后同过WM_DECODEDATA消息发送扫描到的条码给程序,程序窗口重写WndProc方法进行拦截,调用"Reader.ReaderEngineAPI.GetDecodeData(ref tmp);"获取Dll返回的条码字符串。
结论:
1、该设备有点贵哦,上万的售价啊。
2、开发比较简单有CF3.5和厂家提供的SDK开发包的支持像我等小白也可以开发。
最后上一张程序运行时的图:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
"作者:" 数据酷软件工作室
"出处:" http://datacool.cnblogs.com
"专注于CMS(综合赋码系统),MES,WCS(智能仓储设备控制系统),WMS,商超,桑拿、餐饮、客房、足浴等行业收银系统的开发,15年+从业经验。因为专业,所以出色。"
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
"作者:" 数据酷软件工作室
"出处:" http://datacool.cnblogs.com
"专注于CMS(综合赋码系统),MES,WCS(智能仓储设备控制系统),WMS,商超,桑拿、餐饮、客房、足浴等行业收银系统的开发,15年+从业经验。因为专业,所以出色。"
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++