(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天)的主要内容,如果未能解决你的问题,请参考以下文章

C#的MD5加密为啥和JAVA的加密出来的结果不一样?

MD5加密方法

MD5加密C#和js代码加密结果不同

C# 2005 Md5加密后 怎么跟 asp Md5加密不一样!

C# MD5加密

c#字典排序加密MD5加密