功能演示视频 b展示视频: 数据库大作业—日常记账系统(C# winform + SQL Server) .
SQL代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 USE Application DROP TABLE IF EXISTS UserData; DROP TABLE IF EXISTs Account; CREATE TABLE UserData( ID NCHAR (10 ) PRIMARY KEY, UserPassword NCHAR (32 ), UserMail NCHAR (30 ), UserPhoto image, UserName NCHAR (30 ), ); CREATE TABLE Account( UserID NCHAR (10 ), InOrOut NCHAR (10 ), ConsumeType NCHAR (10 ), Price FLOAT , NOTE NCHAR (200 ), RecordDate DATE , ); INSERT INTO UserData(ID,UserPassword,UserMail,UserName) VALUES ('100001' ,' ' ,'wenwen@txw.com' ,'小田txw' );GO
SQL代码说明 创建了2个表:
UserData表
用于存储用户的信息,包括用户名、用户ID、用户密码、用户邮箱、用户头像。
Application表
用于存储用户的记账信息,包括用户ID、账单类型、金额、备注、时间。
自定义类 MailVeriCode
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Net.Mail;using System.Text;using System.Text.RegularExpressions;using System.Threading.Tasks;using System.Windows.Forms;namespace Database { public class MailVeriCode { public static string CreateRandomMailCode (int CodeLength ) { int randNum; char code; string randomCode = String.Empty; for (int i = 0 ; i < CodeLength; i++) { byte [] buffer = Guid.NewGuid().ToByteArray(); int seed = BitConverter.ToInt32(buffer, 0 ); Random random = new Random(seed); randNum = random.Next(); if (randNum % 3 == 1 ) { code = (char )('A' + (char )(randNum % 26 )); } else if (randNum % 3 == 2 ) { code = (char )('a' + (char )(randNum % 26 )); } else { code = (char )('0' + (char )(randNum % 10 )); } randomCode += code.ToString(); } return randomCode; } public static bool SendMailMessage (string MyEmailAddress, string RecEmailAddress, string Subject, string Body, string AuthorizationCode ) { MailMessage mail = new MailMessage(); mail.From = new MailAddress(MyEmailAddress); mail.To.Add(new MailAddress(RecEmailAddress)); mail.Subject = Subject; mail.Body = Body; mail.Priority = MailPriority.High; SmtpClient client = new SmtpClient(); client.Host = "smtp.qq.com" ; client.Port = 587 ; client.EnableSsl = true ; client.DeliveryMethod = SmtpDeliveryMethod.Network; client.Credentials = new NetworkCredential(MyEmailAddress, AuthorizationCode); try { client.Send(mail); } catch (Exception ex) { MessageBox.Show(ex.Message, "发送失败" , MessageBoxButtons.OK, MessageBoxIcon.Error); return false ; } return true ; } public static bool CheckMail (string mail ) { string str = @"^[1-9][0-9]{4,}@qq.com$" ; Regex mReg = new Regex(str); if (mReg.IsMatch(mail)) { return true ; } return false ; } } }
方法概述
CreateRandomMailCode
用于生成要发送的验证码,将验证码长度作为形参,返回字符串型的验证码。
SendMailMessage
用于发送邮件,使用了C#自带的类MailAddress
、SmtpClient
、NetworkCredential
等。收件人邮箱、发件人邮箱、发件人邮箱授权码、邮件内容、邮件标题作为形参,完成邮箱验证码的发送,完成发送后,返回true
的bool值,否则返回false
。
CheckMail
用于检测用户填入的邮箱验证码与发送的是否一致,返回bool类性值。
登录界面 界面展示
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Data.SqlClient;using System.Drawing;using System.Linq;using System.Security.Cryptography;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace Database { public partial class Login : Form { public string code; public Login () { InitializeComponent(); init (); } #region 初始化参数 private void init () { this .MaximizeBox = false ; title_lab.BackColor = Color.Transparent; account_lab.BackColor = Color.Transparent; password_lab.BackColor = Color.Transparent; vericode_lab.BackColor = Color.Transparent; veri_lab.BackColor= Color.Transparent; login_btn.FlatStyle = FlatStyle.Flat; login_btn.ForeColor = Color.Transparent; login_btn.BackColor = Color.Transparent; login_btn.FlatAppearance.BorderSize = 1 ; login_btn.FlatAppearance.MouseOverBackColor = Color.Transparent; login_btn.FlatAppearance.MouseDownBackColor = Color.Transparent; register_btn.FlatStyle = FlatStyle.Flat; register_btn.ForeColor = Color.Transparent; register_btn.BackColor = Color.Transparent; register_btn.FlatAppearance.BorderSize = 1 ; register_btn.FlatAppearance.MouseOverBackColor = Color.Transparent; register_btn.FlatAppearance.MouseDownBackColor = Color.Transparent; forget_linkbtn.FlatStyle = FlatStyle.Flat; forget_linkbtn.ForeColor = Color.Transparent; forget_linkbtn.BackColor = Color.Transparent; checkBox1.BackColor = Color.Transparent; CreatVeriCode(); } #endregion #region 生成随机验证码 private void CreatVeriCode () { code = "" ; Random ran = new Random(); int number; char code1; for (int i = 0 ; i < 5 ; i++) { number = ran.Next(); if (number % 2 == 0 ) code1 = (char )('0' + (char )(number % 10 )); else code1 = (char )('A' + (char )(number % 26 )); this .code += code1.ToString(); } vericode_lab.Text = code; } #endregion #region 登录按钮事件(连接数据库验证用户名和密码) private void login_btn_Click (object sender, EventArgs e ) { string username = account_txt.Text.Trim(); string password = EncryptWithMD5(password_txt.Text.Trim()); string sqlconf = "Data Source = .;Initial Catalog = Application;Integrated Security = SSPI" ; SqlConnection sqlConnection = new SqlConnection(sqlconf); sqlConnection.Open(); string sql = "select ID,UserPassword from UserData where UserName = '" + username + "'and UserPassword = '" + password + "'" ; SqlCommand cmd = new SqlCommand(sql, sqlConnection); SqlDataReader reader = cmd.ExecuteReader(); if (reader.HasRows && vericode_txt.Text.ToLower() == code.ToLower()) { new Main(username).Show(); this .Hide(); } else if (reader.HasRows && vericode_txt.Text.ToLower()!=code.ToLower()) { MessageBox.Show("验证码有误,登录失败!" ,"警告" ); CreatVeriCode(); return ; } else { MessageBox.Show("账号密码有误,登录失败!" , "警告" ); return ; } reader.Close(); sqlConnection.Close(); } #endregion #region 注册界面 private void register_btn_Click (object sender, EventArgs e ) { new Register().Show(); } #endregion #region MD5加密算法 private string EncryptWithMD5 (string source ) { byte [] sor = Encoding.UTF8.GetBytes(source); MD5 md5 = MD5.Create(); byte [] result = md5.ComputeHash(sor); StringBuilder strbul = new StringBuilder(40 ); for (int i = 0 ; i < result.Length; i++) { strbul.Append(result[i].ToString("x2" )); } return strbul.ToString(); } #endregion #region 点击验证码标签刷新验证码 private void vericode_lab_Click (object sender, EventArgs e ) { CreatVeriCode(); } #endregion private void forget_linkbtn_LinkClicked (object sender, LinkLabelLinkClickedEventArgs e ) { new Forget().Show(); } private void checkBox1_CheckedChanged (object sender, EventArgs e ) { if (checkBox1.Checked) { password_txt.PasswordChar = new char (); } else { password_txt.PasswordChar = '*' ; } } } }
方法概述 主要方法:init
、CreatVeriCode
、login_btn_Click
、register_btn_Click
、EncryptWithMD5
、vericode_lab_Click
、forget_linkbtn_LinkClicked
、checkBox1_CheckedChanged
其中
init
:初始化方法,初始化界面和生成初始的验证码。
CreatVeriCode
:验证码生成方法。
login_btn_Click
:点击登录按钮事件,具体的事件后面描述。
register_btn_Click
:点击注册按钮事件,调出注册界面。
EncryptWithMD5
:MD5加密算法方法,实际的密码经过该方法后,返回经MD5加密的密码。
vericode_lab_Click
:点击验证码标签事件,点击验证码标签后,会刷新验证码。
forget_linkbtn_LinkClicked
:点击忘记密码事件,调出找回密码界面。
checkBox1_CheckedChanged
:复选框改变事件,用于改变密码文本框的显示(显示密码和隐藏密码)。
主要控件及具体事件说明
“登录”按钮
按下“登录”按钮后,程序会与Application数据库连接,根据输入的用户名和密码,从UserData表中查询相应的数据,若存在用户名且密码正确,则会验证输入的验证码是否正确,若正确,则调出主界面。
总结说明 登录界面的主要功能:
有调出注册界面和找回密码界面按钮;
登录时连接数据库,验证账号和密码的有效性,完成登录;
为让用户确认密码,附加显示密码复选框,用户可勾选复选框显示具体密码,也可取消勾选隐藏密码。
登录界面较为简单,要实现的功能不多,主要就是为了调出其他界面。
注册界面 界面展示
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Data.SqlClient;using System.Drawing;using System.IO;using System.Linq;using System.Security.Cryptography;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms;namespace Database { public partial class Register : Form { public static string pathPicture; public Byte[] mybyte = new byte [0 ]; public Register () { InitializeComponent(); init (); } #region 参数初始化 private void init () { this .MaximizeBox = false ; mail_lab.BackColor = Color.Transparent; passwordreg_lab.BackColor = Color.Transparent; vericode_lab.BackColor = Color.Transparent; register_lab.BackColor = Color.Transparent; username_lab.BackColor = Color.Transparent; pic_lab.BackColor = Color.Transparent; Mail_btn.FlatStyle = FlatStyle.Flat; Mail_btn.ForeColor = Color.Transparent; Mail_btn.BackColor = Color.Transparent; Mail_btn.FlatAppearance.BorderSize = 1 ; Mail_btn.FlatAppearance.MouseOverBackColor = Color.Transparent; Mail_btn.FlatAppearance.MouseDownBackColor = Color.Transparent; register_btn.FlatStyle = FlatStyle.Flat; register_btn.ForeColor = Color.Transparent; register_btn.BackColor = Color.Transparent; register_btn.FlatAppearance.BorderSize = 1 ; register_btn.FlatAppearance.MouseOverBackColor = Color.Transparent; register_btn.FlatAppearance.MouseDownBackColor = Color.Transparent; pictureBox1.BackColor = Color.Transparent; checkBox1.BackColor = Color.Transparent; } #endregion #region 获取邮箱验证码(MailMessage类和SmtpClient类) int seconds1 = 60 ; int seconds2 = 60 * 5 ; string strMailVeriCode; private void Mail_btn_Click (object sender, EventArgs e ) { string recEMailAddress = Mail_txt.Text.Trim(); strMailVeriCode = MailVeriCode.CreateRandomMailCode(6 ); string strBody = "验证码:" + strMailVeriCode + ",5分钟内有效,请勿泄漏于他人。如非本人操作,请忽略。系统邮件请勿回复。" ; string strSubject = "【小田账本】注册验证" ; string strMyEmailAddress = "xxxxxxxxx@qq.com" ; string strAuthorizationCode = "xxxxxxxxxxxx" ; if (string .IsNullOrEmpty(recEMailAddress)) { MessageBox.Show("请输入邮箱!" , "提示" , MessageBoxButtons.OK, MessageBoxIcon.Information); Mail_txt.Focus(); } else if (MailVeriCode.CheckMail(recEMailAddress) == false ) { MessageBox.Show("您输入的QQ邮箱有误,请重新输入!" , "警告" , MessageBoxButtons.OK, MessageBoxIcon.Exclamation); Mail_txt.Focus(); return ; } else { if (MailVeriCode.SendMailMessage(strMyEmailAddress, recEMailAddress, strSubject, strBody, strAuthorizationCode) == true ) { Mail_btn.Enabled = false ; timer1.Interval = 1000 ; timer1.Start(); timer2.Interval = 1000 ; timer2.Start(); } else { vericode_txt.Focus(); } } } #endregion #region 倒计时1方法 private void timer1_Tick (object sender, EventArgs e ) { if (seconds1 > 0 ) { seconds1--; Mail_btn.Text = "剩余" + seconds1.ToString() + "秒" ; } else { timer1.Stop(); Mail_btn.Text = "获取验证码" ; Mail_btn.Enabled = true ; } } #endregion #region 倒计时2方法 private void timer2_Tick (object sender, EventArgs e ) { if (seconds2 == 0 ) { timer2.Stop(); strMailVeriCode = MailVeriCode.CreateRandomMailCode(6 ); } } #endregion #region 注册按钮事件 private void register_btn_Click (object sender, EventArgs e ) { string mailVeriCode = vericode_txt.Text.Trim(); if (username_txt.Text.Trim() != "" && passwordreg_txt.Text.Trim() != "" ) { if (pathPicture==null ) { MessageBox.Show("请选择头像!" ); return ; } else { string sqlconf = "Data Source = .;Initial Catalog = Application;Integrated Security = SSPI" ; SqlConnection sqlConnection = new SqlConnection(sqlconf); string username = username_txt.Text.Trim(); string mail = Mail_txt.Text.Trim(); sqlConnection.Open(); string sql1 = "select UserName from UserData where UserName = '" + username + "'" ; SqlCommand sqlCommand1 = new SqlCommand(sql1, sqlConnection); SqlDataReader sqlDataReader1 = sqlCommand1.ExecuteReader(); bool a = sqlDataReader1.HasRows; sqlDataReader1.Close(); if (a) { MessageBox.Show("用户名已注册!" ); return ; } else { string sql2 = "select UserName from UserData where UserMail = '" + mail + "'" ; SqlCommand sqlCommand2 = new SqlCommand(sql2, sqlConnection); SqlDataReader sqlDataReader2 = sqlCommand2.ExecuteReader(); bool b = sqlDataReader2.HasRows; sqlDataReader2.Close(); if (b) { MessageBox.Show("该邮箱已注册!" ); return ; } else { if (string .IsNullOrEmpty(mailVeriCode) == true ) { MessageBox.Show("请输入验证码" , "提示" , MessageBoxButtons.OK, MessageBoxIcon.Information); vericode_txt.Focus(); return ; } else if (mailVeriCode.ToLower() != strMailVeriCode.ToLower()) { MessageBox.Show("您输入的验证码有误!" , "警告" , MessageBoxButtons.OK, MessageBoxIcon.Exclamation); vericode_txt.Focus(); return ; } string sql4 = "select max(ID) as maxid from UserData" ; SqlCommand command1 = new SqlCommand(sql4, sqlConnection); SqlDataReader maxid = command1.ExecuteReader(); maxid.Read(); int newid = Convert.ToInt32(maxid["maxid" ]) + 1 ; maxid.Close(); string password = EncryptWithMD5(passwordreg_txt.Text.Trim()); string sql3 = "insert into UserData(ID,UserPassword,UserMail,UserName,UserPhoto)" + "values (@userid, @userpassword,@usermail,@username,@userphoto)" ; SqlCommand command = new SqlCommand(sql3, sqlConnection); SqlParameter sqlParameter = new SqlParameter("@userid" , newid); command.Parameters.Add(sqlParameter); sqlParameter = new SqlParameter("@userpassword" , password); command.Parameters.Add(sqlParameter); sqlParameter = new SqlParameter("@usermail" , Mail_txt.Text); command.Parameters.Add(sqlParameter); sqlParameter = new SqlParameter("@username" , username_txt.Text); command.Parameters.Add(sqlParameter); sqlParameter = new SqlParameter("@userphoto" , System.Data.SqlDbType.Image); sqlParameter.Value = mybyte; command.Parameters.Add(sqlParameter); command.ExecuteNonQuery(); sqlConnection.Close(); MessageBox.Show("注册成功!" ); this .Close(); } } } } else { MessageBox.Show("请先将信息填写完整!" ); } } #endregion #region MD5加密算法 private string EncryptWithMD5 (string source ) { byte [] sor = Encoding.UTF8.GetBytes(source); MD5 md5 = MD5.Create(); byte [] result = md5.ComputeHash(sor); StringBuilder strbul = new StringBuilder(40 ); for (int i = 0 ; i < result.Length; i++) { strbul.Append(result[i].ToString("x2" )); } return strbul.ToString(); } #endregion #region 添加头像 private void pictureBox1_Click (object sender, EventArgs e ) { this .openFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); this .openFileDialog1.Filter = "bmp文件(*.bmp)*.bmpgif文件(*.gif)*.gifjpeg文件(*.jpg)*.jpgpng文件(*.png)*.png" ; this .openFileDialog1.FilterIndex = 3 ; this .openFileDialog1.RestoreDirectory = true ; this .openFileDialog1.Title = "选择头像照片" ; if (this .openFileDialog1.ShowDialog() == DialogResult.OK) { pathPicture = this .openFileDialog1.FileName; FileStream fs = new FileStream(pathPicture, FileMode.Open, FileAccess.Read); mybyte = new byte [fs.Length]; fs.Read(mybyte, 0 , mybyte.Length); pictureBox1.Image = Image.FromStream(fs); pictureBox1.BringToFront(); fs.Close(); } } #endregion #region 显示/隐藏密码 private void checkBox1_CheckedChanged (object sender, EventArgs e ) { if (checkBox1.Checked) { passwordreg_txt.PasswordChar = new char (); } else { passwordreg_txt.PasswordChar = '*' ; } } #endregion } }
方法概述 主要方法:init
、Mail_btn_Click
、timer1_Tick
、timer2_Tick
、register_btn_Click
、EncryptWithMD5
、pictureBox1_Click
、checkBox1_CheckedChanged
其中
init
:初始化方法,初始化界面。
Mail_btn_Click
:获取验证码按钮事件,用于获取邮箱验证码。
timer1_Tick
:计时器1计时事件,用于将计时器1的时间显示在“获取验证码”上,提示用户还有多久才能再次获取验证码。
timer2_Tick
:时间2计时事件,用于计时已发送验证码的有效时间。
register_btn_Click
:点击“注册”按钮的事件,具体的事件后面描述。
EncryptWithMD5
:MD5加密算法方法,实际的密码经过该方法后,返回经MD5加密的密码。
pictureBox1_Click
:点击图片框触发的事件,打开本地文件对话框,选择要上传的头像图片。
checkBox1_CheckedChanged
:复选框改变事件,用于改变密码文本框的显示(显示密码和隐藏密码)。
主要控件及具体事件说明
图片框pictureBox1
用于触发打开文件对话框,选择要上传的新头像。
“获取验证码”按钮Mail_btn
这里主要使用了自定义类MailVeriCode,详细方法上面已给出。只需要向MailVeriCode的SendMailMessage方法里传参:收件人邮箱、发件人邮箱、发件人邮箱授权码、邮件内容、邮件标题,即可完成发送。但在此之前,也需要用MailVeriCode类中的CheckMail方法检验收件人邮箱的有效性(只支持发送qq邮箱)。
同时,打开两计时器的计时,一个作为获取新验证码的时间放在“获取验证码”按钮上,另一个作为验证码的有效性计时。
“注册”按钮register_btn
这里主要是判断用户所有输入信息的正确性,包括用户名是否已被注册、邮箱是否已被注册、头像是否已上传、邮箱验证码是否正确。通过连接Application数据库,查询UserData表,若用户名和邮箱均未被注册、头像已上传,且邮箱验证码正确,则将用户名、用户邮箱、新生成的ID、用户密码以及邮箱插入UserData表中,完成用户的注册。
总结说明 注册界面的主要功能:
获取邮箱验证码;
创建邮箱和用户名未被注册的用户,其中创建用户需要上传到数据库的数据包括用户id、用户名、用户邮箱、用户密码(经MD5加密后)、用户头像;
为让用户确认密码,附加显示密码复选框,用户可勾选复选框显示具体密码,也可取消勾选隐藏密码。
注册界面的较登录界面复杂一些,登录界面主要是对数据库进行查询操作,而注册界面要完成数据库的查询、插入操作。除此之外,还要完成邮箱验证码的发送和规定有效时间。
找回密码界面 界面展示
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Data.SqlClient;using System.Drawing;using System.Linq;using System.Security.Cryptography;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace Database { public partial class Forget : Form { public Forget () { InitializeComponent(); init (); } #region 参数初始化 private void init () { this .MaximizeBox = false ; forget_lab.BackColor = Color.Transparent; mail_lab.BackColor = Color.Transparent; password_lab.BackColor = Color.Transparent; vericode_lab.BackColor = Color.Transparent; mail_btn.FlatStyle = FlatStyle.Flat; mail_btn.ForeColor = Color.Transparent; mail_btn.BackColor = Color.Transparent; mail_btn.FlatAppearance.BorderSize = 1 ; mail_btn.FlatAppearance.MouseOverBackColor = Color.Transparent; mail_btn.FlatAppearance.MouseDownBackColor = Color.Transparent; showpw_btn.BackColor = Color.Transparent; } #endregion #region 获取验证码按钮事件 int seconds1 = 60 ; int seconds2 = 60 * 5 ; string strMailVeriCode; private void mail_btn_Click (object sender, EventArgs e ) { string recEMailAddress = mail_txt.Text.Trim(); if (!mail_exist(recEMailAddress)) { MessageBox.Show("邮箱未注册!" ); return ; } strMailVeriCode = MailVeriCode.CreateRandomMailCode(6 ); string strBody = "验证码:" + strMailVeriCode + ",5分钟内有效,请勿泄漏于他人。如非本人操作,请忽略。系统邮件请勿回复。" ; string strSubject = "【小田账本】找回密码" ; string strMyEmailAddress = "xxxxxxxxxx@qq.com" ; string strAuthorizationCode = "xxxxxxxxxxxx" ; if (string .IsNullOrEmpty(recEMailAddress)) { MessageBox.Show("请输入邮箱!" , "提示" , MessageBoxButtons.OK, MessageBoxIcon.Information); mail_txt.Focus(); } else if (MailVeriCode.CheckMail(recEMailAddress) == false ) { MessageBox.Show("您输入的QQ邮箱有误,请重新输入!" , "警告" , MessageBoxButtons.OK, MessageBoxIcon.Exclamation); mail_txt.Focus(); return ; } else { if (MailVeriCode.SendMailMessage(strMyEmailAddress, recEMailAddress, strSubject, strBody, strAuthorizationCode) == true ) { mail_btn.Enabled = false ; timer1.Interval = 1000 ; timer1.Start(); timer2.Interval = 1000 ; timer2.Start(); } else { vericode_txt.Focus(); } } } #endregion #region 时钟1计时事件 private void timer1_Tick (object sender, EventArgs e ) { if (seconds1 > 0 ) { seconds1--; mail_btn.Text = "剩余" + seconds1.ToString() + "秒" ; } else { timer1.Stop(); mail_btn.Text = "获取验证码" ; mail_btn.Enabled = true ; } } #endregion #region 时钟2计时事件 private void timer2_Tick (object sender, EventArgs e ) { if (seconds2 == 0 ) { timer2.Stop(); strMailVeriCode = MailVeriCode.CreateRandomMailCode(6 ); } } #endregion #region 查找邮箱存在性 private bool mail_exist (string mail ) { string sqlconf = "Data Source = .;Initial Catalog = Application;Integrated Security = SSPI" ; SqlConnection sqlConnection = new SqlConnection(sqlconf); sqlConnection.Open(); string sql1 = "select UserMail from UserData where UserMail = '" + mail + "'" ; SqlCommand sqlCommand1 = new SqlCommand(sql1, sqlConnection); SqlDataReader sqlDataReader = sqlCommand1.ExecuteReader(); bool a = sqlDataReader.HasRows; sqlDataReader.Close(); sqlConnection.Close(); if (a) { return true ; } else { return false ; } } #endregion #region 找回密码确认按钮事件 private void confirm_btn_Click (object sender, EventArgs e ) { string mailVeriCode = vericode_txt.Text.Trim(); if (mail_txt.Text.Trim() != "" && password_txt.Text.Trim() != "" ) { string mail = mail_txt.Text.Trim(); if (!mail_exist(mail)) { MessageBox.Show("邮箱未注册!" ); return ; } if (string .IsNullOrEmpty(mailVeriCode) == true ) { MessageBox.Show("请输入验证码" , "提示" , MessageBoxButtons.OK, MessageBoxIcon.Information); vericode_txt.Focus(); return ; } else if (mailVeriCode.ToLower() != strMailVeriCode.ToLower()) { MessageBox.Show("您输入的验证码有误!" , "警告" , MessageBoxButtons.OK, MessageBoxIcon.Exclamation); vericode_txt.Focus(); return ; } string sqlconf = "Data Source = .;Initial Catalog = Application;Integrated Security = SSPI" ; SqlConnection sqlConnection = new SqlConnection(sqlconf); string password = EncryptWithMD5(password_txt.Text.Trim()); sqlConnection.Open(); string sqlStr = "update UserData Set UserPassword = '" + password + "'where UserMail = '" + mail +"'" ; SqlCommand cmd = new SqlCommand(sqlStr, sqlConnection); cmd.ExecuteNonQuery(); MessageBox.Show("修改密码成功!" ); sqlConnection.Close(); this .Close(); } else if (mail_txt.Text.Trim() == "" && password_txt.Text.Trim() != "" ) { MessageBox.Show("请填写邮箱!" ,"提示" ); mail_txt.Focus(); } else if (mail_txt.Text.Trim() != "" && password_txt.Text.Trim() == "" ) { MessageBox.Show("请填写新密码!" , "提示" ); password_txt.Focus(); } else { MessageBox.Show("请完善相关信息!" , "提示" ); mail_txt.Focus(); } } #endregion #region MD5加密算法 private string EncryptWithMD5 (string source ) { byte [] sor = Encoding.UTF8.GetBytes(source); MD5 md5 = MD5.Create(); byte [] result = md5.ComputeHash(sor); StringBuilder strbul = new StringBuilder(40 ); for (int i = 0 ; i < result.Length; i++) { strbul.Append(result[i].ToString("x2" )); } return strbul.ToString(); } #endregion #region 显示/隐藏密码 private void showpw_btn_CheckedChanged (object sender, EventArgs e ) { if (showpw_btn.Checked) { password_txt.PasswordChar = new char (); } else { password_txt.PasswordChar = '*' ; } } #endregion } }
方法概述 主要方法:init
、mail_btn_Click
、timer1_Tick
、timer2_Tick
、confirm_btn_Click
、EncryptWithMD5
、showpw_btn_CheckedChanged
、mail_exist
其中
init
:初始化方法,初始化界面。
mail_btn_Click
:获取验证码按钮事件,用于获取邮箱验证码。
timer1_Tick
:计时器1计时事件,用于将计时器1的时间显示在“获取验证码”上,提示用户还有多久才能再次获取验证码。
timer2_Tick
:时间2计时事件,用于计时已发送验证码的有效时间。
confirm_btn_Click
:点击“确认”按钮的事件,具体的事件后面描述。
EncryptWithMD5
:MD5加密算法方法,实际的密码经过该方法后,返回经MD5加密的密码。
showpw_btn_CheckedChanged
:复选框改变事件,用于改变密码文本框的显示(显示密码和隐藏密码)。
mail_exist
:连接数据库,查询账户邮箱的存在性。
主要控件及具体事件说明
“获取验证码”按钮mail_btn
这里就不再赘述了,和注册界面的“获取验证码”按钮出发的事件完全一样,就是将邮件的标题改为“找回密码”。
“确认”按钮confirm_btn
首先,连接Application数据库通过UserData表确认邮箱是否已注册,若已注册,则检查输入验证码的正确性,若上述信息均正确,则将输入的新密码更新到UserData表中相应邮箱的用户密码。
总结说明 找回界面的主要功能:
获取邮箱验证码;
通过验证账户邮箱的存在性和验证码的正确性,连接数据库进行用户密码更新操作。
找回密码的实现和注册账户差不多,可以说大部分代码可以直接从注册界面照搬,唯一的区别在于,找回密码需要的数据交互更少,不需要向数据库表插入数据,只需要查询数据和更新数据。
主界面 界面展示
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Data.SqlClient;using System.Drawing;using System.IO;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace Database { public partial class Main : Form { private static float inmoney; private static float outmoney; public static string pathPicture; static string userid; static string username; static string usermail; static string password; public Main () { InitializeComponent(); } #region 有参构造窗体初始化 public Main (string Username ) { InitializeComponent(); init (Username); } #endregion #region 初始化参数和导入数据库数据 public void init (string Username ) { inmoney = 0 ; outmoney = 0 ; this .MaximizeBox = false ; string sqlconf = "Data Source = .;Initial Catalog = Application;Integrated Security = SSPI" ; SqlConnection sqlConnection = new SqlConnection(sqlconf); sqlConnection.Open(); string sqlStr = "select *from UserData where UserName = '" + Username + "'" ; SqlCommand cmd = new SqlCommand(sqlStr, sqlConnection); SqlDataReader sqlDataReader = cmd.ExecuteReader(); if (sqlDataReader.Read()) { usermail = sqlDataReader["UserMail" ].ToString().Trim(); userid = sqlDataReader["ID" ].ToString(); username = Username; password = sqlDataReader["UserPassword" ].ToString(); } sqlDataReader.Close(); id_lab.Text = userid; username_lab.Text = username; mail_lab.Text = usermail; sqlStr = "select UserPhoto from UserData where UserName = '" + Username + "'" ; cmd = new SqlCommand(sqlStr, sqlConnection); SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(cmd); DataSet ds = new DataSet(); sqlDataAdapter.Fill(ds, "UserData" ); int c = ds.Tables["UserData" ].Rows.Count; if (c > 0 ) { Byte[] mybyte = new byte [0 ]; mybyte = (Byte[])(ds.Tables["UserData" ].Rows[c - 1 ]["UserPhoto" ]); MemoryStream ms = new MemoryStream(mybyte); pictureBox1.Image = Image.FromStream(ms); } else pictureBox1.Image = null ; sqlStr = "select *from Account where UserID = '" + Main.userid + "'" ; cmd = new SqlCommand(sqlStr, sqlConnection); sqlDataReader = cmd.ExecuteReader(); while (sqlDataReader.Read()) { string inorout_tmp = sqlDataReader["InOrOut" ].ToString().Trim(); string conType_tmp = sqlDataReader["ConsumeType" ].ToString(); float price_tmp = (float )Convert.ToDouble(sqlDataReader["Price" ]); string note_tmp = sqlDataReader["NOTE" ].ToString(); string time_tmp = Convert.ToDateTime(sqlDataReader["RecordDate" ]).Date.ToString("D" ); if (inorout_tmp.Equals("收入" )) { income_list.Items.Add(conType_tmp + "\t" + price_tmp.ToString() + "元\t" + time_tmp + "\t" + note_tmp); innum_lab.Text = income_list.Items.Count.ToString(); inmoney = inmoney + price_tmp; inmoney_lab.Text = Convert.ToString(inmoney); } else { expend_list.Items.Add(conType_tmp + "\t" + price_tmp.ToString() + "元\t" + time_tmp + "\t" + note_tmp); outnum_lab.Text = expend_list.Items.Count.ToString(); outmoney = outmoney + price_tmp; outmoney_lab.Text = Convert.ToString(outmoney); } } sqlConnection.Close(); } #endregion #region 收入单选按钮事件 private void income_btn_CheckedChanged (object sender, EventArgs e ) { matter_box.Items.Clear(); matter_box.Items.Add("工资" ); matter_box.Items.Add("理财" ); matter_box.Items.Add("礼金" ); matter_box.Items.Add("其他" ); matter_box.Text = "" ; } #endregion #region 支出单选按钮事件 private void expend_btn_CheckedChanged (object sender, EventArgs e ) { matter_box.Items.Clear(); matter_box.Items.Add("餐饮" ); matter_box.Items.Add("购物" ); matter_box.Items.Add("交通" ); matter_box.Items.Add("娱乐" ); matter_box.Items.Add("医疗" ); matter_box.Items.Add("彩票" ); matter_box.Items.Add("旅行" ); matter_box.Items.Add("运动" ); matter_box.Items.Add("通讯" ); matter_box.Items.Add("社交" ); matter_box.Items.Add("学习" ); matter_box.Items.Add("其他" ); matter_box.Text = "" ; } #endregion #region 记录按钮事件 private void record_btn_Click (object sender, EventArgs e ) { string sqlconf = "Data Source = .;Initial Catalog = Application;Integrated Security = SSPI" ; SqlConnection sqlConnection = new SqlConnection(sqlconf); string inorout; if (income_btn.Checked == true ) { income_list.Items.Add(matter_box.Text+"\t" +money_txt.Text+"元\t" + dateTimePicker1.Text+"\t" +note_txt.Text); innum_lab.Text = income_list.Items.Count.ToString(); inmoney = inmoney + float .Parse(money_txt.Text); inmoney_lab.Text = Convert.ToString(inmoney); inorout = "收入" ; } else { expend_list.Items.Add(matter_box.Text + "\t" + money_txt.Text + "元\t" + dateTimePicker1.Text + "\t" + note_txt.Text); outnum_lab.Text = expend_list.Items.Count.ToString(); outmoney_lab.Text = Convert.ToString(float .Parse(outmoney_lab.Text) + float .Parse(money_txt.Text)); inorout = "支出" ; } string consumeType = matter_box.Text; string note = note_txt.Text; float price = float .Parse(money_txt.Text.Trim()); string time = dateTimePicker1.Text; sqlConnection.Open(); string insertStr = "insert into Account(UserID,InOrOut,ConsumeType,NOTE,Price,RecordDate)" + "values('" + userid + "','" + inorout + "','" + consumeType + "','" + note + "','" + price + "','" + Convert.ToDateTime(time) + "')" ; SqlCommand cmd = new SqlCommand(insertStr, sqlConnection); cmd.ExecuteNonQuery(); sqlConnection.Close(); } #endregion #region 点击头像事件(修改头像) private void pictureBox1_Click (object sender, EventArgs e ) { this .openFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); this .openFileDialog1.Filter = "bmp文件(*.bmp)*.bmpgif文件(*.gif)*.gifjpeg文件(*.jpg)*.jpgpng文件(*.png)*.png" ; this .openFileDialog1.FilterIndex = 3 ; this .openFileDialog1.RestoreDirectory = true ; this .openFileDialog1.Title = "选择头像照片" ; if (this .openFileDialog1.ShowDialog() == DialogResult.OK) { Byte[] picbyte = new byte [0 ]; pathPicture = this .openFileDialog1.FileName; FileStream fs = new FileStream(pathPicture, FileMode.Open, FileAccess.Read); picbyte = new byte [fs.Length]; fs.Read(picbyte, 0 , picbyte.Length); pictureBox1.Image = Image.FromStream(fs); fs.Close(); string sqlconf = "Data Source = .;Initial Catalog = Application;Integrated Security = SSPI" ; SqlConnection sqlConnection = new SqlConnection(sqlconf); string userid = id_lab.Text.Trim(); sqlConnection.Open(); string sqlStr = "delete from UserData where ID = '" +userid+ "'" ; SqlCommand sqlCommand = new SqlCommand(sqlStr,sqlConnection); sqlCommand.ExecuteNonQuery(); sqlStr = "insert into UserData(ID,UserPassword,UserMail,UserName,UserPhoto)" + "values (@userid, @userpassword,@usermail,@username,@userphoto)" ; SqlCommand command = new SqlCommand(sqlStr, sqlConnection); SqlParameter sqlParameter = new SqlParameter("@userid" , userid); command.Parameters.Add(sqlParameter); sqlParameter = new SqlParameter("@userpassword" , password); command.Parameters.Add(sqlParameter); sqlParameter = new SqlParameter("@usermail" , usermail); command.Parameters.Add(sqlParameter); sqlParameter = new SqlParameter("@username" , username); command.Parameters.Add(sqlParameter); sqlParameter = new SqlParameter("@userphoto" , System.Data.SqlDbType.Image); sqlParameter.Value = picbyte; command.Parameters.Add(sqlParameter); command.ExecuteNonQuery(); sqlConnection.Close(); MessageBox.Show("更改头像成功!" ); } } #endregion #region 关闭窗口事件 private void Main_FormClosed (object sender, FormClosedEventArgs e ) { System.Environment.Exit(0 ); } #endregion } }
方法概述 主要方法:
init
、income_btn_CheckedChanged
、expend_btn_CheckedChanged
、record_btn_Click
、pictureBox1_Click
、Main_FormClosed
其中
init
:初始化方法,初始化界面,以及将用户数据从数据库导入。
income_btn_CheckedChanged
和expend_btn_CheckedChanged
:单选框选择改变事件,用于更新下拉栏的内容。
record_btn_Click
:“记录”按钮事件,具体的事件后面描述。
pictureBox1_Click
:点击图片框触发的事件,打开本地文件对话框,选择要上传的头像图片,用于更改头像。
Main_FormClosed
:窗口关闭事件,当窗口关闭后,使所有程序结束运行。
主要控件及具体事件说明
“记录按钮record_btn”
当点击”记录按钮后”,会将用户选择的记录类型、金额、时间以及备注附加到相应种类的ListBox上,并连接Application数据库,将当前用户ID和记账的数据添加到Account表上。
图片框PictureBox
用于触发打开文件对话框,选择要上传的新头像。选择成功后,删除UserData上对应用户的数据,重新给该用户创建新账号,附上新头像(其他信息不变)(感觉这是比较笨的方法了,但是本人初学数据库太菜,不知道怎么单独更新照片的数据)。
总结说明 这是所有窗体中,需要实现数据库交互功能最多的窗体(但是论实现的功能和复杂性,还是比注册界面略逊一筹),也是整个系统主要的窗体,用于实现记账功能。其中需要与数据库的进行数据交互的操作就有:查询、插入、删除。
个人认为不足的是没有删除记录项的功能,这导致整个系统很累赘,但由于时间关系,最终没能完善,有能力的各位大佬可以再次基础上继续完善,日后我自己若是有机会完善的话会再次更新。
【参考资料】 数据库大作业-代码展示(C#) .C# 数据库大作业-学生管理系统 .ASP.NET(C#)操作SQL Server数据库 .SQL 菜鸟教程 .
工程文件下载 链接:https://pan.baidu.com/s/1xtowjV39Ara3ozPuAW9YQw 提取码:7gju