Загрузка данных
using System;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfCalculator
{
public partial class MainWindow : Window
{
// Переменные для хранения состояния вычислений
private double _currentValue = 0;
private string _currentOperator = "";
private bool _isNewInput = true; // Флаг, показывающий, что сейчас начнется ввод нового числа
private bool _isResultDisplayed = false; // Показывает, что на экране результат предыдущего вычисления
public MainWindow()
{
InitializeComponent();
InputBox.Focus();
}
// --- ОБРАБОТЧИКИ КНОПОК ---
// Обработка цифр (0-9)
private void DigitButton_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
string digit = button.Content.ToString();
// Если только что был результат (=) и не нажат оператор, сбрасываем для нового ввода
if (_isResultDisplayed && string.IsNullOrEmpty(_currentOperator))
{
InputBox.Text = "0";
_isResultDisplayed = false;
}
if (_isNewInput)
{
InputBox.Text = digit;
_isNewInput = false;
}
else
{
// Проверка на переполнение длины (опционально)
if (InputBox.Text.Length < 15)
{
// Убираем ведущий ноль, если он один
if (InputBox.Text == "0" && digit != ".")
InputBox.Text = digit;
else
InputBox.Text += digit;
}
}
_isResultDisplayed = false;
InputBox.Focus();
}
// Обработка десятичной точки
private void DecimalButton_Click(object sender, RoutedEventArgs e)
{
if (_isResultDisplayed && string.IsNullOrEmpty(_currentOperator))
{
InputBox.Text = "0";
_isResultDisplayed = false;
}
if (_isNewInput)
{
InputBox.Text = "0.";
_isNewInput = false;
}
else
{
if (!InputBox.Text.Contains("."))
InputBox.Text += ".";
}
_isResultDisplayed = false;
InputBox.Focus();
}
// Обработка операторов (+, -, *, /, ^)
private void OperatorButton_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
string op = button.Content.ToString();
// Если пользователь ввел число и сразу жмет оператор еще раз
if (!_isNewInput)
{
// Если есть предыдущий оператор, выполняем вычисление
if (!string.IsNullOrEmpty(_currentOperator))
{
PerformCalculation();
}
else
{
// Просто сохраняем текущее значение
_currentValue = double.Parse(InputBox.Text, CultureInfo.InvariantCulture);
}
}
// Если это был результат (=) и теперь нажали оператор
else if (_isResultDisplayed)
{
_currentValue = double.Parse(InputBox.Text, CultureInfo.InvariantCulture);
}
_currentOperator = op;
_isNewInput = true;
_isResultDisplayed = false;
InputBox.Focus();
}
// Обработка равно (=)
private void EqualsButton_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(_currentOperator) && !_isNewInput)
{
PerformCalculation();
_currentOperator = "";
_isNewInput = true;
_isResultDisplayed = true;
}
InputBox.Focus();
}
// Обработка очистки (C)
private void ClearButton_Click(object sender, RoutedEventArgs e)
{
InputBox.Text = "0";
_currentValue = 0;
_currentOperator = "";
_isNewInput = true;
_isResultDisplayed = false;
InputBox.Focus();
}
// --- ЛОГИКА ВЫЧИСЛЕНИЙ ---
private void PerformCalculation()
{
try
{
double newValue = double.Parse(InputBox.Text, CultureInfo.InvariantCulture);
double result = 0;
switch (_currentOperator)
{
case "+":
result = _currentValue + newValue;
break;
case "-":
result = _currentValue - newValue;
break;
case "*":
result = _currentValue * newValue;
break;
case "/":
if (Math.Abs(newValue) < 0.0000001)
{
MessageBox.Show("Деление на ноль невозможно.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
ClearButton_Click(null, null);
return;
}
result = _currentValue / newValue;
break;
case "^":
result = Math.Pow(_currentValue, newValue);
break;
}
InputBox.Text = result.ToString(CultureInfo.InvariantCulture);
_currentValue = result;
}
catch (Exception ex)
{
MessageBox.Show($"Ошибка вычисления: {ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
ClearButton_Click(null, null);
}
}
// --- ВАЛИДАЦИЯ ВВОДА С КЛАВИАТУРЫ ---
/// <summary>
/// Метод обработки ввода текста. Здесь мы разрешаем или запрещаем ввод символа.
/// </summary>
private void InputBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
// Разрешаем ввод только: цифр, одной точки, знака минус в начале
string newText = InputBox.Text.Insert(InputBox.SelectionStart, e.Text);
// Проверяем, является ли строка валидным числом (с учетом ввода минуса в начале)
// Используем флаг AllowDecimalPoint для проверки на ввод числа с плавающей точкой
bool isValid = double.TryParse(newText, NumberStyles.Any, CultureInfo.InvariantCulture, out _);
// Дополнительная проверка для случаев, когда ввод начинается с "-" или содержит только "-"
if (newText == "-" || (newText.StartsWith("-") && newText.Count(c => c == '-') == 1 &&
newText.Replace("-", "").All(c => char.IsDigit(c) || c == '.')))
{
isValid = true;
}
// Проверка на несколько точек
if (newText.Count(c => c == '.') > 1)
{
isValid = false;
}
// Проверка на несколько минусов
if (newText.Count(c => c == '-') > 1 || (newText.IndexOf('-') > 0))
{
isValid = false;
}
// Если ввод не валиден, отказываем (e.Handled = true)
e.Handled = !isValid;
// Сбрасываем флаг, так как пользователь что-то ввел руками
if (isValid)
{
_isNewInput = false;
_isResultDisplayed = false;
}
}
/// <summary>
/// Обработка нажатия клавиш (Enter, Backspace и т.д.)
/// </summary>
private void InputBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
EqualsButton_Click(null, null);
e.Handled = true;
}
else if (e.Key == Key.Escape)
{
ClearButton_Click(null, null);
e.Handled = true;
}
else if (e.Key == Key.Back || e.Key == Key.Delete)
{
// Разрешаем стирание
_isNewInput = false;
_isResultDisplayed = false;
}
// Цифровые клавиши с NumPad
else if (e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9)
{
string digit = ((int)(e.Key - Key.NumPad0)).ToString();
// Симулируем нажатие кнопки цифры
if (_isNewInput || InputBox.Text == "0")
InputBox.Text = digit;
else
InputBox.Text += digit;
_isNewInput = false;
_isResultDisplayed = false;
e.Handled = true;
}
// Операторы с NumPad
else if (e.Key == Key.Add)
{
OperatorButton_Click(new Button { Content = "+" }, null);
e.Handled = true;
}
else if (e.Key == Key.Subtract)
{
OperatorButton_Click(new Button { Content = "-" }, null);
e.Handled = true;
}
else if (e.Key == Key.Multiply)
{
OperatorButton_Click(new Button { Content = "*" }, null);
e.Handled = true;
}
else if (e.Key == Key.Divide)
{
OperatorButton_Click(new Button { Content = "/" }, null);
e.Handled = true;
}
else if (e.Key == Key.Decimal)
{
DecimalButton_Click(null, null);
e.Handled = true;
}
}
}
}