WPF桌面应用实例:做一个简单的计算器

虽然一直在玩VS,但是最近才发现,VS可以开发桌面应用,通过WPF,我们可以根据自己的需求定义想要的功能。实在是太方便了,话不多说,我们开始。

VS的版本是2017,之前的版本应该影响也不大

先讲一下基础的思路,首先我们会在界面上布局一个Border(边框),内包含一个TextBlock(文本),作为计算器的显示框。

然后我们再添加一个UniformGrid(均匀分布网格),内包含12个Button(按钮),做为计算机的输入框。最后,我们需要在后台的代码中给每一个按钮添加点击事件,按类型,可以分为,数字点击事件,运算符点击事件,等于键点击事件,清除键点击事件,根据运算结果显示到显示框上。

说完思路,那我们开始吧,首先新建一个工程:

打开工程,我们可以发现有四个比较明显的脚本:

分别是App.xaml、App.xaml.cs、MainWindow.xaml、MainWindow.xaml.cs

App.xaml是负责应用内部的资源管理,App.xaml.cs是负责App.xaml的交互逻辑,MainWindow.xaml是负责页面布局脚本,MainWindow.xaml.cs是负责页面控件交互逻辑的管理。

我们首先设计一下按钮的形式风格,在风格设计上有参考另外一篇博文,出处会在文末指出,我们先写App.xaml:

<Application x:Class="WpfCalc.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfCalc"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <!--点击按钮背景顔色-->
        <LinearGradientBrush x:Key="LinearGradientBlueBackground" EndPoint="0.5,1" StartPoint="0.5,0">
            <GradientStop Color="#FF2F70BD" Offset="0" />
            <GradientStop Color="#FF5278B8" Offset="1" />
        </LinearGradientBrush>
        <!--按钮外边框顔色-->
        <SolidColorBrush x:Key="MyBtnBorderColor" Color="#FF2D78F4"></SolidColorBrush>
        <SolidColorBrush x:Key="MyBtnHoverBackgroundColor" Color="#FF317EF3"></SolidColorBrush>
        <!--END-->

        <Style x:Key="MyWpfButton" TargetType="{x:Type Button}" >
            <!--设置按钮颜色-->
            <Setter Property="Background" Value="{StaticResource LinearGradientBlueBackground}"></Setter>
            <Setter Property="Foreground" Value="White"></Setter>
            <Setter Property="BorderBrush" Value="{StaticResource MyBtnBorderColor}"></Setter>
            <!--设置按钮圆角-->
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" 
                                BorderThickness="{TemplateBinding BorderThickness}" 
                                Background="{TemplateBinding Background}" 
                                SnapsToDevicePixels="true" CornerRadius="5,5,5,5">
                            <!--设置圆角尺寸-->
                            <ContentPresenter x:Name="contentPresenter"
                                              Focusable="False"
                                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                              Margin="{TemplateBinding Padding}"
                                              RecognizesAccessKey="True"
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                        <!--设置触发事件,鼠标悬在按钮上方时按钮变成淡蓝色-->
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Background" TargetName="border" Value="{StaticResource MyBtnHoverBackgroundColor}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Application.Resources>
</Application>
xaml的语法风格几乎跟Html一模一样,所以比较容易掌握,在按钮的设计上,我们用到了四种颜色。
#FF2F70BD
#FF5278B8
#FF2D78F4
#FF317EF3

前两种代表按钮本来的颜色,利用渐变色的原理,让颜色从两个相近的蓝色逐渐过渡。然后通过Border里的CornerRadius属性可以设置按钮的圆角的大小。通过判断鼠标悬停状况,可以让按钮颜色改变。

接着,我们来看一下布局代码MainWindow.xaml:

