using MvCodeReaderSDKNet; using System.Drawing; using System.Drawing.Drawing2D; using System.Runtime.InteropServices; using System.Text; namespace Aucma.Core.Scanner { public class MvCodeHelper { static MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST m_stDeviceList = new MvCodeReader.MV_CODEREADER_DEVICE_INFO_LIST(); static MvCodeReader.MV_CODEREADER_DEVICE_INFO stDevInfo;// 通用设备信息 private static MvCodeReader m_cMyDevice = new MvCodeReader(); bool m_bGrabbing = true; // ch:用于从驱动获取图像的缓存 | en:Buffer for getting image from driver byte[] m_BufForDriver = new byte[1024 * 1024 * 20]; // 显示 Bitmap bmp = null; Graphics gra = null; Pen pen = new Pen(Color.Blue, 3); // 画笔颜色 Point[] stPointList = new Point[4]; // 条码位置的4个点坐标 GraphicsPath WayShapePath = new GraphicsPath(); // 图形路径,内部变量 GraphicsPath OcrShapePath = new GraphicsPath(); // 图形路径,内部变量 Matrix stRotateWay = new Matrix(); Matrix stRotateM = new Matrix(); Pen penOcr = new Pen(Color.Yellow, 3); Pen penWay = new Pen(Color.Red, 3); #region 获取设备列表 /// /// 获取设备列表 /// public static void DeviceListAcq() { // ch:创建设备列表 | en:Create Device List System.GC.Collect(); m_stDeviceList.nDeviceNum = 0; int nRet = MvCodeReader.MV_CODEREADER_EnumDevices_NET(ref m_stDeviceList, MvCodeReader.MV_CODEREADER_GIGE_DEVICE); if (0 != nRet) { ShowErrorMsg("Enumerate devices fail!", nRet); return; } if (0 == m_stDeviceList.nDeviceNum) { ShowErrorMsg("None Device!", 0); return; } string strUserDefinedName = ""; //获取设备列表 for (int i = 0; i < m_stDeviceList.nDeviceNum; i++) { MvCodeReader.MV_CODEREADER_DEVICE_INFO stDevInfo = (MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[i], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO)); if (stDevInfo.nTLayerType == MvCodeReader.MV_CODEREADER_GIGE_DEVICE) { IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(stDevInfo.SpecialInfo.stGigEInfo, 0); MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO stGigEDeviceInfo = (MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MvCodeReader.MV_CODEREADER_GIGE_DEVICE_INFO)); if (stGigEDeviceInfo.chUserDefinedName != "") { byte[] byteUserDefinedName = Encoding.GetEncoding("GB2312").GetBytes(stGigEDeviceInfo.chUserDefinedName); bool bIsValidUTF8 = IsTextUTF8(byteUserDefinedName); if (bIsValidUTF8) { strUserDefinedName = Encoding.UTF8.GetString(byteUserDefinedName); } else { strUserDefinedName = Encoding.GetEncoding("GB2312").GetString(byteUserDefinedName); } Console.WriteLine("GEV: " + strUserDefinedName + " (" + stGigEDeviceInfo.chSerialNumber + ")"); } else { Console.WriteLine("GEV: " + stGigEDeviceInfo.chManufacturerName + " " + stGigEDeviceInfo.chModelName + " (" + stGigEDeviceInfo.chSerialNumber + ")"); } } } } #endregion #region 扫描信息 public static void StartGrab() { Thread m_hReceiveThread = new Thread(ReceiveThreadProcess); m_hReceiveThread.Start(); } public static void ReceiveThreadProcess() { int nRet = MvCodeReader.MV_CODEREADER_OK; IntPtr pData = IntPtr.Zero; MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2 stFrameInfoEx2 = new MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2(); IntPtr pstFrameInfoEx2 = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2))); Marshal.StructureToPtr(stFrameInfoEx2, pstFrameInfoEx2, false); int ik = 0; while (true) { nRet = m_cMyDevice.MV_CODEREADER_GetOneFrameTimeoutEx2_NET(ref pData, pstFrameInfoEx2, 1000); // ch:获取一帧图像 | en:Get one image if (MvCodeReader.MV_CODEREADER_OK == nRet) { stFrameInfoEx2 = (MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2)Marshal.PtrToStructure(pstFrameInfoEx2, typeof(MvCodeReader.MV_CODEREADER_IMAGE_OUT_INFO_EX2)); // 分配条码内存空间 MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2 stBcrResult = (MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2)Marshal.PtrToStructure(stFrameInfoEx2.UnparsedBcrList.pstCodeListEx2, typeof(MvCodeReader.MV_CODEREADER_RESULT_BCR_EX2)); for (int i = 0; i < stBcrResult.nCodeNum; ++i) { bool bIsValidUTF8 = IsTextUTF8(stBcrResult.stBcrInfoEx2[i].chCode); if (bIsValidUTF8) { string strCode = System.Text.Encoding.Default.GetString(stBcrResult.stBcrInfoEx2[i].chCode); //Console.WriteLine($"【{ik}】1条码信息[{strCode.Trim().TrimEnd('\0')}]"); //定义自己的业务处理方式 ik++; } else { string strCode = System.Text.Encoding.Default.GetString(stBcrResult.stBcrInfoEx2[i].chCode); //Console.WriteLine($"【{ik}】2条码信息[{strCode.Trim().TrimEnd('\0')}]"); //定义自己的业务处理方式 } } //MvCodeReader.MV_CODEREADER_OCR_INFO_LIST stOcrInfo = (MvCodeReader.MV_CODEREADER_OCR_INFO_LIST)Marshal.PtrToStructure(stFrameInfoEx2.UnparsedOcrList.pstOcrList, typeof(MvCodeReader.MV_CODEREADER_OCR_INFO_LIST)); //for (int i = 0; i < stOcrInfo.nOCRAllNum; i++) //{ // string strOcrCharCode = System.Text.Encoding.Default.GetString(stOcrInfo.stOcrRowInfo[i].chOcr); // Console.WriteLine("Get OcrInfo:" + "ocrNum[" + i.ToString() + "], ocrLen[" + Convert.ToString(stOcrInfo.stOcrRowInfo[i].nOcrLen) + "], ocrChar[" + strOcrCharCode.Trim().TrimEnd('\0') + "]"); //} } else { Console.WriteLine("没有获取到数据:{0:x8}", nRet); //重新获取数据 MvCodeHelper.DeviceListAcq();//获取设备 MvCodeHelper.OpenDevice();//打开设备 } } } #endregion #region 判断字符编码 /// /// 判断字符编码 /// /// /// public static bool IsTextUTF8(byte[] inputStream) { int encodingBytesCount = 0; bool allTextsAreASCIIChars = true; for (int i = 0; i < inputStream.Length; i++) { byte current = inputStream[i]; if ((current & 0x80) == 0x80) { allTextsAreASCIIChars = false; } // First byte if (encodingBytesCount == 0) { if ((current & 0x80) == 0) { // ASCII chars, from 0x00-0x7F continue; } if ((current & 0xC0) == 0xC0) { encodingBytesCount = 1; current <<= 2; // More than two bytes used to encoding a unicode char. // Calculate the real length. while ((current & 0x80) == 0x80) { current <<= 1; encodingBytesCount++; } } else { // Invalid bits structure for UTF8 encoding rule. return false; } } else { // Following bytes, must start with 10. if ((current & 0xC0) == 0x80) { encodingBytesCount--; } else { // Invalid bits structure for UTF8 encoding rule. return false; } } } if (encodingBytesCount != 0) { // Invalid bits structure for UTF8 encoding rule. // Wrong following bytes count. return false; } // Although UTF8 supports encoding for ASCII chars, we regard as a input stream, whose contents are all ASCII as default encoding. return !allTextsAreASCIIChars; } #endregion #region 打开设备 public static void OpenDevice() { if (m_stDeviceList.nDeviceNum == 0) { ShowErrorMsg("No stDevInfo, please select", 0); return ; } // ch:获取选择的设备信息 | en:Get selected stDevInfo information stDevInfo =(MvCodeReader.MV_CODEREADER_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[0], typeof(MvCodeReader.MV_CODEREADER_DEVICE_INFO)); // ch:打开设备 | en:Open stDevInfo if (null == m_cMyDevice) { m_cMyDevice = new MvCodeReader(); if (null == m_cMyDevice) { return; } } int nRet = m_cMyDevice.MV_CODEREADER_CreateHandle_NET(ref stDevInfo);//创建设备 if (MvCodeReader.MV_CODEREADER_OK != nRet) { ShowErrorMsg("创建设备 fail!", nRet); return; } Console.WriteLine("创建设备成功!"); nRet = m_cMyDevice.MV_CODEREADER_OpenDevice_NET();//打开设备 if (MvCodeReader.MV_CODEREADER_OK != nRet) { m_cMyDevice.MV_CODEREADER_DestroyHandle_NET(); ShowErrorMsg("Device open fail!", nRet); return; } Console.WriteLine("打开设备成功!"); // ch:设置触发模式为off || en:set trigger mode as off if (MvCodeReader.MV_CODEREADER_OK != m_cMyDevice.MV_CODEREADER_SetEnumValue_NET("TriggerMode", 0)) { Console.WriteLine("Set TriggerMode failed!"); return; } Console.WriteLine("设置采集连续模式成功!"); // ch:开启抓图 | en:start grab nRet = m_cMyDevice.MV_CODEREADER_StartGrabbing_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Start grabbing failed:{0:x8}", nRet); return; } Console.WriteLine("开启抓图成功!"); Console.WriteLine("设备已经开启"); } #endregion #region 关闭设备 public static void CloseDevice() { int nRet = MvCodeReader.MV_CODEREADER_OK; // ch:停止抓图 | en:Stop grab image nRet = m_cMyDevice.MV_CODEREADER_StopGrabbing_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Stop grabbing failed{0:x8}", nRet); } // ch:关闭设备 | en:Close device nRet = m_cMyDevice.MV_CODEREADER_CloseDevice_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Close device failed{0:x8}", nRet); } // ch:销毁设备 | en:Destroy device nRet = m_cMyDevice.MV_CODEREADER_DestroyHandle_NET(); if (MvCodeReader.MV_CODEREADER_OK != nRet) { Console.WriteLine("Destroy device failed:{0:x8}", nRet); } //if (MvCodeReader.MV_CODEREADER_OK != nRet) //{ // // ch:销毁设备 | en:Destroy device // nRet = m_cMyDevice.MV_CODEREADER_DestroyHandle_NET(); // if (MvCodeReader.MV_CODEREADER_OK != nRet) // { // Console.WriteLine("Destroy device failed:{0:x8}", nRet); // } //} Console.WriteLine("设备已经关闭"); } #endregion #region 将Byte转换为结构体类型 //将Byte转换为结构体类型 public static object ByteToStruct(byte[] bytes, Type type) { int size = Marshal.SizeOf(type); if (size > bytes.Length) { return null; } //分配结构体内存空间 IntPtr structPtr = Marshal.AllocHGlobal(size); //将byte数组拷贝到分配好的内存空间 Marshal.Copy(bytes, 0, structPtr, size); //将内存空间转换为目标结构体 object obj = Marshal.PtrToStructure(structPtr, type); //释放内存空间 Marshal.FreeHGlobal(structPtr); return obj; } #endregion #region 异常信息展示 /// /// 异常信息展示 /// /// /// private static void ShowErrorMsg(string csMessage, int nErrorNum) { string errorMsg; if (nErrorNum == 0) { errorMsg = csMessage; } else { errorMsg = csMessage + ": Error =" + String.Format("{0:X}", nErrorNum); } switch (nErrorNum) { case MvCodeReader.MV_CODEREADER_E_HANDLE: errorMsg += " Error or invalid handle "; break; case MvCodeReader.MV_CODEREADER_E_SUPPORT: errorMsg += " Not supported function "; break; case MvCodeReader.MV_CODEREADER_E_BUFOVER: errorMsg += " Cache is full "; break; case MvCodeReader.MV_CODEREADER_E_CALLORDER: errorMsg += " Function calling order error "; break; case MvCodeReader.MV_CODEREADER_E_PARAMETER: errorMsg += " Incorrect parameter "; break; case MvCodeReader.MV_CODEREADER_E_RESOURCE: errorMsg += " Applying resource failed "; break; case MvCodeReader.MV_CODEREADER_E_NODATA: errorMsg += " No data "; break; case MvCodeReader.MV_CODEREADER_E_PRECONDITION: errorMsg += " Precondition error, or running environment changed "; break; case MvCodeReader.MV_CODEREADER_E_VERSION: errorMsg += " Version mismatches "; break; case MvCodeReader.MV_CODEREADER_E_NOENOUGH_BUF: errorMsg += " Insufficient memory "; break; case MvCodeReader.MV_CODEREADER_E_UNKNOW: errorMsg += " Unknown error "; break; case MvCodeReader.MV_CODEREADER_E_GC_GENERIC: errorMsg += " General error "; break; case MvCodeReader.MV_CODEREADER_E_GC_ACCESS: errorMsg += " Node accessing condition error "; break; case MvCodeReader.MV_CODEREADER_E_ACCESS_DENIED: errorMsg += " No permission "; break; case MvCodeReader.MV_CODEREADER_E_BUSY: errorMsg += " Device is busy, or network disconnected "; break; case MvCodeReader.MV_CODEREADER_E_NETER: errorMsg += " Network error "; break; } Console.WriteLine(errorMsg, "PROMPT"); } #endregion } }