以下是一个使用 **C# Windows Forms(WinForms)** 编写的简易但功能完整的计算器程序,支持加、减、乘、除、小数点、正负号切换、百分号、清屏(C)、退格(←)、等号计算,以及基本的错误处理(如除零、溢出、表达式语法错误)。
✅ 特点:
- 纯 WinForms 设计(无 WPF / MAUI)
- 使用 `TextBox` 显示表达式和结果(只读),`Button` 实现按键
- 支持连续运算(如 `1+2*3=` → 7),符合四则运算优先级(通过 `DataTable.Compute` 简洁安全实现,也可替换为手写解析器)
- 响应式 UI(按钮自动布局,字体适中)
- 错误提示友好(如 `Error` 显示在文本框)
---
### ✅ 完整可运行代码(Form1.cs)
```csharp
using System;
using System.Drawing;
using System.Windows.Forms;
namespace SimpleCalculator
{
public partial class Form1 : Form
{
private TextBox displayBox;
private string currentInput = ""; // 当前显示的表达式(如 "12+3")
private bool isNewOperation = true; // 是否刚按过 = 或操作符,准备输入新数字
public Form1()
{
InitializeComponent();
SetupUI();
}
private void SetupUI()
{
this.Text = "简易计算器";
this.Size = new Size(320, 450);
this.StartPosition = FormStartPosition.CenterScreen;
this.Font = new Font("Microsoft YaHei", 12F);
// 显示框(只读,居右对齐)
displayBox = new TextBox
{
Location = new Point(10, 10),
Size = new Size(280, 50),
ReadOnly = true,
TextAlign = HorizontalAlignment.Right,
Font = new Font("Consolas", 16F, FontStyle.Bold),
Text = "0"
};
this.Controls.Add(displayBox);
// 按钮定义:(文本, 行, 列)
var buttons = new[]
{
("C", 0, 0), ("←", 0, 1), ("%", 0, 2), ("÷", 0, 3),
("7", 1, 0), ("8", 1, 1), ("9", 1, 2), ("×", 1, 3),
("4", 2, 0), ("5", 2, 1), ("6", 2, 2), ("−", 2, 3),
("1", 3, 0), ("2", 3, 1), ("3", 3, 2), ("+", 3, 3),
("±", 4, 0), ("0", 4, 1), (".", 4, 2), ("=", 4, 3)
};
int buttonWidth = 65, buttonHeight = 55;
for (int i = 0; i < buttons.Length; i++)
{
string text = buttons[i].Item1;
int row = buttons[i].Item2;
int col = buttons[i].Item3;
Button btn = new Button
{
Text = text,
Location = new Point(10 + col * buttonWidth, 70 + row * buttonHeight),
Size = new Size(buttonWidth, buttonHeight),
Font = new Font("Microsoft YaHei", 12F, FontStyle.Bold),
Tag = text // 存储原始符号,便于逻辑判断
};
// 统一点击事件
btn.Click += (s, e) => OnButtonClicked(text);
this.Controls.Add(btn);
}
}
private void OnButtonClicked(string key)
{
try
{
switch (key)
{
case "C":
currentInput = "";
displayBox.Text = "0";
isNewOperation = true;
break;
case "←":
if (!string.IsNullOrEmpty(currentInput))
{
currentInput = currentInput.Substring(0, currentInput.Length - 1);
displayBox.Text = string.IsNullOrEmpty(currentInput) ? "0" : currentInput;
}
break;
case "=":
if (!string.IsNullOrEmpty(currentInput))
{
// 替换符号为 C# 兼容格式
string expr = currentInput.Replace('×', '*').Replace('÷', '/').Replace('−', '-');
// 使用 DataTable.Compute 安全计算(自动处理优先级、类型转换)
var result = new System.Data.DataTable().Compute(expr, null);
if (result == null || double.IsInfinity(Convert.ToDouble(result)) || double.IsNaN(Convert.ToDouble(result)))
throw new Exception("Error");
// 格式化:去除末尾 .0,保留最多10位小数
string formatted = Convert.ToDouble(result).ToString("G15");
displayBox.Text = formatted;
currentInput = formatted;
isNewOperation = true;
}
break;
case "%":
if (!string.IsNullOrEmpty(currentInput))
{
if (double.TryParse(currentInput, out double val))
{
double percent = val / 100.0;
string res = percent.ToString("G15");
displayBox.Text = res;
currentInput = res;
isNewOperation = true;
}
}
break;
case "±":
if (!string.IsNullOrEmpty(currentInput))
{
if (double.TryParse(currentInput, out double val))
{
double negated = -val;
string res = negated.ToString("G15");
displayBox.Text = res;
currentInput = res;
isNewOperation = true;
}
}
break;
case "+":
case "−":
case "×":
case "÷":
// 连续操作符:替换最后一个操作符(如 "5+-" → "5-"; "5×+" → "5+")
if (!string.IsNullOrEmpty(currentInput))
{
char lastChar = currentInput[currentInput.Length - 1];
if (char.IsDigit(lastChar) || lastChar == '.' || lastChar == ')')
{
// 正常追加操作符
currentInput += GetOperatorSymbol(key);
}
else if ("+-×÷".Contains(lastChar))
{
// 替换末尾操作符
currentInput = currentInput.Substring(0, currentInput.Length - 1) + GetOperatorSymbol(key);
}
displayBox.Text = currentInput;
isNewOperation = false;
}
break;
default:
// 数字或小数点
if (char.IsDigit(key[0]) || key == ".")
{
if (isNewOperation)
{
currentInput = key == "." ? "0." : key;
isNewOperation = false;
}
else
{
// 防止多个小数点:检查当前数字段是否已含 '.'
if (key == ".")
{
// 找到最后一个操作符之后的部分(粗略处理,适合简单计算器)
int lastOpIndex = Math.Max(
currentInput.LastIndexOf('+'),
Math.Max(currentInput.LastIndexOf('−'),
Math.Max(currentInput.LastIndexOf('×'), currentInput.LastIndexOf('÷'))));
string lastNumber = lastOpIndex == -1 ? currentInput : currentInput.Substring(lastOpIndex + 1);
if (!lastNumber.Contains('.'))
currentInput += ".";
}
else
{
currentInput += key;
}
}
displayBox.Text = currentInput;
}
break;
}
}
catch (Exception ex) when (ex is DivideByZeroException || ex is ArgumentException || ex is OverflowException)
{
displayBox.Text = "Error";
currentInput = "";
isNewOperation = true;
}
}
// 将界面符号转为 C# 计算符号
private char GetOperatorSymbol(string op)
{
return op switch
{
"+" => '+',
"−" => '-', // 注意:这里是全角减号(UI用),但实际建议统一用 ASCII '-';本例中 UI 按钮用的是 ASCII 减号(见 buttons数组),所以此处仅为兼容说明
"×" => '*',
"÷" => '/',
_ => throw new NotSupportedException($"Unknown operator: {op}")
};
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
// 为元组语法兼容旧版 C#(若用 C# 7+ 可直接用 (string, int, int)[])
internal static class TupleExtensions
{
public static (string Item1, int Item2, int Item3) Item(this string s, int r, int c) => (s, r, c);
}
}
```
> 🔔 **注意**:上面代码中 `buttons` 数组使用了 C# 7+ 的 ValueTuple 语法 `(string, int, int)`。如果你使用的是 **C# 6 或更早版本**,请将 `("C", 0, 0)` 改为 `TupleExtensions.Item("C", 0, 0)`(已提供扩展方法),或改用 `new { Text="C", Row=0, Col=0 }` + `foreach`。
---
### 📌 关键设计说明:
| 模块 | 说明 |
|------|------|
| **显示逻辑** | `displayBox` 是只读 `TextBox`,始终显示 `currentInput`(表达式)或计算结果;避免直接操作 `Text` 引发闪烁/焦点问题 |
| **表达式计算** | 使用 `DataTable.Compute()` —— 它是 .NET 内置、线程安全、支持 `+ - * / ( )` 和优先级的轻量表达式求值器,比手写递归下降解析器更适合教学/简单计算器(⚠️生产环境如需高精度/自定义函数,建议用 NCalc 或 ExprLib) |
| **操作符替换** | UI 显示 `× ÷ −` 更美观,但计算时转为 `* / -`(ASCII) |
| **防错机制** | 捕获 `DivideByZeroException`, `OverflowException`, `ArgumentException`,统一显示 `"Error"` 并重置状态 |
| **小数点控制** | 仅允许每“一段数字”中出现一个 `.`(如 `1.2+3.4` 合法,`1..2` 不合法) |
| **连续运算** | 如输入 `5+3=` → 显示 `8`,再按 `×2=` → 自动变成 `8×2=` → `16`(因 `currentInput` 已更新为 `"8"`) |
---
### ✅ 如何运行?
1. 打开 **Visual Studio**(2019+ 推荐)→ 新建 **Windows Forms App (.NET Framework)** 或 **(.NET 5/6/7/8)** 项目
2. 删除默认生成的 `Form1.Designer.cs` 和 `Form1.cs` 内容
3. 将上方完整代码粘贴到 `Form1.cs` 中(确保命名空间与项目名一致)
4. 按 `Ctrl+F5` 运行(无需额外引用)
> 💡 提示:若目标框架是 `.NET Core/.NET 5+`,需确认项目 SDK 为 `<Project Sdk="Microsoft.NET.Sdk">` 且已安装 **Windows Desktop workload**(VS 安装时勾选 “.NET desktop development”)。
---
### 🧩 可拓展方向(进阶建议):
- ✅ 添加括号支持 `(` / `)`(`DataTable.Compute` 原生支持)
- ✅ 历史记录面板(`ListBox` 显示 `5+3=8` 等)
- ✅ 键盘事件支持(`KeyPress` 响应 `0-9`, `Enter`, `Backspace`, `+`, `-`, `*`, `/`, `.`)
- ✅ 主题切换(亮色/暗色模式)
- ✅ 科学计算(sin/cos/log/π/^)→ 需替换为 `NCalc` 或 `mXparser`
---