winform+wcf搭建商戶管理系統(2)-用戶登錄界面設計


1.UI設計

winform不像Wpf那樣,可以通過各層的疊加,來實現各種炫酷的特效。在網上找了一個三方類庫,很好的解決了這個問題。

如圖,通過三方控件LayeredSkin.dll實現的一個類似於QQ的登錄界面

首先引用LaryeredSkin,然后新增一個Form窗體(這里命名為FormLogin),然后讓它繼承LayeredForm

public partial class FormLogin : LayeredForm

 

這里的樹葉和雲彩都能夠移動(通過Timer+GDI+實現)

        private void FormLogin_Load(object sender, EventArgs e)
        {
            yezi = new Bitmap(90, 80);//先把葉子畫在稍微大一點的畫布上,這樣葉子旋轉的時候才不會被裁掉一部分
            using (Graphics g = Graphics.FromImage(yezi))
            {
                g.DrawImage(Resources.yezi3, 10, 0);
            }
            timer1.Start();
            //讀取賬戶信息
            string result = AccountHelper.ReadAccount();
            if (string.IsNullOrEmpty(result) == false)
            {
                string[] temp = result.Split(',');
                if (temp != null && temp.Length == 2)
                {
                    txtAccount.Text = temp[0];
                    txtPassword.Text = temp[1];
                }
            }
        }
 protected override void OnLayeredPaint(LayeredSkin.LayeredEventArgs e)
        {
            Graphics g = e.Graphics;
            if (cloudX > this.Width - Cloud.Width)
            {//雲的飄動
                cloudX = 0;
            }
            else
            {
                cloudX += 0.5f;
            }
            g.DrawImage(Cloud, cloudX, 0);//把雲繪制上去

            if (angle > 10)
            {//控制旋轉方向
                RotationDirection = false;
            }
            if (angle < -10)
            {
                RotationDirection = true;
            }
            if (RotationDirection)
            {
                angle += 1;
            }
            else
            {
                angle -= 1;
            }
            using (Image temp = LayeredSkin.ImageEffects.RotateImage(yezi, angle, new Point(25, 3)))
            {
                g.DrawImage(temp, 140, 70);//繪制葉子
            }
            base.OnLayeredPaint(e);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            LayeredPaint();
            GC.Collect();
        }

加上窗體的移動事件,來實現窗體的拖動

        private void FormMoveMouseDown(object sender, MouseEventArgs e)
        {
            LayeredSkin.NativeMethods.MouseToMoveControl(this.Handle);
        }

 

到這里UI的設計就已經完成了

2.登錄和注冊邏輯

一般的登錄窗體都會有一個窗口的登錄和注冊邏輯(查詢和新增)

1.登錄邏輯

首先在客戶端進行初步的空值或者字符驗證

                if (string.IsNullOrEmpty(txtAccount.Text))
                {
                    layeredLabel5.Text = "用戶名不能為空!";
                    layeredLabel5.ForeColor = Color.Red;
                    txtAccount.Focus();
                    return;
                }
                if (string.IsNullOrEmpty(txtPassword.Text))
                {
                    layeredLabel5.Text = "密碼不能為空!";
                    layeredLabel5.ForeColor = Color.Red;
                    txtPassword.Focus();
                    return;
                }

然后這里調用服務端的賬號密碼驗證方法,來確定登錄是否正確,同時返回用戶信息,以供后面調用

 bool result = _client.TLoginCheckLogin(out message, out dto, txtAccount.Text, txtPassword.Text);

2.保存密碼

這里通過本地文本的讀寫來實現密碼的保存和自動填充功能

 //保存賬號信息
 if (cbRemind.Checked)
    AccountHelper.WriteAccount(txtAccount.Text, txtPassword.Text);

在用戶的加載事件中,已經貼出了自動讀取保存的用戶信息

3.用戶的注冊

這里分為員工信息和賬號信息兩類信息。(這兩類信息在服務端表現為一一對應關系)

    public class T_Login : Entity
    {
        private string _loginid;
        public string LoginId { get { return _loginid; } set { this.Id = value; this._loginid = value; } }  // LoginId (Primary key)

        public string LoginName { get; set; } // LoginName
        public string LoginPsw { get; set; } // LoginPsw
        public string Role { get; set; } // Role
        public string EmployeeId { get; set; } // EmployeeId
        public virtual T_Employee TEmployee { get; set; } // FK_T_Login_T_Employee  外鍵關系

    }

對於上節提到的DDD架構的業務邏輯而言,我們可以通過先增加外鍵表(員工信息表),再增加主鍵表(登錄信息表)來新增登錄信息。也可以應用架構本身的聚合根特性,來同時添加。第一種需要調用2次服務,第二種只需要在服務中傳兩個實體,然后聚合到主鍵實體,Commit就行了。

第一種方法

 private void btnRegist_Click(object sender, EventArgs e)
        {
            string message = string.Empty;
            if (!ConfirmNull(out message))
            {
                labelWarning.Text = message;
                labelWarning.ForeColor = Color.Red;
                return;
            }

            if ((bool)txtAccount.Tag == false)
            {
                TEmployeeDTO emp = new TEmployeeDTO();
                emp.EmployeeId = Guid.NewGuid().ToString();
                emp.EmployeeName = txtName.Text;
                emp.EmployeePhone = txtTel.Text;
                emp.EmployeeSex = coboSex.Text;
                emp.EntryData = dateTimePicker1.Value;
                emp.IdCard = txtIdCard.Text.Replace("-", "");
                emp.EmployeeAge = int.Parse(dmpAge.Text);
                emp.EntryImage = pictureStreamBox1.GetPictureStream();
                bool result = _client.TEmployeeAdd(emp);

                TLoginDTO login = new TLoginDTO();
                login.EmployeeId = emp.EmployeeId;
                login.LoginId = Guid.NewGuid().ToString();
                login.LoginName = txtAccount.Text;
                login.LoginPsw = txtPsw.Text;
                login.Role = coboRole.Text;
                result &= _client.TLoginAdd(login);
                if (result)
                {
                    labelWarning.ForeColor = Color.Green;
                    labelWarning.Text = "注冊成功!";
                    _account = login.LoginName + "," + login.LoginPsw;
                    Thread.Sleep(2000);
                    this.DialogResult = DialogResult.OK;
                }
                else
                {
                    labelWarning.Text = "注冊失敗!";
                    labelWarning.ForeColor = Color.Red;
                }
            }

第二種方法

        public bool Add(TLoginDTO dto,TEmployeeDTO employeeDTO)
        {
            try
            {
                var entity = dto.ProjectedAs<T_Login>();
                entity.TEmployee = employeeDTO.ProjectedAs<T_Employee>();
                if (_repository.Insert(entity) > 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

這里推薦使用第二種方法。效率高,同時不易產生臟數據

3.線程之間的關系

winform界面在程序入口Main函數中啟用登錄界面的時候,就將登錄界面設定為主線程。登錄成功之后,需要將登錄界面隱藏,顯示出我們需要的主界面。

所以,不能直接將登錄界面干掉(Close),不然,整個程序將完全關閉,相當於Application.Exit().

有兩種方法可以解決:1.關閉登錄界面之前,通過System.Diagnostics.Process.Start來啟動MainForm,然后關閉。2.將登錄界面Hide,在MainForm關閉的時候,將主線程關閉。

4.總結

Github源碼下載

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM