问题描述
运用WPF技术,模仿Windows 10系统中计算机器(Calculator)程序,开发一个类似程序。
问题分析
注:
- MS:记忆当前显示的数字(Memory Save)
- MC:清除记忆的数字(Memory Clean)
- MR:显示记忆的数字(Memory Recall)
- M-:记忆的数字减去当前数字,并保存
- M+:记忆的数字加上当前数字,并保存
解决方案
创建WPF应用
UI设计
Metro风格来美化:https://www.cnblogs.com/ouyangkai/p/12759466.html
App.xaml
<Application x:Class="Homework19.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Homework19"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
MainWindow.xaml
<Controls:MetroWindow x:Class="Homework19.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:Homework19"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
mc:Ignorable="d"
ResizeMode = "NoResize"
Title="计算器" Height="750" Width="1000">
<Grid>
<TextBlock x:Name="Out_2" HorizontalAlignment="Left" Margin="10,55,0,0" TextWrapping="Wrap"
VerticalAlignment="Top" Height="33" Width="670" TextAlignment="Right" FontSize="24">
<Run/>
<LineBreak/>
<Run/>
</TextBlock>
<TextBlock x:Name="Out_1" HorizontalAlignment="Left" Margin="10,93,0,0" TextWrapping="Wrap" Text="0"
VerticalAlignment="Top" Height="91" Width="670" TextAlignment="Right" FontSize="72"
FontFamily="Microsoft YaHei"/>
<Button x:Name="btnMenu" Content="≡标准" HorizontalAlignment="Left" Margin="10,10,0,0"
VerticalAlignment="Top" Width="70" Height="40" FontSize="20" Click="Button_Click">
<Button.ContextMenu>
<ContextMenu Name="contextMenu">
<MenuItem Header="标准"/>
<MenuItem Header="科学"/>
<MenuItem Header="程序员"/>
<MenuItem Header="日期计算"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
<Button x:Name="B_MC" Content="MC" HorizontalAlignment="Left" Margin="10,189,0,0" VerticalAlignment="Top"
Width="70" Height="40" Click="B_MC_Click"/>
<Button x:Name="B_MR" Content="MR" HorizontalAlignment="Left" Margin="85,189,0,0" VerticalAlignment="Top"
Width="70" Height="40" Click="B_MR_Click"/>
<Button x:Name="B_M__1" Content="M+" HorizontalAlignment="Left" Margin="160,189,0,0" VerticalAlignment="Top"
Width="70" Height="40" Click="B_M__1_Click"/>
<Button x:Name="B_M__" Content="M-" HorizontalAlignment="Left" Margin="235,189,0,0" VerticalAlignment="Top"
Width="70" Height="40" Click="B_M___Click"/>
<Button x:Name="B_MS" Content="MS" HorizontalAlignment="Left" Margin="310,189,0,0" VerticalAlignment="Top"
Width="70" Height="40" Click="B_MS_Click"/>
<Button x:Name="B_per" Content="%" HorizontalAlignment="Left" Margin="10,236,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="24" FontFamily="Microsoft YaHei UI Light" Click="B_per_Click"/>
<Button x:Name="B_CE" Content="CE" HorizontalAlignment="Left" Margin="145,236,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="24" FontFamily="Microsoft YaHei UI Light" Click="B_CE_Click"/>
<Button x:Name="B_C" Content="C" HorizontalAlignment="Left" Margin="280,236,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="24" FontFamily="Microsoft YaHei UI Light" Click="B_C_Click"/>
<Button x:Name="B_delete" Content="<-" HorizontalAlignment="Left" Margin="415,236,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="24" FontFamily="Microsoft YaHei UI Light" Click="B_delete_Click"/>
<Button Content="÷" HorizontalAlignment="Left" Margin="550,236,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="48" FontFamily="Microsoft YaHei UI Light" Click="operater_Button_Click"/>
<Button x:Name="B_radical" Content="√" HorizontalAlignment="Left" Margin="10,331,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" FontFamily="Microsoft YaHei UI Light" Click="B_radical_Click"/>
<Button x:Name="B_7" Content="7" HorizontalAlignment="Left" Margin="145,331,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" Click="B_NUM_Click"/>
<Button x:Name="B_8" Content="8" HorizontalAlignment="Left" Margin="280,331,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" Click="B_NUM_Click"/>
<Button x:Name="B_9" Content="9" HorizontalAlignment="Left" Margin="415,331,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" Click="B_NUM_Click"/>
<Button Content="×" HorizontalAlignment="Left" Margin="550,331,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="48" FontFamily="Microsoft YaHei UI Light" Click="operater_Button_Click"/>
<Button x:Name="B_sq" Content="x²" HorizontalAlignment="Left" Margin="10,426,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" FontFamily="Microsoft YaHei UI Light" Click="B_sq_Click"/>
<Button x:Name="B_4" Content="4" HorizontalAlignment="Left" Margin="145,426,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" Click="B_NUM_Click"/>
<Button x:Name="B_5" Content="5" HorizontalAlignment="Left" Margin="280,426,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" Click="B_NUM_Click"/>
<Button x:Name="B_6" Content="6" HorizontalAlignment="Left" Margin="415,426,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" Click="B_NUM_Click"/>
<Button x:Name="B_sub" Content="-" HorizontalAlignment="Left" Margin="550,426,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="48" FontFamily="Microsoft YaHei UI Light" Click="operater_Button_Click"/>
<Button x:Name="B_cu" Content="x³" HorizontalAlignment="Left" Margin="10,521,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" FontFamily="Microsoft YaHei UI Light" Click="B_cu_Click"/>
<Button x:Name="B_1" Content="1" HorizontalAlignment="Left" Margin="145,521,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" Click="B_NUM_Click"/>
<Button x:Name="B_2" Content="2" HorizontalAlignment="Left" Margin="280,521,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" Click="B_NUM_Click"/>
<Button x:Name="B_3" Content="3" HorizontalAlignment="Left" Margin="415,521,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" Click="B_NUM_Click"/>
<Button Content="+" HorizontalAlignment="Left" Margin="550,521,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="48" FontFamily="Microsoft YaHei UI Light" Click="operater_Button_Click"/>
<Button x:Name="B_reciprocal" Content="1/x" HorizontalAlignment="Left" Margin="10,616,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="24" FontFamily="Microsoft YaHei UI Light" Click="B_reciprocal_Click"/>
<Button x:Name="B_opp" Content="±" HorizontalAlignment="Left" Margin="145,616,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" FontFamily="Microsoft YaHei UI Light" Click="B_opp_Click"/>
<Button x:Name="B_0" Content="0" HorizontalAlignment="Left" Margin="280,616,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" Click="B_NUM_Click"/>
<Button Content="." HorizontalAlignment="Left" Margin="415,616,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" FontFamily="Microsoft YaHei UI Light" Click="Button_Click_1"/>
<Button x:Name="B_eq" Content="=" HorizontalAlignment="Left" Margin="550,616,0,0" VerticalAlignment="Top"
Width="130" Height="90" FontSize="36" FontFamily="Microsoft YaHei UI Light" Click="B_eq_Click"/>
<TabControl Margin="700,0,0,0">
<TabItem>
<TabItem.Header >
历史记录
</TabItem.Header>
<Grid>
<ScrollViewer HorizontalScrollBarVisibility="Auto" Margin="0,0,0,25">
<StackPanel x:Name="historyPanel" >
</StackPanel>
</ScrollViewer>
<Button x:Name="clear_Btn" Height="8" Margin="0,650,0,0" Click="clear_Btn_Click">
全部清空
</Button>
</Grid>
</TabItem>
<TabItem Header="内存">
<!--Bind TextBlock.Text to the TextBox on the first TabItem.-->
<TextBlock Text="{Binding ElementName=textBox1, Path=Text}"/>
</TabItem>
</TabControl>
<!--
<Grid>
-->
<!-- Declare normal view content here -->
<!--
<Border CornerRadius="5" Background="White" BorderBrush="LightGray"
BorderThickness="1" Width="200" Height="100" Panel.ZIndex="10">
<Border.Effect>
<DropShadowEffect BlurRadius="10" Direction="270" ShadowDepth="7" Opacity="0.5"/>
</Border.Effect>
<TextBlock Text="I'm a fake Popup control" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</Grid> -->
</Grid>
</Controls:MetroWindow>
逻辑设计
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;
using MahApps.Metro.Controls;
using System.Windows.Controls.Primitives;
namespace Homework19
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : MetroWindow
{
public MainWindow()
{
InitializeComponent();
B_MC.IsEnabled = false;
B_M__1.IsEnabled = false;
B_M__.IsEnabled = false;
B_MR.IsEnabled = false;
}
//temp用于临时存储操作数,oper存储最近一次的运算符
private double temp, op1, op2, memory, result;
private string history=null,oper = null;
//next用来表示是否要输入新的操作数
private bool next;
//连续计算时先计算前面的结果
private void Aut()
{
op2 = Convert.ToDouble(Out_1.Text);
switch (oper)
{
case "+":
result = op1 + op2;
break;
case "-":
result = op1 - op2;
break;
case "×":
result = op1 * op2;
break;
case "÷":
result = op1 / op2;
break;
default:
break;
}
Out_1.Text = Convert.ToString(result);
//Out_2.Text = Convert.ToString(result);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//目标
this.contextMenu.PlacementTarget = this.btnMenu;
//位置
this.contextMenu.Placement = PlacementMode.Top;
//显示菜单
this.contextMenu.IsOpen = true;
}
private void B_NUM_Click(object sender, RoutedEventArgs e)
{
Button numBtn = sender as Button;
string numstr = numBtn.Content.ToString();
if (numstr != "0")
{
if (Out_1.Text == "0" || next)
{
Out_1.Text = numstr;
if (next)
{
next = false;
}
}
else
Out_1.Text += numstr;
}
else {
if (Out_1.Text != "0")
{
Out_1.Text += "0";
}
if (next)
{
Out_1.Text = "0";
next = false;
}
}
}
private void B_C_Click(object sender, RoutedEventArgs e)
{
Out_1.Text = "0";
Out_2.Text = "";
oper = null;
}
private void B_CE_Click(object sender, RoutedEventArgs e)
{
Out_1.Text = "0";
Out_2.Text = "";
oper = null;
}
private void operater_Button_Click(object sender, RoutedEventArgs e)
{
Button operaterBtn = sender as Button;
string operater = operaterBtn.Content.ToString();
Out_2.Text += Out_1.Text + operater;
if (oper != null)
{
Aut();
}
op1 = Convert.ToDouble(Out_1.Text);
oper = operater;
next = true;
}
private void B_delete_Click(object sender, RoutedEventArgs e)
{
if (!next)
{
if (Out_1.Text.Length == 1)
{
Out_1.Text = "0";
}
else
{
Out_1.Text = Out_1.Text.Substring(0, Out_1.Text.Length - 1);
}
}
}
private void B_reciprocal_Click(object sender, RoutedEventArgs e)
{
try
{
temp = Convert.ToDouble(Out_1.Text);
temp = 1 / temp;
Out_1.Text = Convert.ToString(temp);
}
catch (Exception ee)
{
Out_1.Text = "除数不能为0";
}
}
private void B_sq_Click(object sender, RoutedEventArgs e)
{
temp = Convert.ToDouble(Out_1.Text);
temp = Math.Pow(temp, 2);
Out_1.Text = Convert.ToString(temp);
}
private void B_cu_Click(object sender, RoutedEventArgs e)
{
temp = Convert.ToDouble(Out_1.Text);
temp = Math.Pow(temp, 3);
Out_1.Text = Convert.ToString(temp);
}
private void B_radical_Click(object sender, RoutedEventArgs e)
{
temp = Convert.ToDouble(Out_1.Text);
temp = Math.Pow(temp, 0.5);
Out_1.Text = Convert.ToString(temp);
}
private void B_per_Click(object sender, RoutedEventArgs e)
{
temp = Convert.ToDouble(Out_1.Text);
temp = temp / 100;
Out_1.Text = Convert.ToString(temp);
}
private void B_MR_Click(object sender, RoutedEventArgs e)
{
Out_1.Text = Convert.ToString(memory);
}
private void B_M__1_Click(object sender, RoutedEventArgs e)
{
memory += Convert.ToDouble(Out_1.Text);
}
private void B_M___Click(object sender, RoutedEventArgs e)
{
memory -= Convert.ToDouble(Out_1.Text);
}
private void B_MC_Click(object sender, RoutedEventArgs e)
{
memory = 0;
B_MC.IsEnabled = false;
B_M__1.IsEnabled = false;
B_M__.IsEnabled = false;
B_MR.IsEnabled = false;
}
private void B_MS_Click(object sender, RoutedEventArgs e)
{
memory = Convert.ToDouble(Out_1.Text);
B_MC.IsEnabled = true;
B_M__1.IsEnabled = true;
B_M__.IsEnabled = true;
B_MR.IsEnabled = true;
}
private void clear_Btn_Click(object sender, RoutedEventArgs e)
{
historyPanel.Children.Clear();
}
private void B_eq_Click(object sender, RoutedEventArgs e)
{
op2 = Convert.ToDouble(Out_1.Text);
switch (oper)
{
case "+":
result = op1 + op2;
break;
case "-":
result = op1 - op2;
break;
case "×":
result = op1 * op2;
break;
case "÷":
result = op1 / op2;
break;
default:
break;
}
oper = null;
history = Out_2.Text + Out_1.Text + "=";
Out_1.Text = Convert.ToString(result);
Out_2.Text = "";
Add_History(history, Convert.ToString(result));
}
private void B_opp_Click(object sender, RoutedEventArgs e)
{
temp = Convert.ToDouble(Out_1.Text);
if (temp != 0)
{
temp = 0 - temp;
}
Out_1.Text = Convert.ToString(temp);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Out_1.Text += ".";
}
private void Add_History(string cal, string result){
Border border = new Border();
border.CornerRadius = new CornerRadius(5);
border.Background = new SolidColorBrush(Colors.White);
border.BorderBrush = new SolidColorBrush(Colors.LightGray);
border.BorderThickness = new Thickness(1);
border.Height = 100;
Grid gird = new Grid();
TextBlock textBlock1 = new TextBlock();
textBlock1.HorizontalAlignment = HorizontalAlignment.Left;
textBlock1.Margin = new Thickness(10, 10, 0, 0);
textBlock1.TextWrapping = TextWrapping.Wrap;
textBlock1.Text = cal;
textBlock1.VerticalAlignment = VerticalAlignment .Top;
textBlock1.Width = 260;
textBlock1.Height = 28;
textBlock1.TextAlignment = TextAlignment.Right;
textBlock1.FontSize = 24;
TextBlock textBlock2 = new TextBlock();
textBlock2.HorizontalAlignment = HorizontalAlignment.Left;
textBlock2.Margin = new Thickness(10, 30, 0, 0);
textBlock2.TextWrapping = TextWrapping.Wrap;
textBlock2.Text = result;
textBlock2.VerticalAlignment = VerticalAlignment.Top;
textBlock2.Width = 260;
textBlock2.Height = 64;
textBlock2.TextAlignment = TextAlignment.Right;
textBlock2.FontSize = 54;
textBlock2.FontFamily = new FontFamily("Microsoft YaHei");
gird.Children.Add(textBlock1);
gird.Children.Add(textBlock2);
border.Child = gird;
historyPanel.Children.Add(border);
}
}
}
运行结果
参考项目
Windows 10 计算器 C++源代码
https://github.com/Microsoft/calculator
仿Windows 10 计算器 C#源代码
https://github.com/BuXianShan/Calculator
参考文章
https://blog.csdn.net/weixin_43272781/article/details/106750837
https://blog.csdn.net/qq_43479622/article/details/91599602
https://blog.csdn.net/OneWord233/article/details/80755284
https://www.cnblogs.com/lonelyxmas/p/12117453.html
https://blog.csdn.net/weixin_42009898/article/details/80921151