zoukankan      html  css  js  c++  java
  • C#WinCE程序(.NET Compact Framework 3.5)项目重构面向抽象设计

    重构关注点

    • 遵循开闭原则
    • 面向抽象设计
    • 实现设备程序端可动态配置

    重构的需求

    领导想省事提出需求,将现有PDA程序修改为支持PC端由电器工程师根据实际的生产流程可配置,PDA程序在读取配置文件后动态生成导航界面。然后导航绑定的是PDA程序Dll里的界面。公司的综合赋码管理系统(CMS)作为服务器端对PDA暴露WCF服务,PDA在执行扫描操作后对CMS发起请求,CMS收到请求后匹配分析PDA的请求,分析完再返回执行结果给PDA。场景就是这样一个场景,PDA扫描条码的操作分:扫描一个码,扫描两个码,扫描多个码三种。领导让写3个界面,其实这正好可以抽象一下,相当于1个界面就能搞定;于是设计了一个扫描操作的基类窗体,把扫描的基本操作写在基类里,使用模板设计模式,扫多少个码的界面继承基类重用大部分扫描的处理逻辑。主要流程是PC端通过反射获取PDA程序的Dll里的窗体类列表,外部定义好PDA要展示的功能清单序列化成为Json格式的文件,PC端使用MTP传输到PDA上,PDA读取该文件来动态生成导航界面。

    重构的过程

    1)定义数据传输对象

    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.Text;
    
    namespace ehsure.Core.Data.dto
    {
        [Serializable]
        /// <summary>
        /// 主界面菜单实体类
        /// </summary>
        public class DesignConfig
        {
            /// <summary>
            /// 界面宽度
            /// </summary>
            public int Width { get; set; }
            /// <summary>
            /// 界面高度
            /// </summary>
            public int Height { get; set; }
            /// <summary>
            /// 界面下所有控件
            /// </summary>
            public List<ControlsConfig> ControlsList { get; set; }
        }
    }
    DesignConfig
    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.Text;
    
    namespace ehsure.Core.Data.dto
    {
        [Serializable]
        /// <summary>
        /// 控件UI配置参数实体
        /// </summary>
        public class ControlsConfig
        {
            /// <summary>
            /// 控件ID
            /// </summary>
            public string ID { get; set; }
            /// <summary>
            /// 控件显示
            /// </summary>
            public string ShowText { get; set; }
            /// <summary>
            /// 控件宽度
            /// </summary>
            public int ControlWidth { get; set; }
            /// <summary>
            /// 控件高度
            /// </summary>
            public int ControlHeight { get; set; }
    
            /// <summary>
            /// 控件命令字
            /// </summary>
            public string Command { get; set; }
            /// <summary>
            /// 控件要打开的界面
            /// </summary>
            public string ForwardForm { get; set; }
    
            /// <summary>
            /// 位置坐标X
            /// </summary>
            public int X { get; set; }
    
            /// <summary>
            /// 位置坐标Y
            /// </summary>
            public int Y { get; set; }
    
            /// <summary>
            /// 排序号
            /// </summary>
            public int Sort { get; set; }
        }
    }
    ControlsConfig

    2)重构解决方案

    原来的主程序集是个exe,建立职责是UI层的程序集,建立PDA主入口程序集。

    3)编码实现动态导航(使用的自定义控件来代替Button)

     自定义控件MenuButton

    /// <summary>
        /// 菜单按钮,自定义控件
        /// </summary>
        public class MenuButton : Button
        {
            public string ActiveFlag = "";
            public string Command { get; set; }
    
            public string ForwardForm { get; set; }
    
            protected bool itemActiveFlag = false;
            /// <summary>
            /// 是否处于被选中状态
            /// </summary>
            public bool ItemActiveFlag
            {
                get { return itemActiveFlag; }
                set
                {
                    itemActiveFlag = value;
                    if (value)
                        Text = ActiveFlag + Text;
                    else Text = Text.Replace(ActiveFlag, "");
                }
            }
    
            private StringFormat sf;
            public MenuButton()
            {
                BackColor = Color.White;
                ForeColor = Color.Black;
                Height = 28;
                Font = new Font("微软雅黑", 14F, FontStyle.Bold);
                sf = new StringFormat();
                sf.Alignment = StringAlignment.Center;
                sf.LineAlignment = StringAlignment.Center;
            }        
    
            protected override void OnGotFocus(EventArgs e)
            {
                BackColor = SystemColors.Highlight;
                ForeColor = Color.OrangeRed;
                ItemActiveFlag = true;
            }
    
            protected override void OnLostFocus(EventArgs e)
            {
                BackColor = Color.White;
                ForeColor = Color.Black;
                ItemActiveFlag = false;
            }
        }
    MenuButton

     导航工作区的父容器就是一个Panel,MenuButton的高度是动态计算的,宽带是匹配父容器。

    public partial class ShellMainForm : Form
        {
            public ShellMainForm()
            {
                InitializeComponent();
                this.Load += new EventHandler(ShellMainForm_Load);
                this.KeyPreview = true;
                this.KeyDown += new KeyEventHandler(ShellMainForm_KeyDown);
            }
    
            void ShellMainForm_KeyDown(object sender, KeyEventArgs e)
            {
                if (e.KeyData == Keys.F1)
                {
                    using (SystemTimeSetForm frm = new SystemTimeSetForm())
                    {
                        var result = frm.ShowDialog();
                        if (result.Equals(DialogResult.OK))
                        {
                            this.statusBar.Text = DateTime.Now.ToLongDateString() + " " + DateTime.Now.DayOfWeek;
                        }
                    }
                }
    
                if (e.KeyData == Keys.F2)
                {
                    using (var powerManager = new PowerManagement())
                    {
                        powerManager.SetSystemPowerState(PowerManagement.SystemPowerStates.Suspend);
                    }
                }
            }
    
            void ShellMainForm_Load(object sender, EventArgs e)
            {
                try
                {
                    Cursor.Current = Cursors.WaitCursor;
                    MaximizeBox = false;
                    MinimizeBox = false;
                    FormBorderStyle = FormBorderStyle.FixedSingle;
                    this.Text = "CMS智能终端";
                    this.Width = Screen.PrimaryScreen.WorkingArea.Width;
                    this.Height = Screen.PrimaryScreen.WorkingArea.Height;
                    this.Left = 0;
                    this.Top = 0;
                    statusBar.Text = string.Join(" ", new string[] 
                    { 
                        "线号:" + DeviceContext.GetInstance().GetGlobalConfig().LineNum ,
                        "设备号:" + DeviceContext.GetInstance().GetGlobalConfig().DeviceNum 
                    });
                    TestLogin();
                    DriveInit();
                }
                finally
                {
                    Cursor.Current = Cursors.Default;
                }
            }
    
            /// <summary>
            /// 初始化系统功能列表
            /// </summary>
            /// <param name="config"></param>
            void InitSystemNavigateBar(DesignConfig config)
            {
                var list = config.ControlsList.OrderByDescending(m => m.Sort);
                if (list.Any())
                {
                    int index = 0;
                    //list.Reverse();
                    foreach (var navigateItem in list)
                    {
                        var btn = new MenuButton();
                        btn.TabIndex = index;
                        btn.Dock = DockStyle.Top;
                        btn.TabIndex = workareaPanel.Controls.Count;
                        btn.Text = navigateItem.ShowText;
                        btn.ForwardForm = navigateItem.ForwardForm;
                        btn.Click += new EventHandler(NavigateButton_Click);
                        btn.KeyDown += new KeyEventHandler(NavigateButton_KeyDown);
                        workareaPanel.Controls.Add(btn);
                        index++;
                    }
                }
            }
            /// <summary>
            /// 响应导航按钮回车事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void NavigateButton_KeyDown(object sender, KeyEventArgs e)
            {
                if (e.KeyValue == 13)
                    NavigateButton_Click(sender, null);
            }
            /// <summary>
            /// 响应导航单击事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void NavigateButton_Click(object sender, EventArgs e)
            {
                RunModuleForm((MenuButton)sender);
            }
    
            private void menuClose_Click(object sender, EventArgs e)
            {
                if (MessageBox.Show("确认要退出系统", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
                {
                    this.Close();
                    Application.Exit();
                }
            }
    
            /// <summary>
            /// 动态打开模块窗体
            /// </summary>
            /// <param name="mb">MenuButton 被点击的控件
            /// mb.ForwardForm要打开的窗体类名:{命名空间+","+类名}
            /// mb.Command {REPLACE,DELETE...CMS脚本对应的指令名称}</param>
            protected void RunModuleForm(MenuButton mb)
            {
                try
                {
                    if (string.IsNullOrEmpty(mb.ForwardForm))
                    {
                        throw new Exception("模块或者窗体没有设定类库信息!");
                    }
                    string[] tempModulesInfo = mb.ForwardForm.Split(",".ToCharArray());
                    Assembly asb = Assembly.Load(tempModulesInfo.FirstOrDefault());
                    string frmTypeName = string.Join(".", tempModulesInfo);
                    var form = asb.GetTypes().Where(p => p.FullName.Equals(frmTypeName)).FirstOrDefault();
                    if (form != null)
                    {
                        DeviceContext.GetInstance().OperateTypeText = mb.Text.Replace(mb.ActiveFlag, "");
                        var frm = (System.Windows.Forms.Form)Activator.CreateInstance(form);
                        if (!string.IsNullOrEmpty(mb.Command))
                        {
                            DeviceContext.GetInstance().CurrentCommand = mb.Command;
                        }
                        frm.ShowDialog();
                    }
                    else
                        throw new Exception(string.Format("类名:{0}不存在!", frmTypeName));
                }
                catch (Exception ex)
                {
                    //throw ex;
                    MessageBox.Show("错误描述:" + Environment.NewLine + ex.Message + Environment.NewLine + ex.StackTrace, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
                }
            }
            /// <summary>
            /// 获取应用程序界面导航配置
            /// </summary>
            /// <returns></returns>
            protected DesignConfig GetDesignNavigateConfig()
            {
                var list = new List<ControlsConfig>();
                System.Action<DesignConfig> addDefaultItemTask = (dc) =>
                {
                    dc.ControlsList.Add(new ControlsConfig
                    {
                        ID = Guid.NewGuid().ToString().Replace("-", ""),
                        Command = "",
                        ForwardForm = "ehsure.Smart.FlowUI,AdminSettingForm",
                        ShowText = "设备配置",
                        ControlHeight = 0,
                        ControlWidth = 0,
                        X = 0,
                        Y = 0,
                        Sort = Int32.MaxValue
                    });
                };
                var path = new DirectoryInfo(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase));
                string fileName = path.FullName + @"ConfigDesignConfig.Config";
                if (!File.Exists(fileName))
                {
                    DesignConfig dc = new DesignConfig
                    {
                        Height = Screen.PrimaryScreen.WorkingArea.Height,
                        Width = Screen.PrimaryScreen.WorkingArea.Width,
                        ControlsList = list
                    };
                    addDefaultItemTask.Invoke(dc);
                    string fileContext = JsonConvert.SerializeObject(dc);
                    using (var fs = new FileStream(fileName, FileMode.Create))
                    {
                        byte[] buffer = Encoding.UTF8.GetBytes(fileContext);
                        fs.Write(buffer, 0, buffer.Length);
                        fs.Flush();
                        fs.Close();
                    }
                    return dc;
                }
                else
                {
                    using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                    {
                        byte[] buffer = new byte[fs.Length];
                        fs.Read(buffer, 0, buffer.Length);
                        string fileContext = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
                        DesignConfig dc = JsonConvert.DeserializeObject<DesignConfig>(fileContext);
                        if (dc != null && !dc.ControlsList.Any(m => m.Sort == Int32.MaxValue))
                        {
                            addDefaultItemTask.Invoke(dc);
                        }
                        fs.Close();
                        return dc;
                    }
                }
            }
            /// <summary>
            /// 测试连接CMS
            /// </summary>
            private void TestLogin()
            {
                string outMsg;
                var codeInfo = new TaskDTOCode
                {
                    Code = "LoginTest"
                };
                CFDataService.SubmitToControl(codeInfo, out outMsg);
            }
            /// <summary>
            /// 加载驱动
            /// </summary>
            private void DriveInit()
            {
                string dllName = ScanCache.DllType.DllName;
                string dllService = ScanCache.DllType.DllService;
                string[] file = Directory.GetFiles(Path.GetDirectoryName(Assembly.GetCallingAssembly().GetName().CodeBase) + "\", dllName);
                if (file.Length == 0)
                {
                    throw new Exception(ErrorMessage.ScanComponentLoadFailed);
                }
                else
                {
                    Assembly assembly = Assembly.LoadFrom(file[0]);
                    Type typeScanService = assembly.GetType(dllService);
                    ScanCache.BaseScanDirve = (BaseScanDriveService)assembly.CreateInstance(typeScanService.FullName);
                    ScanCache.BaseScanDirve.Init();
                }
            }
            /// <summary>
            /// 界面排列布局时触发,初始化界面导航
            /// </summary>
            /// <param name="e"></param>
            protected override void OnResize(EventArgs e)
            {
                base.OnResize(e);
                workareaPanel.Controls.Clear();
                var config = GetDesignNavigateConfig();
                if (config != null)
                {
                    InitSystemNavigateBar(config);
                }
                if (workareaPanel.Controls.Count > 0 && workareaPanel.Height < Screen.PrimaryScreen.WorkingArea.Height)
                {
                    foreach (Control ctrl in workareaPanel.Controls)
                    {
                        ctrl.Height = workareaPanel.Height / workareaPanel.Controls.Count - 2;
                    }
                    workareaPanel.Controls[workareaPanel.Controls.Count - 1].Focus();
                }
            }
        }

    4)UI层业务窗体的实现是本篇随笔的重点

     重点考量的地方就是前面所说的要面向抽象设计,封装和继承。

    所有业务窗体的基类

    /// <summary>
        /// 窗体基类
        /// </summary>
        public partial class BaseForm : Form
        {
            private bool isScaleDown = true;
            /// <summary>
            /// 是否屏幕自适应
            /// </summary>
            public bool IsScaleDown
            {
                get { return isScaleDown; }
                set { isScaleDown = value; }
            }
    
            private bool enterToTab = false;
            /// <summary>
            /// 是否回车变Tab
            /// </summary>
            public bool EnterToTab
            {
                get { return enterToTab; }
                set { enterToTab = value; }
            }
            public BaseForm()
            {
                InitializeComponent();
                KeyPreview = true;
                SetInterval();
            }
    
            private ScannerErrorService ScannerErrorService;
            private ScannerErrorService getScannerErrorService()
            {
                return ScannerErrorService ?? (ScannerErrorService = new ScannerErrorService());
            }
    
            protected virtual void InitMenu()
            {
            }
    
            protected override void OnActivated(EventArgs e)
            {
                CustomizeCursor.CloseCursor();
                base.OnActivated(e);
            }
    
            protected void AddMenuItem(MainMenu mainMenu, string text, ehsure.Common.Action func)
            {
                MenuItem item = new MenuItem();
                item.Text = text;
                item.Click += delegate(object sender, EventArgs e)
                {
                    try
                    {
                        CustomizeCursor.ShowWaitCursor();
                        func();
                    }
                    catch (Exception ex)
                    {
                        ShowMessageBoxForm(ex);
                    }
                    finally
                    {
                        CustomizeCursor.CloseCursor();
                    }
                };
                mainMenu.MenuItems.Add(item);
            }
    
            protected void AddMenuItem(MainMenu mainMenu, string mainText, string text, ehsure.Common.Action func)
            {
                MenuItem mi = null;
                Menu.MenuItemCollection collection = mainMenu.MenuItems;
                for (int i = 0; i < collection.Count; i++)
                {
                    MenuItem item = collection[i];
                    if (string.Equals(item.Text, mainText, StringComparison.OrdinalIgnoreCase))
                    {
                        mi = item;
                        continue;
                    }
                }
                if (mi == null)
                {
                    mi = new MenuItem();
                    mi.Text = mainText;
                    mainMenu.MenuItems.Add(mi);
                }
                MenuItem sub = new MenuItem();
                sub.Text = text;
                sub.Click += delegate(object sender, EventArgs e)
                {
                    try
                    {
                        CustomizeCursor.ShowWaitCursor();
                        func();
                    }
                    catch (Exception ex)
                    {
                        ShowMessageBoxForm(ex);
                    }
                    finally
                    {
                        CustomizeCursor.CloseCursor();
                    }
                };
                mi.MenuItems.Add(sub);
            }
    
            protected virtual void FireAction(ehsure.Common.Action action)
            {
                try
                {
                    CustomizeCursor.ShowWaitCursor();
                    action();
                }
                catch (Exception ex)
                {
                    ShowMessageBoxForm(ex);
                }
                finally
                {
                    CustomizeCursor.CloseCursor();
                }
            }
    
            public virtual void FireActionCode(ActionCode action, string code, int inputType)
            {
                try
                {
                    CustomizeCursor.ShowWaitCursor();                
                    action(code, inputType);
                }
                catch (Exception ex)
                {
                    ShowMessageBoxForm(ex);
                }
                finally
                {
                    CustomizeCursor.CloseCursor();
                }
            }
    
            private void BaseForm_Load(object sender, EventArgs e)
            {
                InitMenu();
            }
    
            public void ShowMessageBoxForm(Exception ex)
            {
                CustomizeCursor.CloseCursor();
                try
                {
                    string msg = null;
                    msg = ex.Message;
                    string type = ex.GetType().FullName;
                    if (type == "System.Net.WebException")
                    {
                        msg = "网络异常!";
                    }
                    if (type != "System.Exception" || msg == ErrorMessage.ScanComponentLoadFailed)
                    {
                        ScannerErrorReport error = new ScannerErrorReport()
                        {
                            Id = Guid.NewGuid().ToString(),
                            ErrorInfo = msg,
                            ErrorTime = DateTime.Now,
                            CustomerCode = ScanCache.UserContext.CorpId,
                            CustomerName = ScanCache.UserContext.CorpName,
                            Remark = ex.StackTrace
                        };
                        getScannerErrorService().Insert(error);
                    }
                    MessageBoxForm form = new MessageBoxForm();
                    form.ShowMessage(msg);
                    form.ShowDialog();
                }
                catch (Exception eex)
                {
                    MessageBoxForm form = new MessageBoxForm();
                    form.ShowMessage(eex.Message);
                    form.ShowDialog();
                }
            }
    
            private void SetInterval()
            {
                var file = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase) + "\App.Config";
                XmlDocument doc = new XmlDocument();
                if (!File.Exists(file))
                {
                    ScanCache.SuccessInterval = 200;
                    ScanCache.ErrorInterval = 3000;
                    return;
                }
                doc.Load(file);
                XmlNodeList nodes = doc.GetElementsByTagName("add");
                for (int i = 0; i < nodes.Count; i++)
                {
                    XmlAttribute att = nodes[i].Attributes["key"];
                    if (att != null)
                    {
                        if (att.Value == "SuccessInterval")
                        {
                            att = nodes[i].Attributes["value"];
                            ScanCache.SuccessInterval = Convert.ToInt32(att.Value);
                        }
                        if (att.Value == "ErrorInterval")
                        {
                            att = nodes[i].Attributes["value"];
                            ScanCache.ErrorInterval = Convert.ToInt32(att.Value);
                        }
                    }
                }
            }
    
            private void BaseForm_Closed(object sender, EventArgs e)
            {
                if (DeviceContext.GetInstance().BarcodeData == null)
                {
                    DeviceContext.GetInstance().CurrentCommand = string.Empty;
                    DeviceContext.GetInstance().OperateTypeText = string.Empty;
                }
                this.Close();
            }
    
            /// <summary>
            /// 屏幕自适应
            /// </summary>
            /// <param name="frm"></param>
            private void ScaleDown()
            {
                int scrWidth = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width;
                int scrHeight = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
                if (scrWidth < this.Width)
                    foreach (System.Windows.Forms.Control cntrl in this.Controls)
                    {
                        cntrl.Width = ((cntrl.Width) * (scrWidth)) / (this.Width);
                        cntrl.Left = ((cntrl.Left) * (scrWidth)) / (this.Width);
                    }
                if (scrHeight < this.Height)
                    foreach (System.Windows.Forms.Control cntrl in this.Controls)
                    {
                        cntrl.Height = ((cntrl.Height) * (scrHeight)) / (this.Height);
                        cntrl.Top = ((cntrl.Top) * (scrHeight)) / (this.Height);
                    }
            }
    
            /// <summary>
            /// 递归控件 外接事件Enter变Tab
            /// </summary>
            /// <param name="ctrl"></param>
            void SetControlEnterToTab(Control ctrl)
            {
                foreach (Control subControl in ctrl.Controls)
                {
                    if (subControl is TextBox || subControl is DateTimePicker || subControl is ComboBox || subControl is NumericUpDown)
                    {
                        subControl.KeyDown += new KeyEventHandler(ctrl_KeyDown);
                    }
                    if (ctrl.Controls.Count > 0)
                        SetControlEnterToTab(subControl);
                }
            }
    
            void ctrl_KeyDown(object sender, KeyEventArgs e)
            {
                if (e.KeyValue == 13)
                {
                    var ctrl = sender as Control;
                    if (!string.IsNullOrEmpty(ctrl.Text) && ctrl is TextBox)
                    {
                        var tbx = ctrl as TextBox;
                        tbx.SelectAll();
                    }
                    WinceApi.keybd_event(9, 0, 0, 0);
                }
            }
    
            protected override void OnKeyDown(KeyEventArgs e)
            {
                base.OnKeyDown(e);
                if (e.KeyValue == 27)
                    this.Close();
            }
    
            protected override void OnLoad(EventArgs e)
            {
                if (IsScaleDown)
                    ScaleDown();
                if (EnterToTab)
                    SetControlEnterToTab(this);
                this.Width = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width;
                this.Height = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
                base.OnLoad(e);
            }
        }
    View Code

    扫描业务的基类

    /// <summary>
        /// 扫描窗体基类
        /// </summary>
        public partial class ScanBaseForm : BaseForm
        {
            /// <summary>
            /// 操作类型
            /// </summary>
            public string ScanOperateType
            {
                get { return lbOperType.Text.Trim(); }
                set { lbOperType.Text = value; }
            }
            /// <summary>
            /// 需要扫码个数
            /// </summary>
            public int ScanBarcodeNumber
            {
                get { return int.Parse(lbCount.Text.Trim()); }
                set { lbCount.Text = value.ToString(); }
            }
    
            protected TaskDTOCode _TaskDTOCode = new TaskDTOCode();
    
            protected string _SplitChars = string.Empty;
            protected string _GroupSplitFlag = string.Empty;
            /// <summary>
            /// 需要扫码的个数
            /// </summary>
            protected int _NeedScanNumber = 0;
            /// <summary>
            /// 已经扫描的码
            /// </summary>
            protected List<string> _BarcodeList = new List<string>();
    
            protected Socket pdaClientSocket = null;
    
            public ScanBaseForm()
            {
                InitializeComponent();
                MaximizeBox = false;
                MinimizeBox = false;
                Load += new EventHandler(ScanBaseForm_Load);
            }
    
            #region 扫描处理部分
            public delegate void ActingThread(string code, int inputType);
    
            /// <summary>
            ///  窗体激活时启动扫描头,绑定事件
            /// </summary>
            /// <param name="e"></param>
            protected override void OnActivated(EventArgs e)
            {
                base.OnActivated(e);
                ScanCache.BaseScanHandle = new BaseScanHandle(ScanCodeEventHandle);
                ScanCache.BaseScanDirve.CodeReaded += ScanCache.BaseScanHandle;
                ScanCache.BaseScanDirve.BeginScan();
                tbMessage.Text = "扫描头已经打开,请扫描!";
            }
    
            /// <summary>
            /// 读取截取字符和多码分隔符
            /// </summary>
            protected virtual void GetGlobalConfig()
            {
                string configPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + "\Config\Device.Config";
                if (File.Exists(configPath))
                {
                    using (System.Data.DataSet ds = new System.Data.DataSet())
                    {
                        ds.ReadXml(configPath);
                        if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
                        {
                            var dt = ds.Tables[0];
                            _SplitChars = dt.Rows[0]["CodeSplit"] == null ? string.Empty : dt.Rows[0]["SplitChars"].ToString();
                            _GroupSplitFlag = dt.Rows[0]["CodeSplit"] == null ? string.Empty : dt.Rows[0]["CodeSplit"].ToString();
                        }
                    }
                }
            }
    
            /// <summary>
            /// 截取正确的条码内容
            /// </summary>
            /// <param name="scanData"></param>
            /// <returns></returns>
            protected virtual string ScanCodeToRightCode(string scanData)
            {
                if (!string.IsNullOrEmpty(_SplitChars) && string.IsNullOrEmpty(scanData))
                {
                    string[] temp = scanData.Split(_SplitChars.ToCharArray());
                    if (temp.Length > 1)
                        return temp.LastOrDefault();
                }
                return scanData;
            }
    
            /// <summary>
            /// 扫到码事件触发
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void ScanCodeEventHandle(object sender, BaseScanEventArgs e)
            {
                ActingThread act = new ActingThread(ScanActionExecute);
                this.BeginInvoke(act, new object[] { e.Message, 1 });
            }
    
            /// <summary>
            ///扫描到条码本地窗体处理
            /// </summary>
            /// <param name="code"></param>
            /// <param name="inputType"></param>
            protected virtual void ScanActionExecute(string code, int inputType)
            {
                string barcode = ScanCodeToRightCode(code);
                if (!_BarcodeList.Contains(barcode))
                {
                    _BarcodeList.Add(barcode);
                    tbMessage.Text = string.Format("扫描到条码:{0}", barcode);
                    if (_NeedScanNumber < 10)
                    {
                        int index = _BarcodeList.Count;
                        listView.Items[index - 1].SubItems[0].Text = index.ToString() + "-->";
                        listView.Items[index - 1].SubItems[1].Text = barcode;
                        listView.Refresh();
                    }
                    else
                    {
                        int index = _BarcodeList.Count;
                        var li = listView.Items.Add(new ListViewItem(index.ToString()));
                        li.SubItems[0].Text = index.ToString();
                        li.SubItems.Add(barcode);
                    }
                }
                else
                {
                    new MessageBoxForm().ErrorBeep();
                    tbMessage.ForeColor = Color.Red;
                    tbMessage.Text = "重复扫描!";
                }
                if (_BarcodeList.Count == _NeedScanNumber)
                {
                    FireAction(SendRequest);
                }
                //选中刚刚扫描到的码
                foreach (ListViewItem item in listView.Items)
                {
                    if (item.SubItems[1].Text.Trim().Equals(_BarcodeList.LastOrDefault()))
                    {
                        item.Selected = true;
                    }
                }
                listView.Focus();
            }
    
            /// <summary>
            /// 关闭扫描头,取消绑定
            /// </summary>
            /// <param name="e"></param>
            protected override void OnDeactivate(EventArgs e)
            {
                base.OnDeactivate(e);
                ScanCache.BaseScanDirve.CodeReaded -= ScanCache.BaseScanHandle;
                ScanCache.BaseScanDirve.StopScan();
            }
            #endregion
    
            void ScanBaseForm_Load(object sender, EventArgs e)
            {
                ScanOperateType = DeviceContext.GetInstance().OperateTypeText;
                ScanBarcodeNumber = _NeedScanNumber;
                GetGlobalConfig();
                if (_NeedScanNumber < 10)
                    InitNavigateView();
                else
                {
                    lbCount.Text = "N(多个)";
                    listView.Items.Clear();
                }
                _TaskDTOCode.ParentCode = DeviceContext.GetInstance().CurrentCommand;
                if (DeviceContext.GetInstance().GetGlobalConfig().IsOpenTcpClient)
                {
                    pdaClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    pdaClientSocket.Connect(new IPEndPoint(IPAddress.Parse(DeviceContext.GetInstance().GetGlobalConfig().TcpClientIp), DeviceContext.GetInstance().GetGlobalConfig().TcpPort));
                    if (pdaClientSocket != null && pdaClientSocket.Connected)
                    {
                        tbMessage.Text += (Environment.NewLine + "连接TCP Server成功!");
                    }
                }
            }
    
            /// <summary>
            /// 初始化导航视图
            /// </summary>
            public virtual void InitNavigateView()
            {
                listView.Items.Clear();
                for (int i = 0; i < _NeedScanNumber; i++)
                {
                    var li = listView.Items.Add(new ListViewItem((i + 1).ToString()));
                    li.SubItems[0].Text = "1";
                    li.SubItems.Add("请扫描...");
                }
            }
    
            /// <summary>
            /// 对CMS发起请求 eg: { Code = txt_BoxCode.Text.Trim(), EptCode = txt_BagCode.Text.Trim(), ParentCode = "EA_BOX_BAG" };
            /// </summary>
            protected virtual void SendRequest()
            {
                tbMessage.Text += (Environment.NewLine + "正在发起请求,请等待CMS回应...");
                DeviceContext.GetInstance().BarcodeData = _TaskDTOCode;
                if (!DeviceContext.GetInstance().GetGlobalConfig().IsOpenTcpClient)
                {
                    #region WCF请求
                    string msgifno = "";
                    try
                    {
                        Cursor.Current = Cursors.WaitCursor;
                        CFDataService.SubmitToControl(_TaskDTOCode, out msgifno);
                    }
                    catch (Exception ex)
                    {
                        tbMessage.Text += "CMS返回错误消息:" + ex.Message;
                        return;
                    }
                    finally
                    {
                        Cursor.Current = Cursors.Default;
                    }
                    if (!string.IsNullOrEmpty(msgifno))
                    {
                        tbMessage.Text += (Environment.NewLine + msgifno);
                    }
                    else
                    {
                        tbMessage.Text += "操作失败,CMS服务器端无响应!";
                    }
                    #endregion
                }
                else
                {
                    if (pdaClientSocket != null && !pdaClientSocket.Connected)
                    {
                        pdaClientSocket.Connect(new IPEndPoint(IPAddress.Parse(DeviceContext.GetInstance().GetGlobalConfig().TcpClientIp), DeviceContext.GetInstance().GetGlobalConfig().TcpPort));
                    }
                    if (pdaClientSocket == null || !pdaClientSocket.Connected)
                    {
                        tbMessage.Text += (Environment.NewLine + "和CMS服务器端建立连接失败!");
                    }
                    byte[] buffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(_TaskDTOCode));
                    try
                    {
                        Cursor.Current = Cursors.WaitCursor;
                        pdaClientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
                        byte[] revBuffer = new byte[1024];
                        int len = pdaClientSocket.Receive(revBuffer, SocketFlags.None);
                        if (len > 0)
                        {
                            string resultMessage = Encoding.UTF8.GetString(revBuffer, 0, len);
                            tbMessage.Text += (Environment.NewLine + resultMessage);
                        }
                    }
                    catch (Exception ex)
                    {
                        tbMessage.Text += (Environment.NewLine + ex.Message);
                    }
                    finally
                    {
                        Cursor.Current = Cursors.Default;
                    }
                }
            }
    
            private void menuItem2_Click(object sender, EventArgs e)
            {
                Close();
            }
    
            private void menuItem1_Click(object sender, EventArgs e)
            {
                if (_BarcodeList.Count != _NeedScanNumber && _NeedScanNumber < 10)
                {
                    tbMessage.Text += (Environment.NewLine + "扫描条码个数不正确!");
                    return;
                }
                FireAction(SendRequest);
            }
    
            private void menuItem3_Click(object sender, EventArgs e)
            {
                if (_BarcodeList.Count > 0)
                {
                    tbMessage.Text = "已清空,请开始扫描!";
                    _BarcodeList.Clear();
                    int index = 0;
                    foreach (ListViewItem item in listView.Items)
                    {
                        index++;
                        item.SubItems[0].Text = index.ToString();
                        item.SubItems[1].Text = "请扫描...";
                    }
                    listView.Refresh();
                }
                else
                {
                    new MessageBoxForm().ErrorBeep();
                    tbMessage.Text = "已扫编码数量为0,请开始扫描!";
                }
            }
     
        }

    具体子类是实现,只是需要几行代码。

      [ModuleDescription("外部可调用","扫1个码进行操作,适用于整箱删除,查关联关系等操作。")]
        public partial class ScanOneForm : ScanBaseForm
        {
            public ScanOneForm()
            {
                InitializeComponent();
                _NeedScanNumber = 1;
                Menu = mainMenu2;
            }
    
            protected override void SendRequest()
            {
                _TaskDTOCode.Code = _BarcodeList.FirstOrDefault();
                _TaskDTOCode.EptCode = "";
                base.SendRequest();
            }
        }
    [ModuleDescription("外部可调用","扫两个码进行操作,适用于比如单品替换,添加到箱等操作。")]
        public partial class ScanTwoForm : ScanBaseForm
        {
            public ScanTwoForm()
            {
                InitializeComponent();
                _NeedScanNumber = 2;
                Menu = mainMenu2;
            }
    
            protected override void SendRequest()
            {
                _TaskDTOCode.Code = _BarcodeList.FirstOrDefault();
                _TaskDTOCode.EptCode = _BarcodeList.LastOrDefault();
                base.SendRequest();
            }
        }
    扫描2个码
    [ModuleDescription("外部可调用","扫N个码进行操作,适用批量处理等操作。码之间用分隔符连接,N指的是大于10的情况。")]
        public partial class ScanNForm : ScanBaseForm
        {  
            public ScanNForm()
            {
                InitializeComponent();
                _NeedScanNumber = 11;
                Menu = mainMenu2;
            }
    
            protected override void SendRequest()
            {
                _TaskDTOCode.Code = string.Join(_GroupSplitFlag, _BarcodeList.ToArray());
                _TaskDTOCode.EptCode = "";
                base.SendRequest();
            }
        }
    扫描N个码

    重构的心得

    又是一次认真思考过后的编程实践。总之,不是为了完成任务而编码。

    重构的成果

    这样的文章只是适合自己记录一下,编码心得,思路。对外人好像也没啥用吧。只是觉得好久不写博客,练习一下。

  • 相关阅读:
    ActiveReport9 在MVC4项目中出错
    EntityFramework5.0 DataBase-First 在三层架构中的使用,分离实体类到Model层。
    SqlServer存在并删除 表,函数,view等
    Visual Studio常用技巧与插件
    让 WPF 应用程序单例化
    C# 常用加密方法一 AES 与 DES
    Windows 的公共文件夹
    Hibernate中Criteria的完整用法
    maven依赖关系中Scope的作用
    Eclipse取消设置项目默认空间
  • 原文地址:https://www.cnblogs.com/datacool/p/datacool_2017_pda.html
Copyright © 2011-2022 走看看