<Window x:Class="WpfCalc.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfCalc"
        mc:Ignorable="d"
        Title="MainWindow" Height="630" Width="500">
    <Grid>
        <Border Margin="5" Padding="5" Background="LightYellow" BorderBrush="SteelBlue" BorderThickness="3,5,3,5" CornerRadius="10" VerticalAlignment="Top" Height="130" Width="440">
            <TextBlock Name="ShowNumText" Text="" Height="100" Width="450" VerticalAlignment="Top" FontSize="70" Margin="2,15,20,20" HorizontalAlignment="Right" FlowDirection="RightToLeft">
            </TextBlock>
        </Border>
        <UniformGrid Rows="4" Columns="4" Height="400" Width="450" Margin="5,160,6,20">
            <Button Name="btn1" Content="1" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btn2" Content="2" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btn3" Content="3" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btnD" Content="/" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btn4" Content="4" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btn5" Content="5" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btn6" Content="6" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btnX" Content="X" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btn7" Content="7" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btn8" Content="8" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btn9" Content="9" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btnM" Content="—" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btnC" Content="C" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btn0" Content="0" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btnE" Content="=" Style="{StaticResource MyWpfButton}" FontSize="35"/>
            <Button Name="btnP" Content="+" Style="{StaticResource MyWpfButton}" FontSize="35"/>
        </UniformGrid>
    </Grid>
</Window>

我们按照之前的思路,设计了一个界面630*500,显示框130*440,输入框400*450的计算机UI界面,显示框字号70,输入框35,根据这样的格式,最后的显示界面会是这样:

那么,把界面写好了,我们来写一下界面的交互逻辑MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfCalc
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        Dictionary<string, string> OperationDict;//存储两个运算数和运算符的字典
        string num2Str = "";//存储第二个数的临时变量

        public MainWindow()
        {
            InitializeComponent();
            Title = "计算器";
            btnC.Click += BtnC_Click;
            btnE.Click += BtnE_Click;
            btnD.Click += new RoutedEventHandler (BtnOperator_Click);
            btnX.Click += new RoutedEventHandler(BtnOperator_Click);
            btnM.Click += new RoutedEventHandler(BtnOperator_Click);
            btnP.Click += new RoutedEventHandler(BtnOperator_Click);
            btn9.Click += new RoutedEventHandler(BtnNum_Click);
            btn8.Click += new RoutedEventHandler(BtnNum_Click);
            btn7.Click += new RoutedEventHandler(BtnNum_Click);
            btn6.Click += new RoutedEventHandler(BtnNum_Click);
            btn5.Click += new RoutedEventHandler(BtnNum_Click);
            btn4.Click += new RoutedEventHandler(BtnNum_Click);
            btn3.Click += new RoutedEventHandler(BtnNum_Click);
            btn2.Click += new RoutedEventHandler(BtnNum_Click);
            btn1.Click += new RoutedEventHandler(BtnNum_Click);
            btn0.Click += new RoutedEventHandler(BtnNum_Click);
            OperationDict = new Dictionary<string, string>();
        }

        private void BtnOperator_Click(object sender, RoutedEventArgs e)//运算符点击事件
        {
            try {
                var opr = sender as Button;
                if (ShowNumText.Text == "")
                    return;

                switch (opr.Content.ToString())
                {
                    case "+":
                        OperationDict.Add("Operator", "+");
                        break;
                    case "—":
                        OperationDict.Add("Operator", "-");
                        break;
                    case "X":
                        OperationDict.Add("Operator", "*");
                        break;
                    case "/":
                        OperationDict.Add("Operator", "/");
                        break;
                }
                ShowNumText.Text += opr.Content.ToString();
            } catch (Exception e2) {
                MessageBox.Show(e2.ToString());
            }
        }

        private void BtnE_Click(object sender, RoutedEventArgs e)//等于键点击事件
        {
            try
            {
                ShowNumText.Text += "=";
                string str1 = "", str2 = "", opr = "";
                if (OperationDict.TryGetValue("Num1", out str1) && OperationDict.TryGetValue("Operator", out opr) && OperationDict.TryGetValue("Num2", out str2))
                {//如果字典中两个运算数和运算符都不为空,则执行运算
                    int num1 = int.Parse(str1);
                    int num2 = int.Parse(str2);
                    switch (opr)
                    {
                        case "+":
                            ShowNumText.Text = (num1 + num2).ToString();
                            break;
                        case "-":
                            ShowNumText.Text = (num1 - num2).ToString();
                            break;
                        case "*":
                            ShowNumText.Text = (num1 * num2).ToString();
                            break;
                        case "/":
                            ShowNumText.Text = (num1 / num2).ToString();
                            break;
                    }
                    //MessageBox.Show(OperationDict["Num1"] + ":" + OperationDict["Operator"] + ":" + OperationDict["Num2"]);
                    OperationDict.Clear();
                    num2Str = "";
                    OperationDict.Add("Num1", ShowNumText.Text);
                }
                else
                {
                    return;
                }
            }
            catch (Exception e1)
            {
                MessageBox.Show(e1.ToString());
            }
        }

        private void BtnC_Click(object sender, RoutedEventArgs e)//清除键点击事件
        {
            OperationDict.Clear();
            ShowNumText.Text = "";
            num2Str = "";
        }

        private void BtnNum_Click(object sender, RoutedEventArgs e)//数字点击事件
        {
            var num = sender as Button;
            string value = "";
            if (!OperationDict.TryGetValue("Operator",out value ) )
            {//运算符为空,存储的数字为第一个
                if (ShowNumText.Text == "")
                {
                    ShowNumText.Text = num.Content.ToString();
                    OperationDict.Add("Num1", num.Content.ToString());
                }
                else
                {
                    ShowNumText.Text += num.Content.ToString();
                    OperationDict["Num1"] = ShowNumText.Text;
                }
            }
            else {//运算符不为空,存储的数字为第二个
                if (num2Str == "")
                {
                    ShowNumText.Text += num.Content.ToString();
                    num2Str += num.Content.ToString();
                    OperationDict.Add("Num2", num.Content.ToString());
                }
                else
                {
                    ShowNumText.Text += num.Content.ToString();
                    num2Str += num.Content.ToString();
                    OperationDict["Num2"] = num2Str;
                }
            }
            
        }
    }
}

