虽然一直在玩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