(14)C#传智:MD5加密,ToString格式,窗体与控件,文本框,单/多选框,图片框,MDI窗体(第14天)
Posted dzweather
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(14)C#传智:MD5加密,ToString格式,窗体与控件,文本框,单/多选框,图片框,MDI窗体(第14天)相关的知识,希望对你有一定的参考价值。
一、MD5加密
数据库是以明文保密,一旦泄露不堪设想.故数据库保存密码时,需要进行第二加密。
MD5加密是不可逆的。简单的是可以解密的。所以尽量复杂避免解密。
创建MD5对象不能用New,因为它是抽象类。可用里面的静态方法Create()。
回忆:抽象方法只能在抽象类中,但抽象类中不一定只有抽象方法,如上面静态方法.
MD5加密操作是字节数组,所以加密前的字串应转为字节数组,加密后也是一字节数组,
再将字节数组转为字串,即得加密后的字串。
在将加密字节数组转为字串后,得到提乱码。
回顾:将字节数组转为字串有三种方式:
1)编码解决:将字节数组中每个元素按照指定的编码格式解析成字符串。
Encoding.UTF8.GetString(str);
2)直接将数组ToString(); (转换成命名空间)
3)将字节数组中的每个元素ToString();
上面中1和3是有区别的。1是将字节按一种编码方式进行解码,可能两码成一字,
可能三码成一字,不同解 码方式不一样。直接不解码,每个字节元素作字符。
ToString("X2"):X表示转换为十六进制,2表示两占位,若0xA则为0x0A,即占位0A。
public static string GetMD5(string str)
MD5 md5 = MD5.Create();//创建md5对象
byte[] buffer = Encoding.Default.GetBytes(str);//入参前字串转字节数组
byte[] md5buffer = md5.ComputeHash(buffer);//计算,不是computer
//return Encoding.Default.GetString(md5buffer);// ,筨琘[朘-#Kp
//上面不能直接转换,否则是乱码
String s = "";
for (int i = 0; i < md5buffer.Length; i++)
//s += md5buffer[i].ToString(); //3244185981728979115075721453575112
//s += md5buffer[i].ToString("x");//202cb962ac5975b964b7152d234b70
s += md5buffer[i].ToString("x2"); //202cb962ac59075b964b07152d234b70
return s;
主函数调用:
private static void Main(string[] args)
//求字串"123"的MD5,密文如下:
//32位大写 3244185981728979115075721453575112
//32位小写 202cb962ac59075b964b07152d234b70
//16位大写 AC59075B964B0715
//16位小写 AC59075B964B0715
Console.WriteLine("0", GetMD5("123"));
Console.ReadKey();
二、ToString()特殊用法
1、日期对象ToString显示.
ToString() 年月日时分秒
ToString("f") 年月日时分(无秒)
ToString("y") 年月
ToString("m") 月日
ToString("d") 年-月-日
ToString("t") 时:分
Console.WriteLine(DateTime.Now.ToString()); //2023/3/5 11:20:45
Console.WriteLine(DateTime.Now.ToString("f"));//2023年3月5日 11:20
Console.WriteLine(DateTime.Now.ToString("y"));//2023年3月
Console.WriteLine(DateTime.Now.ToString("m"));//3月5日
Console.WriteLine(DateTime.Now.ToString("d"));//2023/3/5
Console.WriteLine(DateTime.Now.ToString("t"));//11:22
2、字符型ToString显示
ToString("n") 数字(分节号)
ToString("C") 货币符号+上面 Currency
ToString("e") 指数(科学计算法)
ToString("f4") 固定点(小数点后4位,类推f6则6位)
ToString("x") 16进制
ToString("p") 百分率
double d = 12345678.12345678;
Console.WriteLine(d.ToString("n")); //12,345,678.12
Console.WriteLine(d.ToString("c")); //¥12,345,678.12
Console.WriteLine(d.ToString("e")); //1.234568e+007
Console.WriteLine(d.ToString("f4")); //12345678.1235
Console.WriteLine(12345.ToString("x")); //3039
Console.WriteLine(d.ToString("p")); //1,234,567,812.35%
3、更为常用的占位
yyyy-MM-dd 全占位的月份格式;
yyyy月MMdd日
DateTime n = DateTime.Now;
Console.WriteLine(n.ToString("yyyy-MM-dd"));//2023-03-05
Console.WriteLine(n.ToString("yy-MM-dd")); //23-03-05
Console.WriteLine(n.ToString("yy年MM月dd"));//23年03月05
Console.WriteLine(n.ToString("yyyy年M月d"));//2023年3月5
d:某日(day);
dd某日占两位,前无则用0;
ddd周的简写,如Fri.可设置区域:new CultureInfo("zh")
new CultureInfo("en")
dddd 周的完整名
DateTime d = DateTime.Now;
Console.WriteLine(d.ToString("ddd"));//周日
Console.WriteLine(d.ToString("ddd", new CultureInfo("zh")));//周日
Console.WriteLine(d.ToString("ddd", new CultureInfo("en")));//Sun
Console.WriteLine(d.ToString("dddd"));//星期日
Console.WriteLine(d.ToString("dddd", new CultureInfo("zh")));//星期日
Console.WriteLine(d.ToString("dddd", new CultureInfo("en")));//Sunday
M 某月
MM 某月,占两位
MMM 某月缩写
MMMM 某月全写
DateTime d = DateTime.Now;
Console.WriteLine(d.ToString("MMM"));//3月
Console.WriteLine(d.ToString("MMM", new CultureInfo("zh")));//3月
Console.WriteLine(d.ToString("MMM", new CultureInfo("en")));//Mar
Console.WriteLine(d.ToString("MMMM"));//三月
Console.WriteLine(d.ToString("MMMM", new CultureInfo("zh")));//三月
Console.WriteLine(d.ToString("MMMM", new CultureInfo("en")));//March
y 某年,不含纪元若小于10,只显示个位,否则全显
yy 某年
yyyy 某年,四占位
DateTime d = DateTime.Now;
Console.WriteLine(d.ToString("y"));//2023年3月
Console.WriteLine(d.ToString("y", new CultureInfo("zh")));//2023年3月
Console.WriteLine(d.ToString("y", new CultureInfo("en")));//March 2023
Console.WriteLine(d.ToString("yy"));//23
Console.WriteLine(d.ToString("yy", new CultureInfo("zh")));//23
Console.WriteLine(d.ToString("yy", new CultureInfo("en")));//23
h 小时,12制一占位
hh 小时,12制两占位
H 小时,24制一占位
HH 小时,24制两占位;
m 分钟,一占位
mm 分钟,两占位
s 秒
ss 秒,两占位
三、WinForm窗体应用
控制台方便学习C#,真正项目将不再使用控制台。
为了加快学习进度,vs2022中选择老版本winForm中的NetFramework框架4.72。
1、winForm应用程序是一种智能客户端技术,我们可以使用Winform应用程序帮助我们获得
信息或传输信息等。
2、多了Form1.cs文件:含两个部分类,Form1.Designer.cs和Form1,前者主要设置窗体,后
者主要是后台代码控制。
另外.Form1.resx是资源文件,控制一些字符、音频、视频、数据等。
3、主控Programs.cs是程序入口,调用new Form1()创建窗体对象。每个控件就是一个类,每
一次的拖拉控件到窗体,就是对该控件类进行构造函数调用创建一个控件对象的过程。
4、在InitializeComponent()中有this.SuspendLayout()与this.ResumeLayout()成对出现。
在布局各控件设置变化时,会不断地改变刷新(重绘),引出闪烁,外观上不好还浪费
资源,这时直接暂停(Suspend)重绘,让所有控件设置改变完成后,再一次性重绘刷新
也即Resume,这样节约资源,同时提高程序性能。
四、控件
控件大都一致,也有一些特殊属性和用法。
属性
可以在Form1.Designer.cs中进行设置,也可以在属性面板设置。按F4打开属性面板.
Button
Name 对象名
Text 显示内容
Anchor 锚(上下左右位置锚定)
BackgroundImageLayout:Stretch
ContextMenuStrip:右键菜单,
1.需要添加ContextMenuStrip菜单,并时行设置菜单项;
2.在控件属性中设置与该菜单绑定。
3.运行时对该控件右击,即弹出对应菜单。
Cusor 鼠标样式(仅在对应的控件上生效)
Enable 是否可用
Visible 是否可见
FlatStyle 平面外观
事件:
发生了一件事情。
注册事件:首先先注册一个事件。
触发事件:对上面的注册事件进行触发。
选择控件后按F4调出属性面板,选择事件,里面罗列各种事件,双击其中一个,即进入事件代码。
双击控件出来的事件是控件默认的事件。
事件传参中object sender,表示触发事件的对象,比如点击Button,则sender为Button.
下面查看一下sender是什么
private void button1_Click(object sender, EventArgs e)
string s = sender.ToString();//System.Windows.Forms.Button, Text: button1
Button btn = (Button)sender;
textBox1.Text = btn.ToString();//System.Windows.Forms.Button, Text: button1
如果换成Label控件,看一下sender,里面不再是button对象,而是label。因为触发的是点击
了label,所以触发者乃label也。具体的说是label1.
private void label1_Click(object sender, EventArgs e)
string s = sender.ToString();//System.Windows.Forms.Label, Text: label1
Label btn = (Label)sender;
textBox1.Text = btn.ToString();//System.Windows.Forms.Label, Text: label1
窗体的添加:
在右侧解决方案中的项目右击,选择添加->"Windwos窗体",即可添加新的窗体应用。
但运行调用的仍然是原来的Form1,因为Promgrams.cs的Main()当中:
Application.Run(new Form1());
这里调用的主窗体是Form1,除非改成Form2。
主窗体:
在Main()函数当中创建的窗体对象,我们称之为这个窗体应用程序的主窗体。
也就意味着,当你关闭主窗体那么整个应用程序就关闭了。
例子:在已有Form1窗体时,分别添加Form2.cs与Form3.cs窗体。在Form1中添加Butter1
并命名为"弹出窗体2",对应事件:显示窗体2。同样Form2.cs有按钮,点击事件弹出窗体3。
最后窗体3中有一按钮,事件对应关闭所有窗体。
Form1中:
private void button1_Click(object sender, EventArgs e)
Form frm = new Form2();
frm.Show();
private void button2_Click(object sender, EventArgs e)
Form2 frm2 = new Form2();
frm2.Show();//弹出窗体Form2
用Form与From2定义,两者实质一样,只不过Form是Form2的父类,最好用Form2写,能真实
体现本质对象。
Form2中:
private void button1_Click(object sender, EventArgs e)
Form3 frm = new Form3();
frm.Show();//弹出窗体3
Form3中:
private void button1_Click(object sender, EventArgs e)
//Form1 frm = new Form1();//这个不能关闭主窗体,这是才建立的,不是原窗体1
//frm.Close();
---
//this.Close();//这是关闭当前(Form3)窗体
Form1.frm.Close();
注意,这里关闭所有窗体需要拿到Form1主窗体的对象,但是如何拿到?
1)在Form1类中添加一个Static字段:
public static Form1 frm;
在窗体加载时,让frm=this:
private void Form1_Load(object sender, EventArgs e)
frm = this;
最后在Form3的点击事件中Form1.frm.Close();可以关闭。
2)另外就是添加一个公共静态类,各窗体都可以访问,设置静态字段frm:
internal static class Test
public static Form1 frm;
同样在Form1加载时
private void Form1_Load(object sender, EventArgs e)
Test.frm = this;
最后在Form3点击事件中:Test.frm.Close();
例子:点不到的键钮。一个按钮可以点击,显示信息。另一个按钮鼠标永远点不着。
点不着,就是鼠标移入该按钮时,按钮就会随机变化坐标,从而到了另一个位置。
this.Width与this.ClientSize.Width的区别
ClientSize窗体的工作区。窗体工作区的大小是窗体的大小(不包括边框和标题栏)。 窗体的
工作区是窗体内可放置控件的区域。 当执行图形操作或在窗体上调整控件大小和定位控件时,可以使
用此属性获取正确的尺寸。 若要获取整个窗体的大小,请使用 Size 属性或使用单个属性 Height
和 Width。
this.ClientSize = this.Size;//明显Y轴变化更大,因为标题栏比边框大得多。
MessageBox.Show(this.Width + "--" + this.Size.Width);//两者一样
private void btnLove_Click(object sender, EventArgs e)
MessageBox.Show("为伊消得人憔悴");
this.Close();
private void btnUnLove_MouseEnter(object sender, EventArgs e)
//用户区宽度减去自身宽度,即自身当前能活动的最大宽度
int x = this.ClientSize.Width - btnUnLove.Width;
int y = this.ClientSize.Height - btnUnLove.Height;
Random r = new Random();
btnUnLove.Location = new Point(r.Next(0, x + 1), r.Next(0, y + 1));
五、TextBox
属性
箭头:可以多行,上下拖动。
WorWrap True可换行,False不换行
ScrollBar 滚动条 Horizontal横向 Vertical垂直
PasswordChar 不管输入什么都隐匿,按给定的表现形式显示。
默认事件:TextChanged
label的默认事件是:Click
Timer 计时器(组件里)
Enabled 时间流逝(elapse)是否启用
Interval 流逝(elapsed)事件的频率(以毫秒为单位)
练习:跑马灯.
拖动一Timer控件。
private void timer1_Tick(object sender, EventArgs e)
if (DateTime.Now.Second % 2 == 0)//跑一秒,停一秒
string s = lblShow.Text.Substring(0, 1);
lblShow.Text = lblShow.Text.Substring(1) + s;
练习:闹钟
private void timer1_Tick(object sender, EventArgs e)
lblShow.Text = DateTime.Now.ToString("HH:mm:ss");
if (lblShow.Text == "21:04:50")
SoundPlayer sp = new SoundPlayer();
sp.SoundLocation = @"E:\\1.wav";
sp.Play();
练习:简单记事本,要求:
1)有登陆验证,增强用户体验。
2)无需新开窗口,登陆后显示文本框.
3)自动换行设置。保存文本设置
界面演示:
第一步,窗体加载前处理:
private void Form1_Load(object sender, EventArgs e)
txtWords.Visible = false;
txtWords.WordWrap = false;
btnWrap.Visible = false;
btnSave.Visible = false;
lblUser.Visible = true;
lblPwd.Visible = true;
txtUser.Visible = true;
txtPwd.Visible = true;
btnLogin.Visible = true;
btnReset.Visible = true;
txtPwd.PasswordChar = '*';
txtUser.Focus();
//txtUser.Text = "admin";//调试用
//txtPwd.Text = "123";
第二步,登陆时各按键的处理:
private void btnReset_Click(object sender, EventArgs e)
txtUser.Clear();
txtPwd.Clear();
txtUser.Focus();
private void txtPwd_KeyDown(object sender, KeyEventArgs e)
if (e.KeyCode == Keys.Enter)
btnLogin.PerformClick();//接收回车事件--登陆
private void btnLogin_Click(object sender, EventArgs e)
txtPwd.Text = txtPwd.Text.Trim();
txtUser.Text = txtUser.Text.Trim();
if (txtUser.Text == "admin" && txtPwd.Text == "123")
MessageBox.Show("登陆成功!");
lblUser.Visible = false;
lblPwd.Visible = false;
txtUser.Clear();
txtUser.Visible = false;
txtPwd.Clear();
txtPwd.Visible = false;
btnLogin.Visible = false;
btnReset.Visible = false;
btnWrap.Visible = true;
btnSave.Visible = true;
txtWords.Visible = true;
txtWords.Focus();
else if (txtUser.Text == "" || txtPwd.Text == "")
MessageBox.Show("用户名或密码未输入!");
else
MessageBox.Show("登陆失败");
txtUser.Clear();
txtPwd.Clear();
txtUser.Focus();
第三步,成功后编辑保存
private void btnWrap_Click(object sender, EventArgs e)
if (btnWrap.Text == "自动换行")
btnWrap.Text = "取消换行";
txtWords.WordWrap = true;
else
btnWrap.Text = "自动换行";
txtWords.WordWrap = false;
private void btnSave_Click(object sender, EventArgs e)
using (FileStream fs = new FileStream(@"E:\\666.txt", FileMode.OpenOrCreate, FileAccess.Write))
byte[] b = System.Text.Encoding.Default.GetBytes(txtWords.Text);
fs.Write(b, 0, b.Length);
MessageBox.Show("保存成功");
六、单选RadioButton与多选CheckBox
CheckBox 默认不选中 Checked=False;
RadioButton 默认不选中 Checked=false,且同组控件只能选中一个。
要想分别选中多个,就需要分组,分组最佳选择用容器:GroupBox
练习:学习或老师分别在同一界面登陆
界面:
第一步:程序加载预先设置
private void Form1_Load(object sender, EventArgs e)
this.CenterToScreen();
txtUser.Focus();
txtPwd.PasswordChar = '*';
第二步:登陆选择
private void btnLogin_Click(object sender, EventArgs e)
if (!rdoStudent.Checked && !rdoTeacher.Checked)
MessageBox.Show("请选择学生or老师!");
return;
string user = txtUser.Text.Trim();
string pwd = txtPwd.Text.Trim();
if (rdoStudent.Checked)
if (txtUser.Text == "student" && txtPwd.Text == "student")
MessageBox.Show("登陆成功");
else
MessageBox.Show("登陆失败");
txtUser.Clear();
txtPwd.Clear();
txtUser.Focus();
else
if (txtUser.Text == "teacher" && txtPwd.Text == "teacher")
MessageBox.Show("登陆成功");
else
MessageBox.Show("登陆失败");
txtUser.Clear();
txtPwd.Clear();
txtUser.Focus();
七、MDI窗体的设计
创建步骤:
1)首先确定一个主窗体,将其IsMdiContainer设置为true
2)添加一个菜单,将MenuStrip放置在主窗体中。并设置父窗体:frm.MdiParent=this;
3)布局 LayoutMdi(MdiLayout.TitleHorizontal)
界面:
第一步:加载时窗体居中
private void Form1_Load(object sender, EventArgs e)
this.CenterToScreen();
第二步,设置form1为ismdiparent为真,添加菜单控件,并设置。然后双击菜单添加下面事件:
private void 显示子窗体ToolStripMenuItem_Click(object sender, EventArgs e)
Form2 frm2 = new Form2();
frm2.MdiParent = this;
frm2.Show();
Form3 frm3 = new Form3();
frm3.MdiParent = this;
frm3.Show();
Form4 frm4 = new Form4();
frm4.MdiParent = this;
frm4.Show();
private void 横向排列ToolStripMenuItem_Click(object sender, EventArgs e)
this.LayoutMdi(MdiLayout.TileHorizontal);
private void 纵向排列ToolStripMenuItem_Click(object sender, EventArgs e)
this.LayoutMdi(MdiLayout.TileVertical);
private void 关闭子窗体ToolStripMenuItem_Click(object sender, EventArgs e)
foreach (var frm in this.MdiChildren)
frm.Close();
八、图片框PictureBox
Image 指明显示的图片,图片全路径
SizeMode 显示图片方式
注意:焦点只有在窗体显示后设置有效,在未加载完成前设置焦点无用。
另一个设置焦点的就是设置TabIndex顺序可以隐式设置焦点。
练习:显示图片,通过上一张下一张
界面:
private int i = 0;
private bool blnWinShow = true;
private string[] p = Directory.GetFiles(@"E:\\Test");//全路径
private void Form1_Load(object sender, EventArgs e)
this.CenterToScreen();
picShow.SizeMode = PictureBoxSizeMode.StretchImage;
picShow.Image = Image.FromFile(p[0]);
btnNext.Focus();//此设置无效,因为窗体还没显示出现。
private void Form1_Activated(object sender, EventArgs e)
if (blnWinShow)//应在窗体激活时设置焦点
btnNext.Focus();
blnWinShow = false;
private void btnNext_Click(object sender, EventArgs e)
if (++i == p.Length) i = 0;
picShow.Image = Image.FromFile(p[i]);
private void btnPre_Click(object sender, EventArgs e)
if (--i == -1) i = p.Length - 1;
picShow.Image = Image.FromFile(p[i]);
练习:每秒随机显示图片,并播放音乐
说明:Controls是窗体中控件的集合,可能是Button或TextBox,所以需要再进行判断类型。
在使用类型时,需要显式明确地转换到类型,这样才会有对应的属性与方法提示出现,否则
会出错,找不出原因。
界面:
private int i = 0;
private Random r = new Random();
private string[] s = Directory.GetFiles(@"E:\\Test");
private void Form1_Load(object sender, EventArgs e)
foreach (Control p in this.Controls)
if (p is PictureBox)
//(PictureBox)p.SizeMode这样会出错,点号的优先级高于括号
((PictureBox)p).SizeMode = PictureBoxSizeMode.StretchImage;
((PictureBox)p).Image = Image.FromFile(s[i]);
//播放音乐
SoundPlayer sp = new SoundPlayer();
sp.SoundLocation = @"E:\\1.wav";
sp.Play();
private void timer1_Tick(object sender, EventArgs e)
foreach (Control p in this.Controls)
if (p is PictureBox box)
//is类型模式,减少转换
box.SizeMode = PictureBoxSizeMode.StretchImage;
box.Image = Image.FromFile(s[r.Next(0, s.Length)]);
以上是关于(14)C#传智:MD5加密,ToString格式,窗体与控件,文本框,单/多选框,图片框,MDI窗体(第14天)的主要内容,如果未能解决你的问题,请参考以下文章