登录需求很常见,不管BS项目还是CS项目,你几乎都需要一个登录界面来开启你的项目。登录时通过查询验证数据库的用户名和密码,来判断是否登录成功。那么一个完整的登录过程需要有哪几步呢?
1,登录界面(Login):
两个Lable控件: 用户名 和 密码
对应两个Lable有用户名框和密码框两个TextBox控件: accountTextBox,passwordTextBox ,
三个Button控件:登录(loginBouttom),注册(registeredButton),关闭(closeBouttom)
Check控件:在密码框后面,是否显示密码(visibilityCheck)
2,注册界面(Registered)
三个Lable控件: 用户名 , 密码 和 重复密码
对应三个个Lable有用户名框和密码框三个TextBox控件: accountTextBox,passwordTextBox ,repeatPasswordTextBox
两个Button控件:注册(registeredButton),关闭(closeBouttom)
3,用到的工具类和静态类(前两个类我都专门写在一篇博客,这里就不上代码了)
XmlToolClass:XML工具类 保存琐细的数据,比如记录最后一次成功登录的账号,没必要因为存一个账号而在数据库新建一个表。
SqlHelpClass:简化对数据库的操作
LoginInfo:用户类,应用单件模式,保存用户登录状态
LoginInfo类代码:
/// <summary>
/// 用户类
/// </summary>
public class LoginInfo
{
//用户帐号,登录帐号
private string _Account = "";
public string Account { get { return _Account; } set { _Account = value; } }
//用户名
private string _PassWord = "";
public string PassWord { get { return _PassWord; } set { _PassWord = value; } }
//登录时间
private DateTime _LoginTime;
public DateTime LoginTime { get { return _LoginTime; } set { _LoginTime = value; } }
private static LoginInfo _CurrentUser = null;
//应用单件模式,保存用户登录状态
public static LoginInfo CurrentUser
{
get
{
if (_CurrentUser == null)
_CurrentUser = new LoginInfo();
return _CurrentUser;
}
}
}
View Code
4,注册
注册的话数据库需要一个表
create table usersTable
(
accout char(20) primary key,
password char(20) not null
)
账号是主键,不能重复,密码这里不为空就行,实际需要给个最小长度,这个最小长度不一定需要在数据库加check,也可以在注册的检测代码里校对。
5,登录
就是对数据库的查询
首先两个textbox上的数据是否符合==> 查询账号是否存在==>查询密码是否正确
登录成功后,需要把数据记录在LoginInfo里面,不然一点击登录这些数据就拿不到了。
接下来分别把各个步骤的代码上一遍
Login窗口是该实例的主窗口
Windows窗体文件(From窗口)类文件里尽量不要写太多关于逻辑控制和数据操作的代码,小练习MVC框架用不上,但是MVC的编程思想要有,即使是在做一个很小的程序。
public partial class login : Form
{
public bool IsClose { get; set; }
public login()
{
InitializeComponent();
AccoutTextBox.Text = XmlToolClass.GetLastTimeSuccessfulLoginAccount("账号");
PasswordTextBox.PasswordChar = '*';//设置显示*隐藏密码
IsClose = false;
//利用XmlToolClass从xml文件中获取最后一次成功登录的账号
}
private void registeredButton_Click_1(object sender, EventArgs e)
{
Registered registered = new Registered();
this.Hide();//隐藏当前窗口
registered.ShowDialog();//显示注册窗口
}
private void visibilityCheck_CheckedChanged(object sender, EventArgs e)
{
if (visibilityCheck.Checked)
{
PasswordTextBox.PasswordChar = new char();//设置密码可见
}
else
{
PasswordTextBox.PasswordChar = '*';//设置显示*隐藏密码
}
}
private void loginBoutton_Click(object sender, EventArgs e)
{
string strSqlAccout = "select count(*) from usersTable where accout='" + AccoutTextBox.Text.Trim() + "'";
string strSqlPassword = "select count(*) from usersTable where accout='" + AccoutTextBox.Text.Trim() +
"' and password='" + PasswordTextBox.Text + "'";
if (AccoutTextBox.Text == "" || PasswordTextBox.Text == "")
MessageBox.Show("账号和密码不能为空!", "登陆提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
else if (Convert.ToInt16( SqlHelpClass.ExecuteScalar(strSqlAccout)) <= 0)
//利用SqlHelpClass查询账号
MessageBox.Show("账号不存在!", "登陆提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
else if (Convert.ToInt16(SqlHelpClass.ExecuteScalar(strSqlPassword)) <= 0)
//利用SqlHelpClass验证密码
MessageBox.Show("密码错误!", "登陆提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
else
{
//LoginInfo为静态类,登陆成功后此静态类用于存储账号,用户名,登陆时间
LoginInfo.CurrentUser.Account = AccoutTextBox.Text;
LoginInfo.CurrentUser.PassWord = PasswordTextBox.Text;
LoginInfo.CurrentUser.LoginTime = DateTime.Now;
XmlToolClass.SetSuccessfulLoginAccount("账号", LoginInfo.CurrentUser.Account);//将账号写入xml
this.DialogResult = DialogResult.OK;
}
}
private void closeButton_Click(object sender, EventArgs e)
{
IsClose = true;
this.Close();
}
}
View Code
Registered窗口类
public partial class Registered : Form
{
public Registered()
{
InitializeComponent();
}
private void closButton_Click(object sender, EventArgs e)
{
this.Close();
}
private void registeredButton_Click(object sender, EventArgs e)
{
string strSqlAccout = "select count(*) from usersTable where accout='" + accountTextBox.Text.Trim() + "'";
if (accountTextBox.Text == "" || accountTextBox.Text == "")
MessageBox.Show("账号和密码不能为空!", "登陆提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
else if ( int.Parse(SqlHelpClass.ExecuteScalar(strSqlAccout).ToString()) > 0)
//利用SqlHelpClass查询账号
MessageBox.Show("账号已存在!", "登陆提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
else if (passwordTextBox.Text!=repeatPassword.Text)
//利用SqlHelpClass验证密码
MessageBox.Show("两次密码不相同!", "登陆提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
else
{
try
{
if (SqlHelpClass.AddData("usersTable", accountTextBox.Text, passwordTextBox.Text) > 0)
MessageBox.Show("注册成功");
else
MessageBox.Show("注册失败,请重新注册");
}
catch { }
}
}
}
最后就是测试,新建一个主页窗口(Home),模拟登陆成功后,跳转的窗口。
有两个Label控件,用来显示登陆时数据。
上面Login的代码到最后面登陆为什么不跳转窗口反而是来一段 this.DialogResult = DialogResult.OK;,有一些人看不懂。
如果以Login为主窗口的话,那么正常的操作应该是,先隐藏Login窗口个在实例化一个Home窗口,然后使得Home窗口可见。我们不能关闭Login,因为关闭主窗口,整个应用程序就直接退出了。
所以我们需要做一些改动,使得Login窗口变成在主窗口弹出前的一个判断性质的窗口——模式对话框。
模式对话框,当它弹出后,本应用程序其他窗口将不再接受用户输入,只有该对话框响应用户输入,在对它进行相应操作退出后,其他窗口才能继续与用户交互。
我们对Program类的main方法做些改变,main方法是应用程序的主入口点。
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
login login1;
do //模式窗口之间循环,直到密码正确
{
login1 = new login();//实例化Login
login1.ShowDialog();//将Login实例窗体显示为模式对话框
if (login1.IsClose)
break;
} while (!login1.DialogResult.Equals(DialogResult.OK));//登录成功才显示主窗体
if(login1.DialogResult.Equals(DialogResult.OK))
Application.Run(new Home());// Application.Run()方法运行主窗口
}
}
这里用到了一个do while循环,因为注册窗口也是模式对话框,对于两个模式对话框之间切换,我只能说能力有限。基于两个模式对话框相互操作和切换太难,只能重复关闭窗口,实例化窗口,来维持
登录界面与注册界面直至登录成功或者退出,因为do while 循环 所以只能添加一个IsClose布尔值属性来判断是否终止循环来退出。