• C# Winform下一个热插拔的MIS/MRP/ERP框架11(启航)


      初学时,有了想法却完全不知道该从何下指,此序列将抛砖引玉,与大家共同学习进步。

      一个程序的初始,必然是启动。

      我的要求:

      1、应用程序保持单例;

      2、从配置文件加载一些基础数据进行初始化;

      3、显示软件的LOGO页面;

      4、判断应用程序是否有更新;

      4、进入用户登录界面;

      5、用户成功登录后显示主界面。

      

      如上图,基本达成目标,这个项目也是很简单的结构:

    看窗体名称就知道各自的用途了。主要的Program.cs代码如下:

        static class Program
        {
            public static bool 切换用户 = false;
    
            /// <summary>
            /// 主体框架应用程序的主入口点。
            /// </summary>
            [STAThread]
            static void Main()
            {
                string 实例标识 = Assembly.GetExecutingAssembly().GetName().Name + "_SingtonB20";
                Mutex mutex = new Mutex(true, 实例标识, out bool 单实例);
                if (!单实例)
                {
                    唤醒进程(实例标识);
                    return;
                }
    
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.DoEvents();
    
                //初始化全局DS
                if (GlbInfo.DSGlb == null) GlbInfo.DSGlb = new System.Data.DataSet();
                else
                {
                    GlbInfo.DSGlb.Clear();
                    GlbInfo.DSGlb.Tables.Clear();
                }
    
                //加载全局多语言资源
                try
                {
                    AppInit.CreateDT_MulLang(AppInfo.GetFile(AppInfo.AppFile.MulMessage), "Message_Core");
                    AppInit.CreateDT_MulLang(AppInfo.GetFile(AppInfo.AppFile.MulSurface), "Surface_Core");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    Environment.Exit(0);
                }
    
                //展示闪屏窗体
                Fm20Splash 闪屏窗 = new Fm20Splash();
                闪屏窗.ShowDialog();
    
                //系统检测正常则显示登录界面,否则退出应用
                if (闪屏窗.DialogResult == DialogResult.OK)
                {
                    显示登录:
                    切换用户 = false;
                    Fm20Login fmLogin = new Fm20Login();
                    fmLogin.ShowDialog();
                    if (fmLogin.DialogResult == DialogResult.OK)
                    {
                        Application.Run(new Fm20Main());
                    }
                    else
                    {
                        Application.Exit();
                    }
                    //当关闭主程序的时候会执行这个代码,在关闭主程序的时候需要给IsLogin 设置成true
                    //重新回到登录窗口.
                    if (切换用户)
                    {
                        goto 显示登录;
                    }
    
                }
                else
                {
                    Application.Exit();
                }
    
            }
            public static void 唤醒进程(string 进程名称)
            {
                try
                {
                    Process proc = Process.GetCurrentProcess();
    
                    string assemblyName = Assembly.GetExecutingAssembly().GetName().Name + 进程名称;
    
                    foreach (Process 进程 in Process.GetProcessesByName(进程名称))
                    {
                        if (proc.Id != 进程.Id)                    
                        {
                            IntPtr hWnd = 进程.MainWindowHandle;
                            if (WinAPI.IsIconic(hWnd))
                            {
                                WinAPI.ShowWindowAsync(hWnd, WinAPIConst.SW_RESTORE);
                            }
                            WinAPI.SetForegroundWindow(hWnd);
                            return;
                        }
                    }
                }
                catch
                {
                }
            }
    
        }
    Program.cs

    一、第一个被运行的窗体(闪屏窗口):

        /// <summary>
        /// Splash闪屏窗体
        /// </summary>
        public partial class Fm20Splash : Fm11Base
        {
            /// <summary>
            /// 创建闪屏窗体
            /// </summary>
            public Fm20Splash()
            {
                InitializeComponent();
                OINI oINI = new OINI(AppInfo.GetFile(AppInfo.AppFile.ConfigCore));
                GlbInfo.Language = oINI.ReadString("Global", "CurrentLang", "LL");
                string licCompany = oINI.ReadString("Global", "License_To_" + GlbInfo.Language, "所有人");
                LabLicTo.Text = MultiLang.Surface(this, "LabLicTo", "授权给: ") + licCompany;
                if (GlbInfo.Language == "LL") LabSysTitle.Text = "IMES (智能制造执行系统)"; else LabSysTitle.Text= "IMES (Intelligent Manufacturing Execution System)";
            }
    
            private void Fm20Splash_MouseDown(object sender, MouseEventArgs e)
            {
                WinAPI.ReleaseCapture();
                WinAPI.SendMessage(Handle, WinAPIConst.WM_SYSCOMMAND, WinAPIConst.SC_MOVE + WinAPIConst.HTCAPTION, 0);
            }
    
            private static bool Delay(int delayTime)
            {
                DateTime now = DateTime.Now;
                int s;
                do
                {
                    TimeSpan spand = DateTime.Now - now;
                    s = spand.Seconds;
                    Application.DoEvents();
                }
                while (s < delayTime);
                return true;
            }
    
            private void Fm20Splash_Shown(object sender, EventArgs e)
            {
                //开始检测系统配置是否符合要求
                //检测1:FRAMEWORK
                //检测2:检查组件资源
                #region 检测1:检测更新
                SetMainStatus(MultiLang.Surface(this, "ChkAppVersion","正在检查系统版本..."));
                Delay(1);
    
                string localPath = AppDomain.CurrentDomain.BaseDirectory;
                localPath = localPath.Substring(0, localPath.Length - 1);
                string updateTxtFile = localPath + @"UpdateLog.txt";
                //当更新指引文件不存在(如调试时),将跳过自动更新检测.
                if (File.Exists(updateTxtFile))
                {
                    string[] allLines = File.ReadAllLines(localPath + @"UpdateLog.txt");
    
                    string remotePath = string.Empty;
                    foreach (string line in allLines)
                    {
                        if (line.IndexOf("UpdatePath=") >= 0)
                        {
                            remotePath = line.Substring(line.IndexOf("UpdatePath=") + 11);
                            break;
                        }
                    }
    
                    if (NeedUpdate(localPath, remotePath))
                    {
                        File.Delete(localPath + "\" + @"A19.exe");
                        File.Copy(remotePath + "\" + @"A19.exe", localPath + "\" + @"A19.exe", true);
    
                        string updFile = AppDomain.CurrentDomain.BaseDirectory + @"A19.exe";
                        Process.Start(updFile);
                        DialogResult = DialogResult.Cancel;
                        Application.Exit();
                    }
                }
                #endregion
    
                #region 清理过期插件版本,只保留最近的一项
                //根目录下不存在DLL或EXE原文件,则查找日期最后面的文件作为加载文件
                //查找M开头的exe和dll文件,规划M2-M8为模组EXE命名区域.如M22,M88
                var modFiles = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory).Select(f => new FileInfo(f)).Where(f => ((f.Name.IndexOf("M") == 0 ) && f.Name.IndexOf("--") == 3) && (f.Name.IndexOf(".exe") >= 0 || f.Name.IndexOf(".dll") >= 0)).OrderBy(f => f.Name);
                string prevFileSpl = string.Empty;
                FileInfo ofi = null;
                foreach (var s in modFiles)
                {
                    if (!string.IsNullOrEmpty(prevFileSpl))
                    {
                        if (s.Name.Substring(0, s.Name.IndexOf("--")) == prevFileSpl.Substring(0, prevFileSpl.IndexOf("--")))
                        {
                            if (s.LastWriteTime >= ofi.LastWriteTime)
                            {
                                ofi.Delete();
                            }
                            else
                            {
                                s.Delete();
                            }
                        }
                    }
                    ofi = s;
                    prevFileSpl = s.Name;
                }
    
                #endregion
    
                DialogResult = DialogResult.OK;
            }
            /// <summary>
            /// 判断程序是否需要更新
            /// </summary>
            /// <param name="localPath"></param>
            /// <param name="remotePath"></param>
            /// <returns></returns>
            private bool NeedUpdate(string localPath, string remotePath)
            {
                try
                {
                    FileInfo fiUL = new FileInfo(localPath + @"UpdateLog.txt");
                    FileInfo fiUR = new FileInfo(remotePath + @"UpdateLog.txt");
                    if (fiUL.LastWriteTime == fiUR.LastWriteTime)
                    {
                        SetMainStatus(MultiLang.Surface(this, "ChkAppVersion","正在检查系统版本...") + "OK!");
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                catch (Exception)
                {
                    //出错将返回false,比如:没有设置好更新路径。
                    return false; 
                }
            }
        }
    Fm20Splash.cs

    它继承自一个基类窗体Fm11Base,默认会做一些例如加载多语言文本的事情,没这个需求直接继承Form也可以。

    二、这个页面通过后(有更新的话会跳到自动更新程序,可以忽略),会进入到登录窗体:

        /// <summary>
        /// 登录窗体
        /// </summary>
        public partial class Fm20Login : Fm11Base
        {
            bool IsLogin = false;
            protected internal string SelAccountNO ;
            protected internal string SelAccountName ;
            private static readonly string DftAESKeyOfDlls = @"James/Wang/";
    
            private bool m_aeroEnabled;
            private static Fm20LoginTitle fm20LoginTitle;
    
            public string UserID
            {
                get { return TxtUserID.Text; }
                set { TxtUserID.Text = value; }
            }
    
            public Fm20Login()
            {
                m_aeroEnabled = false;
                InitializeComponent();
                fm20LoginTitle = new Fm20LoginTitle();
    
            }
    
            #region 无边框窗体处理
            /// <summary>
            /// 拖动无边框窗体
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void OnFormDrag(object sender, MouseEventArgs e)
            {
                WinAPI.ReleaseCapture();
                WinAPI.SendMessage(Handle, WinAPIConst.WM_SYSCOMMAND, WinAPIConst.SC_MOVE + WinAPIConst.HTCAPTION, 0);
            }
    
            protected override CreateParams CreateParams
            {
                get
                {
                    m_aeroEnabled = CheckAeroEnabled();
                    CreateParams cp = base.CreateParams;
                    if (!m_aeroEnabled)
                        cp.ClassStyle |= WinAPIConst.CS_DropSHADOW;
                    return cp;
                }
            }
    
            private bool CheckAeroEnabled()
            {
                if (Environment.OSVersion.Version.Major >= 6)
                {
                    int enabled = 0;
                    WinAPI.DwmIsCompositionEnabled(ref enabled);
                    return (enabled == 1) ? true : false;
                }
                return false;
            }
    
            protected override void WndProc(ref Message m)
            {
                base.WndProc(ref m);
    
                switch (m.Msg)
                {
                    case WinAPIConst.WM_NCPAINT:
                        if (m_aeroEnabled)
                        {
                            var v = 2;
                            WinAPI.DwmSetWindowAttribute(this.Handle, 2, ref v, 4);
                            WinAPIConst.MARGINS margins = new WinAPIConst.MARGINS()
                            {
                                bottomHeight = 1,
                                leftWidth = 1,
                                rightWidth = 1,
                                topHeight = 1
                            };
                            WinAPI.DwmExtendFrameIntoClientArea(this.Handle, ref margins);
    
                        }
                        break;
                    default:
                        break;
                }
    
                if (m.Msg == WinAPIConst.WM_NCHITTEST && (int)m.Result == WinAPIConst.HTCLIENT)
                    m.Result = (IntPtr)WinAPIConst.HTCAPTION;
    
            }
    
            #endregion
    
            private void MitClose_Click(object sender, EventArgs e)
            {
                DialogResult = DialogResult.Cancel;
            }
    
            private void MitMini_Click(object sender, EventArgs e)
            {
                WindowState = FormWindowState.Minimized;
            }
    
            private void Fm20Login_Shown(object sender, EventArgs e)
            {
                if (!fm20LoginTitle.Visible)
                {
                    fm20LoginTitle.Show(this);
                }
                else
                {
                    fm20LoginTitle.BringToFront();
                }
                fm20LoginTitle.Left = this.Left + this.Width / 2 - fm20LoginTitle.Width / 2;
                fm20LoginTitle.Top = this.Top + SplPnlMain.Panel1.Height - fm20LoginTitle.Height / 2;
            }
    
            private void Fm20Login_Move(object sender, EventArgs e)
            {
                fm20LoginTitle.Left = this.Left + this.Width / 2 - fm20LoginTitle.Width / 2;
                fm20LoginTitle.Top = this.Top + SplPnlMain.Panel1.Height - fm20LoginTitle.Height / 2;
            }
    
            private void Fm20Login_Load(object sender, EventArgs e)
            {
                try
                {
                    LabStsVersion.Text = "Version: " + this.ProductVersion;
                    TstMILangLL.Checked = (GlbInfo.Language == "LL");
                    TstMILangLI.Checked = !TstMILangLL.Checked;
                    PicLogo.Image = Image.FromFile(AppInfo.GetPath(AppInfo.AppPath.Image) + @"AppLoginLd.png");
                    //读取上一次记住的用户名
                    OINI oPIniFile = new OINI(AppInfo.GetFile(AppInfo.AppFile.ConfigCore));
                    TxtUserID.Text = oPIniFile.ReadString("Login", "LastUserID", string.Empty);
                    SetMainStatus("..");
                }
                catch (Exception)
                {
                }
            }
    
            private void TxtUserCode_TextChanged(object sender, EventArgs e)
            {
                CmdClearUser.Visible = !(string.IsNullOrEmpty(TxtUserID.Text.Trim()));
            }
    
            private void TxtUserCode_Enter(object sender, EventArgs e)
            {
                PicFeedUser.BackgroundImage= Properties.Resources.LoginUserB;
            }
    
            private void TxtUserCode_Leave(object sender, EventArgs e)
            {
                PicFeedUser.BackgroundImage = Properties.Resources.LoginUserH;
            }
    
            private void TxtUserPass_TextChanged(object sender, EventArgs e)
            {
                CmdClearPwd.Visible = !(string.IsNullOrEmpty(TxtUserPass.Text.Trim()));
            }
    
            private void TxtUserPass_Enter(object sender, EventArgs e)
            {
                PicFeedLock.BackgroundImage = Properties.Resources.LoginPwdB;
            }
    
            private void TxtUserPass_Leave(object sender, EventArgs e)
            {
                PicFeedLock.BackgroundImage = Properties.Resources.LoginPwdH;
            }
    
            private void CmdClearUser_Click(object sender, EventArgs e)
            {
                TxtUserID.Clear();
            }
    
            private void CmdClearPwd_Click(object sender, EventArgs e)
            {
                TxtUserPass.Clear();
            }
            private void SetLanguage(string tagLang)
            {
                try
                {
                    OINI oINI = new OINI(AppInfo.GetFile(AppInfo.AppFile.ConfigCore));
                    oINI.WriteString("Global", "CurrentLang", tagLang);
                    TstMILangLL.Checked = (tagLang == "LL");
                    TstMILangLI.Checked = !TstMILangLL.Checked;
                    GlbInfo.Language = tagLang;
                    InitObjectsText(this);
                }
                catch (Exception)
                {
                    throw;
                }
            }
            private void TstMILangLL_Click(object sender, EventArgs e)
            {
                SetLanguage("LL");
            }
    
            private void TstMILangLI_Click(object sender, EventArgs e)
            {
                SetLanguage("LI");
                
            }
    
            private void CmdLogin_Click(object sender, EventArgs e)
            {
                string tmpSts1 = MultiLang.Surface(this, "VeriUser", "正在验证用户...");
                SetMainStatus(tmpSts1);
    
                try
                {
                    string postUserID = TxtUserID.Text;
                    string postUserPass = TxtUserPass.Text;
                    if (string.IsNullOrEmpty(postUserID) || string.IsNullOrEmpty(postUserPass))
                    {
                        MyMsg.Information("T.201001/用户名和密码不能为空.");
                        TxtUserID.Focus();
                        return;
                    }
                    if ((SelAccountNO == "DEMOH") )
                    {
                        MyMsg.Warning("T.201002/此帐套尚未开放,请选择其它帐套.");
                        return;
                    }
    
                    if (SelAccountNO == "DEMO")
                    {
                        MyMsg.Warning("T.201003/您登录的是演示库,数据可能随时丢失,如需正式作业,请登录NORMAL正式库.");
                    }
                    string connStrCurAct = GetConnStrFromCfg(SelAccountNO, "ConnStr");
                    string connStrExt1 = GetConnStrFromCfg(SelAccountNO, "ConnStrExt1");
                    string connStrExt2 = GetConnStrFromCfg(SelAccountNO, "ConnStrExt2");
                    string connStrExt3 = GetConnStrFromCfg(SelAccountNO, "ConnStrExt3");
                    string connStrExt4 = GetConnStrFromCfg(SelAccountNO, "ConnStrExt4");
                    string connStrExt5 = GetConnStrFromCfg(SelAccountNO, "ConnStrExt5");
                    this.Cursor = Cursors.WaitCursor;
                    #region 用户ERP登录验证部分
                    DBContext dBContext = new DBContext(connStrCurAct);
                    if (!dBContext.IsConnected)
                    {
                        MyMsg.Error("T.1010/数据库连接已经创建,但无法开启!", dBContext.ConnectErrorMessage);
                        return;  
                    }
    
                    postUserPass = OCrypto.AES16Encrypt(postUserPass, DftAESKeyOfDlls);
                    SqlParameter[] paras = new SqlParameter[]
                    {
                                        new SqlParameter("@UserID", postUserID),
                                        new SqlParameter("@PasswordHash", postUserPass)
                    };
                    string sqlText= "SELECT     U.*, D.DeptCode, D.DeptNameLL, D.DeptNameLI FROM SYS_User AS U LEFT OUTER JOIN  Base_Department AS D ON U.DeptRKEY = D.DeptRKEY WHERE (U.UserID= @UserID) AND (U.PasswordHash= @PasswordHash)";
                    DataTable tmpDTUInfo = dBContext.SqlToDT(sqlText, paras);
                    if (tmpDTUInfo.Rows.Count > 0)
                    {
                        DataRow drUser = tmpDTUInfo.Rows[0];
                        if (!OString.NZ2Bool(drUser["IActived"]))
                        {
                            IsLogin = false;
                            SetMainStatus(MultiLang.Surface(this, "LoginFail1", "登录失败(帐号未激活),请联系管理员!"));
                        }
                        else if (OString.NZ2Bool(drUser["ILocked"]))
                        {
                            IsLogin = false;
                            SetMainStatus(MultiLang.Surface(this, "LoginFail2", "登录失败(帐号被锁定),请联系管理员!"));
                        }
                        else
                        {
                            GlbInfo.User.UserID = OString.NZ2Str(drUser["UserID"]);
                            GlbInfo.User.UserNameLL = OString.NZ2Str(drUser["UserNameLL"]);
                            GlbInfo.User.IsAdmin = OString.NZ2Bool(drUser["Hero"]);
                            GlbInfo.User.RolesUserIDS = OString.NZ2Str(drUser["RolesUserIDS"]);
                            GlbInfo.User.RightsList.Clear();
                            IsLogin = true;
                        }
                    }
                    else
                    {
                        IsLogin = false;
                        SetMainStatus(MultiLang.Surface(this, "LoginFail3", "登录失败(帐号不存在),请重新尝试!"));
                    }
    
                    if (IsLogin)
                    {
                        GlbInfo.ActNO = SelAccountNO;
                        GlbInfo.ActName = SelAccountName;
                        GlbInfo.ConnStrCurAct = connStrCurAct;
                        GlbInfo.ConnStrExt1 = connStrExt1;
                        GlbInfo.ConnStrExt2 = connStrExt2;
                        GlbInfo.ConnStrExt3 = connStrExt3;
                        GlbInfo.ConnStrExt4 = connStrExt4;
                        GlbInfo.ConnStrExt5 = connStrExt5;
                        fm20LoginTitle.Close();
                        if (ChkRemember.Checked)
                        {
                            try
                            {
                                //记录下登录用户,以便下次不必输入用户名
                                OINI oPIniFile = new OINI(AppInfo.GetFile(AppInfo.AppFile.ConfigCore));
                                oPIniFile.WriteString("Login", "LastUserID", postUserID);
                            }
                            catch (Exception)
                            {
                            }
                        }
    
                        DialogResult = DialogResult.OK;
                    }
                    else
                    {
                        TxtUserPass.Text = string.Empty;
                        TxtUserPass.Focus();
                        MyMsg.Warning("T.201004/用户名或密码错误,请检查.");
                    }
                    #endregion                
    
                }
                catch (Exception ex)
                {
                    SetMainStatus(tmpSts1 + "出现异常!");
                    MyMsg.Exclamation(ex.Message);
                }
                finally
                {
                    this.Cursor = Cursors.Default;
                }
            }
    
            /// <summary>
            /// 从配置文件中获取指定帐套数据库连接字符串(已加密)
            /// </summary>
            /// <param name="actNO">帐套代码</param>
            /// <param name="tKey">定义的连接串Key</param>
            /// <returns></returns>
            private string GetConnStrFromCfg(string actNO, string tKey)
            {
                try
                {
                    StringCollection Idents = new StringCollection();
                    OINI oINI = new OINI(AppInfo.GetFile(AppInfo.AppFile.ConfigCore));
                    return oINI.ReadString("Account:" + actNO, tKey, string.Empty);
                }
                catch (Exception ex)
                {
                    MyMsg.Error(ex.Message);
                    return string.Empty;
                }
            }
    
            private void LabChkRemember_DoubleClick(object sender, EventArgs e)
            {
                try
                {
                    //记录下登录用户,以便下次不必输入用户名
                    OINI oPIniFile = new OINI(AppInfo.GetFile(AppInfo.AppFile.ConfigCore));
                    oPIniFile.WriteString("Login", "LastUserID", string.Empty);
                    MyMsg.Information("已经清除登录历史,下次登录将不再显示当前帐号名称.");
                }
                catch (Exception)
                {
                }
            }
        }
    Login.cs

    登录界面是一个起点,涉及到文件操作以及数据库的连接/存取,下次再分解。

  • 相关阅读:
    C++11: reference_wrapper
    mac 查看目前哪些进程占用哪些端口
    Intellij IDEA 10.5 语言设置
    linux中的strip命令简介------给文件脱衣服
    HashMap的key可以是可变的对象吗???
    java BIO/NIO/AIO 学习
    java 反射
    Java线程同步
    maven modules
    设计模式在cocos2d-x中的使用--简单工厂模式(Simple Factory)
  • 原文地址:https://www.cnblogs.com/imes/p/9795191.html
Copyright © 2020-2023  润新知