C# 简易计算器(二)
来源:互联网 发布:windows api函数 编辑:程序博客网 时间:2024/05/17 08:19
C# 简易计算器(一)前面展示了一下用C#winform做的简单的计算器,也是课程的小作业,现在分析一下代码是怎么实现的。
首先窗体的加载将一些事件绑定到对应的函数,以及一些初始化
private void Mainfrm_Load(object sender, EventArgs e) { this.KeyPreview = true;//获取或设置一个值,该值指示在将键事件传递到具有焦点的控件前,窗体是否将接收此键事件 btnNum0.BackgroundImage = new Bitmap(Resource1._0); btnNum1.BackgroundImage = new Bitmap(Resource1._1); btnNum2.BackgroundImage = new Bitmap(Resource1._2); btnNum3.BackgroundImage = new Bitmap(Resource1._3); btnNum4.BackgroundImage = new Bitmap(Resource1._4); btnNum5.BackgroundImage = new Bitmap(Resource1._5); btnNum6.BackgroundImage = new Bitmap(Resource1._6); btnNum7.BackgroundImage = new Bitmap(Resource1._7); btnNum8.BackgroundImage = new Bitmap(Resource1._8); btnNum9.BackgroundImage = new Bitmap(Resource1._9); btnAdd.BackgroundImage = new Bitmap(Resource1.add); btnDecrease.BackgroundImage = new Bitmap(Resource1.decrease); btnMul.BackgroundImage = new Bitmap(Resource1.mul); btnDiv.BackgroundImage = new Bitmap(Resource1.div); btnClear.BackgroundImage = new Bitmap(Resource1.clear); btnEqual.BackgroundImage = new Bitmap(Resource1.equal); btnDel.BackgroundImage = new Bitmap(Resource1.del); btnSquareRoot.BackgroundImage = new Bitmap(Resource1.squareRoot); btnPoint.BackgroundImage = new Bitmap(Resource1.point); btnPosAndNeg.BackgroundImage = new Bitmap(Resource1.posAndNeg); this.btnNum0.Click += new System.EventHandler(this.btnNum_Click); this.btnNum1.Click += new System.EventHandler(this.btnNum_Click); this.btnNum2.Click += new System.EventHandler(this.btnNum_Click); this.btnNum3.Click += new System.EventHandler(this.btnNum_Click); this.btnNum4.Click += new System.EventHandler(this.btnNum_Click); this.btnNum5.Click += new System.EventHandler(this.btnNum_Click); this.btnNum6.Click += new System.EventHandler(this.btnNum_Click); this.btnNum7.Click += new System.EventHandler(this.btnNum_Click); this.btnNum8.Click += new System.EventHandler(this.btnNum_Click); this.btnNum9.Click += new System.EventHandler(this.btnNum_Click); setBtnEnableMethon(false);//防止一开始点击运算符按钮导致出错 }
一、数字键
将所有数字键的事件都绑定到btnNum_Click,
this.btnNum0.Click += new System.EventHandler(this.btnNum_Click); this.btnNum1.Click += new System.EventHandler(this.btnNum_Click); this.btnNum2.Click += new System.EventHandler(this.btnNum_Click); this.btnNum3.Click += new System.EventHandler(this.btnNum_Click); this.btnNum4.Click += new System.EventHandler(this.btnNum_Click); this.btnNum5.Click += new System.EventHandler(this.btnNum_Click); this.btnNum6.Click += new System.EventHandler(this.btnNum_Click); this.btnNum7.Click += new System.EventHandler(this.btnNum_Click); this.btnNum8.Click += new System.EventHandler(this.btnNum_Click); this.btnNum9.Click += new System.EventHandler(this.btnNum_Click);
接下来点啥计算器屏幕上应该就加上啥,我是用一个字符串calshow来实现的,当点击数字键后,在calshow后面加上对应的数字
#region 数字按钮 private void btnNum_Click(object sender, EventArgs e) { bool res = Regex.IsMatch(calShow, @"^0+$");//匹配全都是0的情况 bool res1 = Regex.IsMatch(calShow, @"^(\-)?\d+(\.\d+)?(\+|\-|\*|\/)0+$");//匹配第二个操作数是否全都是0的情况 if (res || res1)//满足其中一个则把前面的0删掉 { btnDel.PerformClick(); } if (equalStatus)//等于号按过之后点数字则直接清除原来的结果 { equalStatus = false; calShow = ""; resultDouble = 0.0; txtResual.Text = ""; } Button btn = (Button)sender; calShow += btn.TabIndex.ToString(); txtResual.Text = calShow; setBtnEnableMethon(true); btnEqual.Focus(); } #endregion
上面用了两个正则表达式,分别是:匹配全都是0的情况、匹配第二个操作数是否全都是0的情况,这个的目的就是当你连续点击0的时候,如果首位开始的连0,则忽略掉,比如一开就一直点击0,那么屏幕上应该只有一个0,而不是000000…
接下来就是如果点过了等于号,接下来再点击数字时直接清除原来的结果,最后再把相对应的数字添加到后面。
二、加减乘除以及等于号
这里我将四则运算的操作和等于号直接归为一类,实际上也是可以这么做的,当你连加的时候其实前面的两个数的相加其实也就是等于号的作用。
还有一个就是除以零的错误检测,当除零时会抛出异常。
#region 运算符处理函数 private void multiDeal() { try { //将前面的表达式的值计算出来 Regex reg = new Regex(@"(\+|\-)?(\d+)(\.\d+)?(\+|\-|\*|\/)(\+|\-)?(\d+)(\.\d+)?"); var res = reg.Match(calShow).Groups; //res[0] 整个匹配的表达式 //res[1] 第一个操作数的符号 //res[2] 第一个操作数的整数部分 //res[3] 第一个操作数的小数部分 //res[4] 操作符 //res[5] 第二个操作数的符号 //res[6] 第二个操作数的整数部分 //res[7] 第而个操作数的小数部分 switch (res[4].ToString()) { case "+": resultDouble = Convert.ToDouble(res[1].ToString() + res[2].ToString() + res[3].ToString()) + Convert.ToDouble(res[5].ToString() + res[6].ToString() + res[7].ToString()); calShow = resultDouble.ToString(); break; case "-": resultDouble = Convert.ToDouble(res[1].ToString() + res[2].ToString() + res[3].ToString()) - Convert.ToDouble(res[5].ToString() + res[6].ToString() + res[7].ToString()); calShow = resultDouble.ToString(); break; case "*": resultDouble = Convert.ToDouble(res[1].ToString() + res[2].ToString() + res[3].ToString()) * Convert.ToDouble(res[5].ToString() + res[6].ToString() + res[7].ToString()); calShow = resultDouble.ToString(); break; case "/": double secondNum = Convert.ToDouble(res[5].ToString() + res[6].ToString() + res[7].ToString()); if(secondNum == 0) throw new Exception("除数不能为0!"); resultDouble = Convert.ToDouble(res[1].ToString() + res[2].ToString() + res[3].ToString()) / secondNum; calShow = resultDouble.ToString(); break; default: break; } } catch (Exception ex) { MessageBox.Show(ex.Message, "警告"); } txtResual.Text = calShow; } #endregion
这个函数是这五个键对应的处理函数,正则对应的是(+-)A+(+-)B这样两个数的运算,然后就对字符串进行操作,将两个操作数分离出来
三、小数点
这里有个问题就是小数点什么时候能加,什么情况不能加,比如我不能出现3.4.2这种情况吧,因此我在这里同样使用正则表达式区分这些,当正确输入时能将小数点加上去。
#region 小数点 private void btnPoint_Click(object sender, EventArgs e) { if (equalStatus)//等于号按过之后点数字则直接清除原来的结果 { equalStatus = false; calShow = ""; resultDouble = 0.0; txtResual.Text = ""; } try { bool res = Regex.IsMatch(calShow, @"^(\-)?\d+$");//匹配纯数字 bool res1 = Regex.IsMatch(calShow, @"^(\-)?\d+(\.\d+)?(\+|\-|\*|\/)\d+$");//匹配第二个操作数是否为整数 if (res || res1)//满足其中一个则可以添加小数点 { calShow += "."; } } catch (Exception) { MessageBox.Show("发生错误!", "警告"); } txtResual.Text = calShow; setBtnEnableMethon(true); } #endregion
四、其他操作符
(1)开根号
使用的是Math的Sqrt方法,其中要注意的就是负数开根号的问题,同样这里将抛出异常。
#region 开平方 private void btnSquareRoot_Click(object sender, EventArgs e) { multiDeal();//先得出前面表达式的值 try { Regex reg = new Regex(@"(\+|\-)?(\d+)(\.\d+)?"); var res = reg.Match(calShow).Groups; if (res[1].ToString() == "-") { throw new Exception("负数不能开根号!"); } resultDouble = Math.Sqrt(Convert.ToDouble(calShow)); calShow = resultDouble.ToString(); } catch (Exception ex) { MessageBox.Show(ex.Message,"警告"); } txtResual.Text = calShow; } #endregion
(2)正负号
正负号的操作是先点数字再取正负,正数的时候字符串前面为空,负数的时候字符串前面为“-”。
#region 正负号 private void btnPosAndNeg_Click(object sender, EventArgs e) { multiDeal();//先计算结果,再来加正负号 try { Regex reg = new Regex(@"^(\-)?"); var res = reg.Match(calShow).Groups; if(res[1].ToString() == "")//正数 { calShow = "-" + calShow; } else//负数 { calShow = calShow.Substring(1,calShow.Length-1); } } catch (Exception) { MessageBox.Show("发生错误!","警告"); } txtResual.Text = calShow; } #endregion
(3)退格键
就是将calshow最后面的字符删除即可
#region 退格键 private void btnDel_Click(object sender, EventArgs e) { if(calShow.Length != 0) { calShow = calShow.Substring(0,calShow.Length - 1);//删除最后一个字符 } txtResual.Text = calShow; setBtnEnableMethon(true); }
(4)清除键
即清除所有数据
#region 清除键 //清除所有 private void btnClear_Click(object sender, EventArgs e) { calShow = ""; resultDouble = 0; txtResual.Text = ""; } #endregion
五、按键操作
#region 按键输入 private void Mainfrm_KeyDown(object sender, KeyEventArgs e) { switch(e.KeyCode) { case Keys.D0://字母上面的数字键 btnNum0.PerformClick(); break; case Keys.NumPad0://键盘右边的数字键 btnNum0.PerformClick(); break; case Keys.D1: btnNum1.PerformClick(); break; case Keys.NumPad1: btnNum1.PerformClick(); break; case Keys.D2: btnNum2.PerformClick(); break; case Keys.NumPad2: btnNum2.PerformClick(); break; case Keys.D3: btnNum3.PerformClick(); break; case Keys.NumPad3: btnNum3.PerformClick(); break; case Keys.D4: btnNum4.PerformClick(); break; case Keys.NumPad4: btnNum4.PerformClick(); break; case Keys.D5: btnNum5.PerformClick(); break; case Keys.NumPad5: btnNum5.PerformClick(); break; case Keys.D6: btnNum6.PerformClick(); break; case Keys.NumPad6: btnNum6.PerformClick(); break; case Keys.D7: btnNum7.PerformClick(); break; case Keys.NumPad7: btnNum7.PerformClick(); break; case Keys.D8: btnNum8.PerformClick(); break; case Keys.NumPad8: btnNum8.PerformClick(); break; case Keys.D9: btnNum9.PerformClick(); break; case Keys.NumPad9: btnNum9.PerformClick(); break; case Keys.Enter: btnEqual.PerformClick(); break; case Keys.Add: btnAdd.PerformClick(); break; case Keys.Subtract: btnDecrease.PerformClick(); break; case Keys.Multiply: btnMul.PerformClick(); break; case Keys.Divide: btnDiv.PerformClick(); break; case Keys.Back: btnDel.PerformClick(); break; case Keys.C: btnClear.PerformClick(); break; case Keys.S: btnSquareRoot.PerformClick(); break; case Keys.Z: btnPosAndNeg.PerformClick(); break; case Keys.Decimal: btnPoint.PerformClick(); break; default: break; } } #endregion
这里重要的一点是窗体加载的第一句
this.KeyPreview = true;//获取或设置一个值,该值指示在将键事件传递到具有焦点的控件前,窗体是否将接收此键事件
如果没有这句的话,当你按下按键是没有反应的,其次就是enter键焦点的问题,在数字键处理的最后一句
btnEqual.Focus();
这里每次操作都将焦点转移到enter键上面去
六、其他
#region textBox字体的大小自适应 private void txtResual_TextChanged(object sender, EventArgs e) { if (calShow.Length < 10) { txtResual.Font = new Font(txtResual.Font.Name, 25); } else if (calShow.Length < 20) { txtResual.Font = new Font(txtResual.Font.Name, 15); } else if (calShow.Length < 30) { txtResual.Font = new Font(txtResual.Font.Name, 11); } else { txtResual.Font = new Font(txtResual.Font.Name, 8); } } #endregion
这个是比较人性化的设计,当数据很长的时候自适应显示出来,就不是出现当数据太长的时候一行没法显示完整。
- C# 简易计算器(二)
- C# 简易计算器(一)
- C# 简易计算器(三)
- c#编写简易计算器
- c#简易计算器设计
- C#简易计算器
- C#实现简易计算器
- C#简易教程(二)
- C#小实验 - 简易计算器
- Antlr实现的简易计算器(C#版)
- JavaSwing图形界面编程之简易计算器(二)
- QT简易计算器--表达式计算核心算法(二)
- 简易计算器(JAVA)
- 简易计算器(Java)
- 简易计算器 (1)
- 第一个C#程序--简易计算器
- 使用C#模拟简易的计算器
- web中用c#设计一个简易计算器
- Java经典算法——猴子吃桃
- Spring 事务
- 基于NXP i.MX6的SOM模块系统:eSOMiMX6-micro
- Haproxy、Keepalived双主高可用负载均衡
- HTTP响应头和请求头信息对照表
- C# 简易计算器(二)
- 服务器php安装configure: error: mcrypt.h not found. Please reinstall libmcrypt
- ajax步骤
- Ubuntu 16.04 安装最新版本wine
- 安卓面试小结.
- STM32 NUCLEO LoRa扩展板I-NUCLEO-LRWAN1简介
- code force. Anton and fairy tale.
- HTTP状态码对照表 HTTP response codes
- HTTP相关