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

这个是比较人性化的设计,当数据很长的时候自适应显示出来,就不是出现当数据太长的时候一行没法显示完整。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 牙龈下面长米粒肉疙瘩怎么办 书画印章盖反了怎么办 金龙鱼一个月不吃东西怎么办 罗汉鱼头撞扁了怎么办 房顶开槽埋线白色不一样怎么办 顶上灯挪位置线怎么办 马蜂窝弄掉又来怎么办 蜂窝弄掉又有怎么办 2018年小龙虾底板脏怎么办 一本分数线擦边过怎么办 玩具塑料球扁了怎么办 胶皮与海绵开了怎么办 安卓不支持flash了怎么办 看视频要加载flash怎么办 下水道管子铁皮破了怎么办 炸金花牌一样大怎么办 玩棋牌游戏输了怎么办 苹果7插耳机外放怎么办 出国种菠菜抓了怎么办 在菲做菠菜抓到怎么办 3串1中两个怎么办 微博账号封停怎么办 阴阳师账号被永久封停怎么办 寒刃2账号被禁用怎么办 输了好多钱我该怎么办 亲朋打鱼别处在玩怎么办 做糯米蛋的蛋清怎么办 水田地没耙地平怎么办 宝宝拉鸡蛋花样大便怎么办 电子琴伴奏区无旋律音怎么办 手机触摸屏摔坏了怎么办 手机充着电玩游戏卡怎么办? 4个月宝宝拉肚子怎么办 6个月宝宝上火怎么办 1月婴儿大便干燥怎么办 椰子鞋350线开了怎么办 打完篮球小腿肌肉酸痛怎么办 衣服穿少了感冒怎么办 侧手翻翻不过去怎么办 生完孩子胯宽了怎么办 小孩户口性质弄错了怎么办