目录
-
1.添加编号、省份和编号、地区 对照信息
-
2.检查身份证号码前两位(省份)
-
3.判断城市信息
-
4.检查校验码
-
5.判断闰年
-
6.检查年月日是否正确
-
7.初始化省份,城市信息(级联表)
-
8.UI,真正的开始
-
9.初始化省、城市、年月日、性别
-
10.顺序码
-
11.生成身份证号码(二代)
-
12.添加特效
-
13.添加移除功能
-
14.添加导出文本功能
-
15.验证身份证号码
-
16.总结
-
17.参考资料
一个小小的问题引发的联想,仅仅是为了学习一下哈希表和字典,没想到一下子写了这么多,姑且做个总结吧。实在想不出该用什么标题,随便聊聊。
1.添加编号、省份和编号、地区 对照信息
这个需要用到键值对,想想List,只能用到List<string>
,倒是没见过使用List<string ,string>
刚开始想到了哈希表,然后又想到二维数组和字典,斟酌再三,于是选中字典。理由如下
二维数组在长度和添加更多的省市对照信息时候需要考虑不少,搞不定多了就晕的要超出长度了;
HashTable在遍历时会大乱顺序;
Dictionay和HashTable比较字典速度更快。(在某个博客看到的)
首先,我们来添加省份对照信息,这方面,百度文库可以出来:
初始化:
// 使用字典初始化
Dictionary<string, string> dtpro = new Dictionary<string, string>();//省份
Dictionary<string, string> dtplace = new Dictionary<string, string>();//城市
添加编号、省份对照表:
/// <summary>
/// 添加编号、省份对照信息
/// xxx.add("xx");让我想起了List<string>中的add
/// </summary>
public void adddtpro()
{
#region 添加省份信息
dtpro.Add("11", "北京市");
dtpro.Add("12", "天津市");
dtpro.Add("13", "河北省");
dtpro.Add("14", "山西省");
dtpro.Add("15", "内蒙古自治区");
dtpro.Add("21", "辽宁省");
dtpro.Add("22", "吉林省");
dtpro.Add("23", "黑龙江省");
dtpro.Add("31", "上海市");
dtpro.Add("32", "江苏省");
dtpro.Add("33", "浙江省");
dtpro.Add("34", "安徽省");
dtpro.Add("35", "福建省");
dtpro.Add("36", "江西省");
dtpro.Add("37", "山东省");
dtpro.Add("41", "河南省");
dtpro.Add("42", "湖北省");
dtpro.Add("43", "湖南省");
dtpro.Add("44", "广东省");
dtpro.Add("45", "广西壮族自治区");
dtpro.Add("46", "海南省");
dtpro.Add("50", "重庆市");
dtpro.Add("51", "四川省");
dtpro.Add("52", "贵州省");
dtpro.Add("53", "云南省");
dtpro.Add("54", "西藏自治区");
dtpro.Add("61", "陕西省");
dtpro.Add("62", "甘肃省");
dtpro.Add("63", "青海省");
dtpro.Add("64", "宁夏回族自治区");
dtpro.Add("65", "新疆维吾尔自治区");
dtpro.Add("71", "台湾省");
dtpro.Add("81", "香港特别行政区");
dtpro.Add("82", "澳门特别行政区");
#endregion
}
添加编号、城市对照表:(改的手麻,卡,还好有正则替换的记事本)
/// <summary>
/// 添加编号、城市对照信息
/// </summary>
public void adddtplace()
{
//大约3400多条,问一下博客园的同志,是不是码长了?怎么一直插入失败呢
}
这样,就把省份和城市的信息初始化了,需要时调用就行,先别急,这是我们的准备工作。
2.检查身份证号码前两位(省份)
既然把省份和城市信息搞定,那么我们是不是得准备一个附加功能,提供对身份信息的查询呢,这样,就意味着要检查前两位号码;因为信息不多,姑且用数组尝尝味道把,
/// <summary>
/// 检查前2个
/// </summary>
/// <param name="str">前2个数字</param>
/// <returns>返回省份</returns>
public string checkpro(string str)
{
string[,] proarray = new string[,] { { "北京市", "11" }, { "天津市", "12" }, { "河北省", "13" }, { "山西省", "14" }, { "内蒙古自治区", "15" }, { "辽宁省", "21" }, { "吉林省", "22" }, { "黑龙江省", "23" }, { "上海市", "31" }, { "江苏省", "32" }, { "浙江省", "33" }, { "安徽省", "34" }, { "福建省", "35" }, { "江西省", "36" }, { "山东省", "37" }, { "河南省", "41" }, { "湖北省", "42" }, { "湖南省", "43" }, { "广东省", "44" }, { "广西壮族自治区", "45" }, { "海南省", "46" }, { "重庆市", "50" }, { "四川省", "51" }, { "贵州省", "52" }, { "云南省", "53" }, { "西藏自治区", "54" }, { "陕西省", "61" }, { "甘肃省", "62" }, { "青海省", "63" }, { "宁夏回族自治区", "64" }, { "新疆维吾尔自治区", "65" }, { "台湾省", "71" }, { "香港特别行政区", "81" }, { "澳门特别行政区", "82" } };
string prostr = "";
for (int i = 0; i < proarray.Length / 2; i++)
{
if (proarray[i, 1] == str)
{
prostr = proarray[i, 0];
break;
}
}
return prostr;
}
3.判断城市信息
这里,我们提供一个对身份证编号前6位的查询方法,这样就可以查询到具体城市。
/// <summary>
/// 判断城市信息
/// </summary>
/// <param name="str">前6位</param>
/// <returns>返回所在位置,没有则返回空</returns>
public string checkplace(string str)
{
adddtplace();//得先初始化信息将其添加到字典
//ContainsKey:这是字典中的一个方法,有点类似HashTable,我们在 1 中增加了dtplace并在上一行初始化了,现在信息已经存入字典。
//这里的ContainsKey是查看key里面,键值对,即键中 是否包含str
if (dtplace.ContainsKey(str))
return dtplace[str].ToString();//返回城市名称
else
return "";//没有则返回空
}
4.检查校验码
理解校验码可以查看某百科,这是复制下来的话:
①、将前面的身份证号码17位数分别乘以不同的系数。第i位对应的数为[2^(18-i)]mod11(这个是什么意思?没理解)。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 ;
②、将这17位数字和系数相乘的结果相加;
③、用加出来和除以11,看余数是多少?;
④、余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2;
⑤、通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2;
例如:某男性的身份证号码是34052419800101001X。我们要看看这个身份证是不是合法的身份证。
首先:我们得出,前17位的乘积和是189
然后:用189除以11得出的结果是17 + 2/11,也就是说余数是2。
最后:通过对应规则就可以知道余数2对应的数字是x。所以,这是一个合格的身份证号码。
好了,我们用程序生成,代码如下:
/// <summary>
/// 检查校验码
/// </summary>
/// <param name="str">输入前17位</param>
/// <returns>返回校验码</returns>
public string checkcode(string str)
{
int sumno = 0;
sumno += strToint(str[0].ToString()) * 7;
sumno += strToint(str[1].ToString()) * 9;
sumno += strToint(str[2].ToString()) * 10;
sumno += strToint(str[3].ToString()) * 5;
sumno += strToint(str[4].ToString()) * 8;
sumno += strToint(str[5].ToString()) * 4;
sumno += strToint(str[6].ToString()) * 2;
sumno += strToint(str[7].ToString()) * 1;
sumno += strToint(str[8].ToString()) * 6;
sumno += strToint(str[9].ToString()) * 3;
sumno += strToint(str[10].ToString()) * 7;
sumno += strToint(str[11].ToString()) * 9;
sumno += strToint(str[12].ToString()) * 10;
sumno += strToint(str[13].ToString()) * 5;
sumno += strToint(str[14].ToString()) * 8;
sumno += strToint(str[15].ToString()) * 4;
sumno += strToint(str[16].ToString()) * 2;
int result = sumno % 11;
string checkcode = "-1";
switch (result)
{
case 0:
checkcode = "1";
break;
case 1:
checkcode = "0";
break;
case 2:
checkcode = "X";
break;
case 3:
checkcode = "9";
break;
case 4:
checkcode = "8";
break;
case 5:
checkcode = "7";
break;
case 6:
checkcode = "6";
break;
case 7:
checkcode = "5";
break;
case 8:
checkcode = "4";
break;
case 9:
checkcode = "3";
break;
case 10:
checkcode = "2";
break;
default:
checkcode = "-1";
break;
}
return checkcode;
}
5.判断闰年
在让用户选择日期的时候,是不是得考虑到下来列表的情况呢?
有点类似级联表,即上述的省份和城市对照表,就是例子。当然年月日也是这样,考虑闰年中的2月29天和28天情况。当年份整除以4并且不能整除以100或者整除以400的情况下才是闰年。
用代码判断吧:
/// <summary>
/// 判断是否闰年
/// </summary>
/// <param name="year">年份</param>
/// <returns>返回bool值</returns>
public bool cheakYear(int year)
{
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
{
return true;
}
else
{
return false;
}
}
6.检查年月日是否正确
涉及到闰年中的2月。闰年2月29天,非闰年2月28天。
/// <summary>
/// 检查年月日是否正确
/// </summary>
/// <param name="str">输入前17位</param>
/// <returns>返回错误提示,没有错误则返回空字符串</returns>
public string checkdate(string str)
{
int checkyear = strToint(str[6].ToString() + str[7].ToString() + str[8].ToString() + str[9].ToString());
int checkmonth = strToint(str[10].ToString() + str[11].ToString());
int checkday = strToint(str[12].ToString() + str[13].ToString());
int year = strToint(DateTime.Now.Year.ToString());//当前年份
int month = strToint(DateTime.Now.Month.ToString());//当前月份
int day = strToint(DateTime.Now.Day.ToString());//当前几号
if (checkyear > year || checkyear + 100 < year)
return "输入年份尚未生效或已经过期!";
else
{
if (checkmonth < 1 || checkmonth > 12)
return "月份有误!";
else
{
//获取输入月份下该月份天数
//判断是否闰年
if (checkday < 0)
return "日期有误";
else
{
if (checkmonth == 1 || checkmonth == 3 || checkmonth == 5 || checkmonth == 7 || checkmonth == 9 || checkmonth == 11 || checkmonth == 12)
{
if (checkday > 31)
return "日期有误!";
}
if (checkmonth == 2)
{
if (cheakYear(checkyear) && checkday > 29)
{
return "2月日期有误!";
}
if (!cheakYear(checkyear) && checkday > 28)
{
return "2月日期有误!";
}
}
if ((checkmonth == 4 || checkmonth == 6 || checkmonth == 8 || checkmonth == 10) && checkday > 30)
{
return "日期有误!";
}
}
return "";
}
}
}
7.初始化省份,城市信息(级联表)
我们的省份信息添加到字典了,城市信息也添加了,这会儿,是不是做一下将其添加到下拉列表前的准备呢。(PS:我真没想到我为什么还要定义一个ArrayList然后而不是ContainsKey判断直接传值,难道是为了绑定数据源方便么?因为写这个玩意过了去了三个月,忘了,有没有人帮我解释一下。)
ArrayList alpro = new ArrayList();
ArrayList alplace = new ArrayList();
/// <summary>
/// 初始化省份信息(添加到alpro中)
/// </summary>
/// <returns>返回省份<编号,省份>的arraylist</returns>
public ArrayList matchpro()
{
adddtpro();
adddtplace();
foreach (var item in dtpro)
{
alpro.Add(new DictionaryEntry(item.Key, item.Value));
}
return alpro;
}
/// <summary>
/// 根据省份初始化城市信息(添加到alplace上)
/// </summary>
/// <param name="strpro">省份代号</param>
/// <returns>返回城市<编号,城市>的arraylist</returns>
public ArrayList matchplace(string strpro)
{
alplace.Clear();//清空数据
foreach (var item in dtplace)
{
string itemkey = item.Key.ToString();
if ((itemkey[0].ToString() + itemkey[1].ToString().ToString() == strpro))
{
//0000为省份代号
if ((itemkey[0].ToString() + itemkey[1].ToString() + itemkey[2].ToString() + itemkey[3].ToString().ToString() != "0000"))
{
alplace.Add(new DictionaryEntry(item.Key, item.Value));
//如果用hashtable用foreach遍历再add之后会发现顺序被打乱
}
}
}
return alplace;
}
8.UI,真正的开始
以上方法我都将其保存到新建的一个类中,命名为ClassCheck.cs,仅仅作为准备工作,
下面,才算是真正的开始,看图如下:
其中命名
省份:cbpro;
城市:cbplace
年、月、日:cbyear 、cbmonth、cbday
性别:cbsex
生成结果的listbox:lbresult
功能区:Get:btnGet;copy:btnCopy;Remove:btnRemove;Check:btnCheck;Output:btnout
9.初始化省、城市、年月日、性别
初始化之前,我们先把我们刚才积累的一些方法用到这里,
实例化类,刚才我们不是把一些准备的方法放到了cs里面了么,现在先准备好:
ClassCheck clcheck = new ClassCheck();
int choseplace = 0;//当没选择城市时初始化为0,后面要用
先上简单点的年月日、性别 初始化
①.添加年份:
//添加年份
private void beginyear()
{
//1950-当前年份
int year = DateTime.Now.Year;
for (int i = 1950; i <= year; i++)
{
cbyear.Items.Add(i);
}
}
②.添加月份:
//添加月份
private void beginmonth()
{
//1-当前月
//两种情况,当前年以前,1-12个月;算了,麻烦,又得判断,就用12个月吧,这样是不是还没出生的都有了
//选1-12
//int month = DateTime.Now.Month;
for (int i = 1; i <= 12; i++)
{
cbmonth.Items.Add(i);
}
}
③.添加当月天数:
//添加当月天数
private void beginday()
{
//分为闰年 的2月判断
//这里是不是就用到了类中的方法了
bool byear = clcheck.cheakYear(Convert.ToInt32(cbyear.Text.Trim()));
switch (cbmonth.Text)
{
case "4":
case "6":
case "8":
case "10":
for (int i = 1; i <= 30; i++)
{
cbday.Items.Add(i);
}
break;
case "2":
if (byear)
{
for (int i = 1; i <= 29; i++)
{
cbday.Items.Add(i);
}
}
else
{
for (int i = 1; i <= 28; i++)
{
cbday.Items.Add(i);
}
}
break;
default:
for (int i = 1; i <= 31; i++)
{
cbday.Items.Add(i);
}
break;
}
}
④.添加性别:
//添加性别
private void beginsex()
{
cbsex.Items.Add("男");
cbsex.Items.Add("女");
}
⑤.两级联动
根据省份(编号)匹配城市(编号)(前两个数字匹配),绑定到下拉列表中
/// <summary>
/// 两级联动,根据省份编号匹配城市(前两个数字)
/// </summary>
/// <param name="strpro"></param>
private void begindata(string strpro)
{
ArrayList alplace = clcheck.matchplace(strpro);
cbplace.DataSource = alplace;
cbplace.DisplayMember = "value";
cbplace.ValueMember = "key";
}
⑥.界面真正的初始化(是不是用到了上面的两级联动的方法了,其实就是传参,没啥高明的)
改动省份城市变化
/// <summary>
/// 改动省份时城市变动
/// </summary>
private void cbpro_SelectedValueChanged(object sender, EventArgs e)
{
//窗体第一次加载时会自动调用该事件,因为窗体加载时初始化了数据,而此时文本框里是空的,所以调用不了数据
cbplace.DataSource = null;
//begindata(cbpro.SelectedValue.ToString());
if (choseplace > 1)
{
cbplace.DataSource = null;
string strpro = cbpro.SelectedValue.ToString();
begindata(strpro);
}
else
{
choseplace++;
}
}
改动月份日期变化(如不写此变化会不会出现了个2月31日的情况呢)
/// <summary>
/// 改变月份时日期变动
/// </summary>
private void cbmonth_SelectedIndexChanged(object sender, EventArgs e)
{
cbday.DataSource = null;
cbday.Items.Clear();
beginday();
//begindata(cbpro.SelectedValue.ToString());
//if (choseplace > 1)
//{
// cbmonth.DataSource = null;
// string strpro = cbpro.SelectedValue.ToString();
// begindata(strpro);
//}
//else
//{
// choseplace++;
//}
}
改动年份时日期变化
/// <summary>
/// 改动年份时日期变动
/// </summary>
private void cbyear_SelectedIndexChanged(object sender, EventArgs e)
{
cbday.DataSource = null;
cbday.Items.Clear();
beginday();
}
⑦.初始化我们的界面吧
private void frmidentity_Load(object sender, EventArgs e)
{
//初始化省份数据源
ArrayList alpro = clcheck.matchpro();
cbpro.DataSource = alpro;
cbpro.DisplayMember = "value";
cbpro.ValueMember = "key";
//设置默认省份
cbpro.SelectedIndex = 0;
//设置默认城市
begindata(cbpro.SelectedValue.ToString());
//设置默认年份
beginyear();
cbyear.SelectedIndex = 0;
//设置默认月份
beginmonth();
cbmonth.SelectedIndex = 0;
//设置默认天数
beginday();
cbday.SelectedIndex = 0;
//设置默认性别
beginsex();
cbsex.SelectedIndex = 0;
//ComboBox控件的DrawMode属性为:OwnerDrawVariable ,然后设置ItemHeight属性你要求的高度。不然下拉下来太长岂不是很像那个...你懂得的...
//cbpro.Height = 20;
cbpro.DropDownHeight = 100;
cbplace.DropDownHeight = 100;
cbyear.DropDownHeight = 100;
cbmonth.DropDownHeight = 100;
cbday.DropDownHeight = 100;
this.Opacity = 0.95;
}
10.顺序码
写到这里,我们是不是忘了身份证号码中一个重要的3位顺序码呢,好吧,这里加上,不习惯可以改到cs类中去。顺序码=2位+性别1位。
//顺序码=2位+性别1位
//随机生成5个不重复的顺序码怎么玩?
private string beginturn()
{
Random rm=new Random();
int turnfirint = rm.Next(0, 100);
string turnfirstr,turnsexstr;
string[] str = new string[5];
if (turnfirint < 10)
{
turnfirstr = "0" + turnfirint.ToString();
}
else
{
turnfirstr = turnfirint.ToString();
}
if (cbsex.SelectedIndex == 0)//男
{
turnsexstr = (2 * rm.Next(0, 5) + 1).ToString(); ;
}
else
{
turnsexstr = (2 * rm.Next(0, 5)).ToString();
}
return turnfirstr + turnsexstr;
}
PS:每次 随机生成5个 不同 顺序码是不是更刺激?不过貌似有点麻烦诶,有没有好的办法。
不要告诉我是把数字分成5等分,每次取出一个等份,连取5次,合起来5个。有兴趣的可以试试更高端的。
11.生成身份证号码(二代)
好了,总算把所有的准备工作做好,调用吧,生成结果,就是符合验证的号码。但是,不一定此号码存在,仅仅可以验证成功而已,其它的,就不在本篇博文范围了。
生成结果:
//生成结果
private string getresule()
{
string strplace= cbplace.SelectedValue.ToString();
string strbir,strmonth,strday;
if(cbmonth.Text.Length<2)
{
strmonth="0"+cbmonth.Text.ToString();//选择的月是一位数要在前面加0
}
else
{
strmonth=cbmonth.Text.ToString();
}
if(cbday.Text.Length<2)
{
strday="0"+cbday.Text.ToString();
}
else
{
strday=cbday.Text.ToString();
}
strbir=cbyear.Text.ToString()+strmonth+strday;
string strfir=strplace+strbir+beginturn();
string strall=strfir+clcheck.checkcode(strfir);
return strall;
}
lbresult.Items.Add(getresule());
12.添加特效
这样就结束了么,我们是不是还添加上一些小功能和特效呢?还有,cs中这个么多准备可不能浪费啊。
添加透明的提示窗体,效果如图:
copy成功,或者导出成功,是不是要加点啥呢,总比MessageBox漂亮吧。
要实现的功能:弹出透明窗体 渐变提示,自动渐变消失。
好了,我们在项目中 添加=>用户控件 ,我的命名为 F_Sign.cs
给控件上添加上label标签:lbsign,添加时间控件(渐变功能):timer1
在F_Sign.cs 的load添加如下代码:
private void Form_CopySign_Load(object sender, EventArgs e)
{
this.timer1.Enabled = true;//激活时间控件
this.Opacity = 1;//窗体透明度为1,即完全不透明
}
timer的Tick事件添加:
private void timer1_Tick(object sender, EventArgs e)
{
if (this.Opacity > 0.5)
{
this.Opacity = this.Opacity - 0.08;
}
else
{
Close();
}
//意思就是当窗体的透明度大于0.5时透明度以0.08的速度递减;否则就关闭窗体
}
重载窗体函数,我们的提示信息狠多,肯定不能单一,所以,这就涉及到两个窗体之间的传参:
public F_Sign(int sign)
{
InitializeComponent();
this.Opacity = 0.9;
if(sign==0)
{
lbsign.Text = "Failed!";
}
else if (sign == 1)
{
lbsign.Text = "Success!";
}
else if (sign == 2)
{
lbsign.Text = "Wrong number!";
}
else if (sign == 3)
{
lbsign.Text = "No chose!";
}
}
当传过来的是0,我们理解我操作失败;1是成功;2是号码错误(用于验证身份证号码);3是你没有选择(用户复制时没有选择生成的特定号码)
窗体传值,从主窗体传到新建窗体,这个不难,大家可以自己学习。倒是从新窗体再把值传到主窗体,这个难度不小,用属性倒是不行的,这个需要深究了。好了,我们先上代码,萨后再在其它功能中添加主窗体和新窗体之间的传值,把你传晕。
复制功能和小特效展示:
/// <summary>
/// 复制
/// </summary>
private void btnCopy_Click(object sender, EventArgs e)
{
try
{
Clipboard.SetDataObject(lbresult.SelectedItem);
F_Sign frm = new F_Sign(1);//这不是就是上面的1么
frm.ShowDialog();
}
catch (Exception err)
{
//出现错误就复制失败
F_Sign frm = new F_Sign(0);//0在这里
frm.ShowDialog();
}
}
上图的提示效果完美完成,
13.添加移除功能
之所以要说到移除,有的同学说,很简单的码,清空Listbox不就OK了,这里我们要实现的是选中一行移除,移除之后我们的焦点一定还要在选中的行上面。但是这时如果移除的下面行没了呢?我们是不是还得把选中的焦点上移呢?
看代码:
/// <summary>
/// 移除选中
/// </summary>
private void btnRemove_Click(object sender, EventArgs e)
{
//try{}catch{}捕获异常,话说去年没毕业的时候面试,还得一个C++的面试官刁难了一次,很恶心,自己不懂还来和我抬杠,诶,没办法诶。
try
{
int indexbegin = lbresult.SelectedIndex;
lbresult.Items.Remove(lbresult.SelectedItem);
if (lbresult.Items.Count == 0)
{
return;
}
//MessageBox.Show(lbresult.SelectedIndex.ToString());
if (indexbegin == 0)
{
lbresult.SelectedIndex = 0;
}
else
{
//选中的为最后一个
if (indexbegin == lbresult.Items.Count - 1)
{
lbresult.SelectedIndex = indexbegin - 1;
}
else
{
//MessageBox.Show(lbresult.SelectedIndex.ToString());
lbresult.SelectedIndex = indexbegin - 1;
}
}
}
catch (Exception err)
{
F_Sign frm = new F_Sign(3);
frm.ShowDialog();
}
}
14.添加导出文本功能
看到生成的这些号码,不导出保存一下,难道要我们一个个复制么,人性化点吧,给个导出功能,就是界面上的OutPut。
上代码,自己可以去学习命名空间 IO 下的一些方法吧,或许你能懂得更多。
/// <summary>
/// 导出结果
/// </summary>
private void btnout_Click(object sender, EventArgs e)
{
if (lbresult.Items.Count > 0)
{
string str = "";
StreamWriter sw = new StreamWriter("outid.txt");
for (int i = 0; i < lbresult.Items.Count; i++)
{
//str += lbresult.Items[i] + "\n";
sw.WriteLine(lbresult.Items[i]);
}
sw.Close();
}
}
15.验证身份证号码
最后再来点,好吧,没完没了了。只是自己做点小工具,此篇博文仅仅是自己的 这次联系的知识总结。好吧,我们生成了号码,但是在文章开始做的那个类cs中,我们的方法,岂不是浪费了,要不要加个验证 身份证号码的小窗体呢。
添加一个新窗体:F_check.cs,相关控件如下图,不再一一说明。
这里涉及到的主要知识点:
传值:主窗体传到新建窗体(见12.添加特效,本功能不再演示,自己可以添加上写写),新窗体传到主窗体。
主窗体添加如下代码:
/// <summary>
/// Check
/// </summary>
private void btnCheck_Click(object sender, EventArgs e)
{
//cbplace.DataSource = null;
//string strpro = cbpro.SelectedValue.ToString();
//begindata(strpro);
F_check f2 = new F_check();
f2.Owner = this;//传值关键,新窗体往主窗体回传值不能用属性
f2.ShowDialog();
}
验证号码信息,当然,我们这里不是从主窗体复制的,你可以自己仿照 12 试试将选中的号码传到 新窗体 来验证,我们这里直接输入吧,
下面代码懒得整理,这不是重点,调用我们在文章开始写的方法即可。
private void btnCheck_Click(object sender, EventArgs e)
{
string strid = txtid.Text.Trim();
string strplace = "";
string stryear="";
string strmonth="";
string strday="";
string strturn="";
string strsex="";
ClassCheck clck = new ClassCheck();
if(strid.Length==18)
{
//校验码
if( clck.checkcode(strid.Substring(0,17))!=strid[17].ToString())
{
lbplace.Text = "place : wrong number!";
lbdate.Text = "";
lbsex.Text = "";
lbturn.Text = "";
F_Sign frm = new F_Sign(2);
frm.ShowDialog();
return;
}
strplace=clck.checkplace(strid.Substring(0,6));
stryear=strid.Substring(6,4);
//strplace=clck.checkplace(strid[0].ToString() + strid[1].ToString() + strid[2].ToString() +
// strid[3].ToString() + strid[4].ToString() + strid[5].ToString());
//stryear = strid[6].ToString() + strid[7].ToString() + strid[8].ToString() + strid[9].ToString();
if (strid[10].ToString() == "0")
{
strmonth = strid[11].ToString();
}
else
{
strmonth = strid[10].ToString() + strid[11].ToString();
}
if (strid[12].ToString() == "0")
{
strday = strid[13].ToString();
}
else
{
strday = strid[12].ToString() + strid[13].ToString();
}
strturn = strid[14].ToString() + strid[15].ToString() + strid[16].ToString();
if (strid[16].ToString() == "1" || strid[16].ToString() == "3" || strid[16].ToString() == "5" || strid[16].ToString() == "7" || strid[16].ToString() == "9")
{
strsex = "男";
}
else
{
strsex = "女";
}
lbplace.Text ="place : "+strplace;
lbdate.Text = "date : " + stryear + "-" + strmonth + "-" + strday;
lbturn.Text = "turn : "+strturn;
lbsex.Text = "sex : " + strsex;
}
}
将我们输入的号码反填到主窗体的ListBox中,至于本号码对不对,想研究的童鞋可以自己做个判断。
private void btnAdd_Click(object sender, EventArgs e)
{
F_main frm = (F_main)this.Owner;
((ListBox)frm.Controls["lbresult"]).Items.Add(this.txtid.Text.Trim());
this.Close();
}
这样,我们图上的功能就基本实现了。
16.总结
实在受不了,一写,发现还有狠多需要实现,入坑了,坚决不继续写了,这孩子,越想越多了。
本篇博文,仅仅是自己学习了一些字典和哈希表的小知识,顺便,想体验一下,没想到搞了这么多。
知识总结如下,通过本文,你需要加深如下了解:
①哈希表,字典,二维数组 的使用(超大数据的提取和写入中作为缓存,后面例子将用到);
② \文件写入和读取(后面将做个超简单的文件浏览器雏形);
③下拉表绑定和多级联动;
④窗体之间的传值,正传和反传;
⑤其它
17.参考资料
注:请勿将工具用于非法用途,否则后果自负。
本文最后修订时间:2017-11-15