跟之前的思路一样,我们在入口方法中给所有按钮添加了点击事件,然后用一个字典来存储运算的第一个数,运算符以及第二个数,在点击等于后,会判断字典中是否包含这三个值,如果有,则进行运算。

写完这三个脚本以后,计算器的基本功能就完成了,可以做整数的四则运算,但是缺陷也有很多,之后如果有时间,还会继续完善。


参考博文:写自己的WPF样式 https://www.cnblogs.com/xinwang/p/4354182.html

  • 25
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF(Windows Presentation Foundation)是一个用于创建可视化用户界面的框架,它具有丰富的特效功能。火焰特效是其中一个非常实用的特效,可以为应用程序增添动态和生动的视觉效果。 要实现一个实用的WPF火焰特效,可以使用一些基本的图形元素和动画技巧。以下是一个简单实例: 首先,创建一个Canvas作为容器,用于承载火焰特效的元素。在Canvas中,添加一个Ellipse作为火焰的底部,设置其填充颜色为橙色。 然后,使用多个Path元素来定义火焰的形状。路径的绘制可以参考火焰的形状和效果,可以使用曲线和直线的组合来绘制出火焰的轮廓,并填充红色或橙色。 接下来,使用TransformGroup和ScaleTransform来实现火焰动画效果。通过改变ScaleTransform的ScaleY属性值,可以实现火焰的垂直扩展和收缩效果。 最后,使用Storyboard和DoubleAnimation来创建动画。在Storyboard中,使用DoubleAnimation实现ScaleTransform的ScaleY属性值从1到一个较小的值,然后再从这个值回到1的过程。通过设置动画的持续时间和重复次数,可以控制火焰的动画效果。 这样,一个实用的WPF火焰特效就创建好了。在应用程序中使用这个特效,可以为界面增加一些动态和生动的效果,吸引用户的注意力。 总的来说,WPF火焰特效是一个非常实用的特效,通过使用基本的图形元素、动画技巧和特效绘制,可以为应用程序增添动态和生动的视觉效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值