Калькулятор
Windows Forms на
языке
C#
Оригинал: http://vscode.ru/prog—lessons/kalkulyator—windows—forms—c—shapr.html
Мы создадим более усовершенствованный калькулятор Windows Forms.Итак, выглядеть у нас
он будет вот так:
Здесь у нас 19 кнопок Button, 1 Textbox и ещё 1
пустой Label (на рисунке он выделен). Применение его будет описано ниже. Итак, создаём
такую или похожую форму. Мы увеличили ширину TextBox’a, используяMultiLine:
Также в Свойствах мы увеличили размер шрифта в
TextBox’e и Label’e до 12 пт.
Теперь делаем так, чтобы при нажатии на цифровые
кнопки, в TextBox’e появлялась соответствующая цифра.
Для этого дважды кликаем на кнопке “0” и в
открывшемся коде пишем:
private void button17_Click(object
sender, EventArgs e)
{
textBox1.Text =
textBox1.Text + 0; }
Проверяем, несколько раз нажав на кнопку “0” у нас в
форме.
Работает. Делаем то же самое с остальными цифровыми
кнопками:
private void button13_Click(object
sender, EventArgs e)
{
textBox1.Text =
textBox1.Text + 1;
}
private void button14_Click(object
sender, EventArgs e)
{
textBox1.Text =
textBox1.Text + 2;
}
private void button15_Click(object
sender, EventArgs e)
{
textBox1.Text =
textBox1.Text + 3;
}
private void button9_Click(object
sender, EventArgs e)
{
textBox1.Text =
textBox1.Text + 4;
}
private void button10_Click(object
sender, EventArgs e)
{
textBox1.Text =
textBox1.Text + 5;
}
private void button11_Click(object
sender, EventArgs e)
{
textBox1.Text =
textBox1.Text + 6;
}
private void button5_Click(object
sender, EventArgs e)
{
textBox1.Text =
textBox1.Text + 7;
}
private void button6_Click(object
sender, EventArgs e)
{
textBox1.Text =
textBox1.Text + 8;
}
private void button7_Click(object
sender, EventArgs e)
{
textBox1.Text =
textBox1.Text + 9; }
Таким же образом кликаем дважды на кнопку “.” в
форме. Она будет использоваться для создания десятичной дроби. Пишем следующий
код:
private void button18_Click(object
sender, EventArgs e)
{
textBox1.Text =
textBox1.Text + «,»;
}
Кнопки нажимаются, в TextBox’e
отображаются нажатые цифры. Теперь надо научить программу производить с ними
какие-либо операции. Как видно из формы, наш калькулятор сможет производить
стандартные математические операции: сложение, вычитание, умножение и деление.
Для начала мы создадим в самом начале программы несколько переменных, которые
нам для этого понадобятся:
float a, b; int count; bool znak =
true;
Первым двум переменным будут
присваиваться значения, набранные пользователем в калькуляторе. В последствии с ними будут
производиться нужные математические операции. Тип float – это тип с плавающей точкой,
позволяющий работать с десятичными дробями, что нам, безусловно, нужно
при наличии кнопки “.” . Благодаря второй переменной мы будем давать программе
указания, какую именно операцию производить с переменными, описанными выше.
Здесь нам не нужна дробь, поэтому обойдёмся целочисленным типом int.
Последняя переменная znak нам понадобится для того,
чтобы менять знаки у введённых чисел. Тип bool может иметь два значения – ture
и false. Мы представим, что если znakимеет значение true в программе, то это
означает, что у числа знак +, если false – число отрицательное и перед собой
имеет знак -. Изначально в калькуляторе вбиваются положительные числа, поэтому
мы сразу присвоили переменной значение true. Далее мы дважды нажимаем на кнопку
“+”, обозначающую сложение, на форме и пишем следующий код:
private void button4_Click(object
sender, EventArgs e)
{
a = float.Parse(textBox1.Text);
textBox1.Clear(); count = 1;
label1.Text =
a.ToString() + «+»; znak = true; }
В строке 3 мы присваиваем первой переменной a то, что
будет написано в TextBox’e (а именно число, которое введёт пользователь перед
тем, как нажать кнопку “+”).
Затем TextBox очищается, число, введённое
пользователем, в нём пропадает (но остаётся в переменной a) Переменной count
присваивается число 1, которая потом укажет программе, что именно операцию
сложения надо будет произвести с числами. Затем в Label записывается число из
переменной a (то самое, которое изначально ввёл пользователь) и знак плюса.
Выглядеть в форме это будет так, как описано ниже. Пользователь вводит
какое-либо число:
Затем нажимает на кнопку “+” и после этого видит:
Кроме того, как бы не было странным с первого
взгляда, мы присваиваем переменнойznak значение true, хотя выше, в начале кода,
мы и так присваивали это же значение. Подробнее данную переменную мы опишем
ниже, но смысл в том, что мы присваиваем значение true, когда хотим сделать
введённое число отрицательным, если оно положительно, а значение false, когда
хотим сделать число положительным, если оно отрицательное. Изначально у нас
вводятся положительные числа, сначала первое, потом второе. И если первое число
мы сделаем отрицательным, то значение у znakперейдёт в false и тогда получится,
что второе слагаемое как бы отрицательное (на практике, просто чтобы поставить
перед ним минус, придётся нажать дважды на соответствующую кнопку, чтобы с
false значение перешло в true, а затем обратно с trueв false, и появился знак
минуса).
Подобным образом заполняем код для кнопок “-“, “*” и
“/”:
private void button8_Click(object
sender, EventArgs e)
{
a =
float.Parse(textBox1.Text); textBox1.Clear(); count =
2;
label1.Text =
a.ToString() + «-«;
znak = true;
}
private void button12_Click(object
sender, EventArgs e)
{
a =
float.Parse(textBox1.Text);
textBox1.Clear(); count = 3;
label1.Text =
a.ToString() + «*»;
znak = true;
}
private void button16_Click(object
sender, EventArgs e)
{
a =
float.Parse(textBox1.Text); textBox1.Clear(); count =
4;
label1.Text =
a.ToString() + «/»; znak = true;
}
Разница лишь в значении переменной count и в том,
какой знак добавляется в Label’e.
Далее нам понадобится создать функцию, которая будет
применять нужные нам математические операции к числам. Назовём её calculate. Но
перед этим мы кликнем дважды на кнопку “=” на форме и в коде к ней мы запишем:
private void button19_Click(object
sender, EventArgs e)
{
calculate(); label1.Text = «»; }
То есть, при нажатии пользователем на кнопку “=”, как
раз выполнится наша функция подсчёта calculate, и, заодно, очистится Label, так
как результат мы в будущем коде выведем в TextBox. Теперь-таки создаём нашу
функцию calculate и пишем следующий код:
private void calculate()
{
switch(count) { case 1:
b = a +
float.Parse(textBox1.Text); textBox1.Text = b.ToString();
break; case 2: b = a —
float.Parse(textBox1.Text); textBox1.Text =
b.ToString(); break; case
3: b = a * float.Parse(textBox1.Text);
textBox1.Text = b.ToString(); break; case
4:
b = a /
float.Parse(textBox1.Text); textBox1.Text = b.ToString();
break; default: break;
}
}
Здесь мы используем конструкцию switch-case.
Switch –
это оператор управления. Он может включать в себя несколько case’ов. Case – метки,
от значения которых зависит, какие операции будут
происходить. Строка switch(count) означает, что именно от значения count будет
зависеть, какое действие будет происходить в коде switch’a. Итак, если count=1
(в коде case 1:), то произойдёт следующее:
После того, как пользователь нажал “+”, он,
естественно, должен ввести второе слагаемое, что он и делает по стандартному
сценарию, а затем нажать кнопку “=” (и в ней, как мы помним, как раз выполнится
наша функция).
Как
только кнопка “=” будет нажата, программа сложит число из переменной a с тем
вторым слагаемым, которое записал пользователь в TextBox, и запишет результат в
переменную b (строка 6 кода функции). В строке 7
программа выведет в TextBoxрезультат сложения – переменную b.
Оператор break (строка завершает исполнение кода
switch при выполнении кода метки case 1, так как больше нам в нём делать
нечего.
Точно так же строится алгоритм при case 2, case 3 и
case 4 с той разницей, что в них происходит не сложение, а вычитание, умножение
и деление соответственно.
Оператор default срабатывает, если вдруг что-то
пойдёт не по плану и count примет какое-либо иное значение, не описанное в
switch. Тогда срабатывает лишь операторbreak. Львиная доля программы готова.
Нам надо лишь написать код для трёх оставшихся нетронутыми до этого время
кнопок. Дважды жмём в форме на кнопку “С”. Она будет очищать все записи из
TextBox’a иLabel’a. Код у неё элементарный:
private void button3_Click(object
sender, EventArgs e)
{
textBox1.Text =
«»; label1.Text = «»; }
На очереди у нас кнопка “<–“. Она будет удалять
последнюю цифру записанного вTextBox’e числа. Код:
private void button2_Click(object
sender, EventArgs e)
{
int lenght =
textBox1.Text.Length — 1; string text = textBox1.Text;
textBox1.Clear();
for (int i = 0; i <
lenght; i++)
{
textBox1.Text =
textBox1.Text + text[i];
}
}
Мы вводим новую переменную lenght целочисленного типа
и записываем в неё количество символов в TextBox’e минус один символ. Также мы
вводим новую переменную text, в которую полностью заносим текст из TextBox’а.
Затем мы очищаем TextBox и вводим цикл for, через который записываем в TextBox
строку text, но уже на символ короче. Например, в TextBox’e записано число
504523 При нажатии на кнопку “<–“ в переменную lenght записывается число 5
(6 цифр – 1), в переменную text записывается строка “504523”, TextBox
очищается, а затем в него по одному записываются символы из text, но в этот раз
их будет не 6, а 5, то есть вTextBox’e появится число 50452. У нас остаётся
последняя кнопка, которая отвечает за знак первого слагаемого. Переходим к её
коду. Тут мы будет работать с переменной znak, которую описывали выше. Код
выглядит вот так:
private void button1_Click(object
sender, EventArgs e)
{
if(znak==true)
{
textBox1.Text =
«-» + textBox1.Text;
znak = false;
}
else if
(znak==false)
{
textBox1.Text=textBox1.Text.Replace(«-«,
«»); znak = true;
}
Изначально, как мы помним, у переменной znak стоит значение true. Если
мы нажмём на кнопку первый раз, то в TextBox’e перед числом появится знак
“-“, а переменной znakбудет присвоено значение false.
Если второй раз нажать на данную кнопку, то, так как znak у нас false,
произойдёт второе условие. Здесь используется метод Replace, который заменяет
какой-либо кусок строки на другой. В скобках после метода вначале пишется, что
будет заменено в строке, а после запятой, то, на что заменять. В данном случае мы заменяем
в TextBox’e минус на пустое значение.
Вот и всё, наш калькулятор Windows Forms готов! Можно его
тестировать!
Для создания приложения Windows Forms в Visual Studio 2019:
Лабораторная работа 1.
Элемент управления TextBox (текстовое поле)
Выполнить: Разработайте приложение, которое вычисляет сумму трех любых чисел при нажатии на кнопку.
Целью работы является знакомство с элементами управления visual c# textbox
и button
— текстовое поле и кнопка.
Пример выполнения:
[Название проекта: Lab1
, название файла формы frmSumma.cs
]
✍ Алгоритм:
-
Инструментарий:
объект | свойство name | свойство text |
---|---|---|
форма | Вычисление суммы | |
кнопка (button) | btnExit | Выход |
текстовое поле (textbox) | txtA | 0 |
текстовое поле (textbox) | txtB | 0 |
текстовое поле (textbox) | txtC | 0 |
текстовое поле (textbox) | txtSumma | 0 |
кнопка (button) | btnCount | Вычислить |
- Внимание! Называйте все объекты согласно правилам именования объектов, принятых в C#. В скобках будет указан возможный вариант для имени создаваемого объекта.
- Создайте новый проект (C# → Windows → Все типы проектов → Приложение Windows Forms (.Net Framework)), назовите проект Урок 4 Лаб 4, а его форму — frmSumma (окно Свойства → свойство (Name)).
- Создайте и запрограммируйте на форме кнопку Выход (btnExit). Для этого в окне Toolbox разверните свиток All Windows Forms и дважды щелкните по элементу button. На форме появилась кнопка. Для того, чтобы запрограммировать кнопку, дважды щелкните по ней на форме — открылась новая вкладка с кодом для кнопки. Введите код:
- Запустите приложение и убедитесь, что кнопка работает.
- Верните во вкладку с дизайном формы. Создайте три элемента управления Textbox (txtA, txtB, txtC) для слагаемых. Задайте свойство Text для этих элементов управления, равное 0 (в окне Properties → Text).
- Создайте еще один элемент управления TextBox (txtSumma) (размеры и расположение кнопок см. выше рис «форма Вычисление_суммы»).
- Создайте кнопку Вычислить (btnCount).
- Запрограммируйте событие Click для кнопки Вычислить следующим образом (дважды щелкните по кнопке на форме, чтобы запрограммировать событие):
- Задайте надписи для кнопок («Вычислить» и «Выход»), изменив их свойство Text.
- Запустите приложение, введите значения для слагаемых и посмотрите, что произойдет, если Вы нажмете на кнопку Вычислить.
- Сохраните проект. Найдите на компьютере папку с проектом. Загрузите в moodle два файла: 1) файл
frmSumma.cs
2) В папке bin → Debug файл с расширением.exe
. Либо загрузите архив всей папки с проектом.
private void btnExit_Click(object sender, EventArgs e) { this.Close(); // эта строка - ваш введенный код }
private void btnCount_Click(object sender, EventArgs e) { // здесь начинается ваш код int summa = Int32.Parse(txtA.Text) + Int32.Parse(txtB.Text) + Int32.Parse(txtC.Text); txtSumma.Text = summa.ToString(); // здесь ваш код закончился }
где Parse – функция преобразования строкового значение в целое число;
Контрольное задание. Разработайте приложение, которое вычисляет:
- площадь треугольника по трем сторонам;
- площадь прямоугольника по двум сторонам;
- площадь треугольника по двум сторонам и углу между ними;
- процент от числа.
[Название проекта: Lesson_4ExTask0
, название формы L4ExTask0.cs
]
Лабораторная работа 2.
Элемент управления ListBox (список), свойства и методы списка, программирование с ветвлением
Измените свойство Backcolor (Задний фон) текстового поля при помощи элемента управления ListBox – список
Целью работы является ознакомление с элементом управления в visual c# Listbox
. Изучаются свойства добавления и удаления пунктов списка listbox. Вводится понятие программирования с ветвлением.
Пример выполнения:
[Название проекта: Lab2
, название файла формы Lab2.cs
]
✍ Алгоритм:
Инструментарий:
объект | свойство name | свойство text |
---|---|---|
форма | ||
кнопка (button) | btnExit | Выход |
текстовое поле (textbox) | txt | |
список (ListBox) | lst |
- Поместите на новую форму текстовое поле TextBox c именем txt и элемент управления Список ListBox . Назовите его lst (свойство Name).
- На панели свойств элемента управления ListBox выберите свойство (атрибут) Items и задайте для него четыре пункта списка (нажимая на Enter после каждого пункта): черный, красный, синий, зеленый.
- Теперь запрограммируйте событие SelectedIndexChanged (изменение пункта списка) для списка, таким образом, чтобы при нажатии на определенный пункт c цветом, цвет текстового поля менялся бы на соответствующий. Используйте при этом оператор Visual c# If:
- Все работает, но теперь мы рассмотрим второй способ задания пунктов списка: с помощью программного кода.
- Удалите все цвета из атрибута Items элемента управления lst. Теперь необходимо добавить в обработку события Load формы (загрузка формы) следующий код (дважды щелкните на пустом месте дизайна формы, чтобы открыть код):
- Запустите и отладьте программу.
private void lst_SelectedIndexChanged(object sender, EventArgs e) { // ваш код: if (lst.SelectedItem == "black") { txt.BackColor = System.Drawing.Color.Black; } else if (lst.SelectedItem == "red") { txt.BackColor = System.Drawing.Color.Red; } else if (lst.SelectedItem == "blue") { txt.BackColor = System.Drawing.Color.Blue; } else if (lst.SelectedItem == "green") { txt.BackColor = System.Drawing.Color.Green; } // здесь ваш код закончился }
System – пространство имен;
Drawing — пространство имен, обеспечивающее доступ к функциональным возможностям графического интерфейса
Событие SelectedIndexChanged происходит при выделении различных пунктов в элементе управления списка данных между отправками к серверу.
private void Form1_Load(object sender, EventArgs e) { // ваш код: lst.Items.Add("black"); // ... добавьте другие цвета }
Контрольное задание.
Добавьте ListBox для изменения ширины (атрибут Width
) текстового поля: минимальная — 20, средняя – 50, максимальная — 100.
Примечание: использовать свойство текстового поля Size
, и System.Drawing.Size(значение ширины, значение высоты)
[Название проекта: ExTaskLab2
, название формы ExTaskLab2.cs
]
Лабораторная работа 3.
Разработайте приложение, которое изменяет задний фон текстового поля из предыдущего занятия, реализовав эту функцию с помощью меню формы
Целью данного урока является ознакомление с элементом управления MenuStrip
при работе в visual c++ с формами.
Пример выполнения:
[Название проекта: Lab3
, название файла формы Lab3.cs
]
✍ Алгоритм:
Инструментарий:
объект | свойство name |
---|---|
форма | |
меню формы (MenuStrip) | MenuStrip1 |
- Для создания меню на панели инструментов выберите MenuStrip . Дважды кликните на появившемся в нижней области окна объекте, а затем перейдите на форму и в области (Вводить здесь) введите меню верхнего уровня с текстом Цвет.
- Переместитесь на нижнюю область и введите текст Черный. Заполните элемент MenuStrip следующим образом:
- Запустите программу и поэкспериментируйте: выбирайте разные элементы созданного объекта.
- Запрограммируйте событие Click для каждого пункта; например, для элемента Черный необходимо написать следующий код (дважды щелкнув на пункте, чтобы открыть код):
private void ЧерныйToolStripMenuItem_Click(object sender, EventArgs e) { this.txt.BackColor=System.Drawing.Color.Black; }
- Запрограммируйте аналогично остальные пункты Цвет.
- Запустите и отладьте приложение. Сохраните проект.
Дополнительное задание:
- При выборе какого-либо пункта сделайте его недоступным для повторного выбора (свойство Enabled=false).
- Выполните дополнительное задание из занятия № 1, реализовав функцию с помощью MenuStrip.
Вопросы для самоконтроля:
- Каково основное назначение объекта MenuStrip?
- Как запрограммировать необходимый пункт меню формы в Visual c++?
- Какое свойство служит для изменения фона объекта?
- С помощью какого свойства menu можно сделать недоступным какой-либо пункт?
Provide feedback
Saved searches
Use saved searches to filter your results more quickly
Sign up
Решаем типовые задачи на C# с помощью Windows Forms
В последнее время здесь был ряд заметок по работе с приложениями Windows Forms на C#, все вместе их можно рассматривать как набросок небольшого курса вроде «Технологии программирования, часть 1», изучаемого, когда «Языки программирования» в лице основ C++ и C# уже «пройдены»:
1. Введение и основы Windows Forms
2. Взаимодействие форм. MDI-приложения
3. Работа со строками и списочными компонентами
4. Табличные компоненты и работа с ними
5. Графика (отрисовка, работа с изображениями)
6. Графика (работа с Chart-компонентами и анимация в .NET)
7. Интеграция с офисными приложениями
В этой заметке мы обобщаем, «чему должны были научиться» и приводим ряд типовых задач, которые имеет смысл ставить перед неофитами при контроле знаний.
В настоящее время нами освоены следующие возможности библиотеки .NET:
- управление приложением и компонентами с помощью событий и свойств;
- создание прикладных приложений и вычислительная обработка данных на основе базовых компонент (Panel, Button, Label, TextBox);
- списочные и табличные компоненты, обработка информации с их помощью (ListView, ListBox, ComboBox, DataGridView, DataGrid);
- работа с графической канвой и таймером, управление отображением и перемещением графических объектов (PictureBox, Graphics, Timer);
- работа с текстовыми и структурированными файлами средствами .NET;
- динамическое создание/удаление компонентов, управление дочерними объектами.
Как правило, в зачётной или экзаменационной работе по подобному курсу задач на «конкретные компоненты» нет (если тип компоненты отдельно не оговорен в условии), а задача состоит в том, чтобы написать работающее приложение согласно поставленному условию и с применением компонент, которые кажутся вам наиболее подходящими для этой цели.
Проект Ex8_1. Реализовать отсортированный по алфавиту список имён с поддержкой операций добавления и удаления элементов, сохранением списка строк в файл и загрузкой его из файла. Допустимые символы в именах – буквы и цифры.
Задачу можно решать как на основе списочных, так и табличных компонент. Поскольку требуется сортировка данных, удобнее решать на основе какого-либо списка, имеющего встроенное свойство Sorted. Форма будет иметь следующий вид:
Повторите, какие свойства формы вы поменяли, чтобы получить такой вид окна?
Справа расположена panel1
со свойством Dock = Right
, на ней 4 кнопки button1
, …, button4
для выполнения предусмотренных задачей действий. Слева – список comboBox1
со свойством Dock = Fill
.
По загрузке формы настроим список для нашей задачи:
private void Form1_Load (object sender, EventArgs e) { comboBox1.Sorted = true; //список будет сортироваться comboBox1.DropDownStyle = ComboBoxStyle.Simple; //развёрнутый вид списка }
Кнопка 1 будет добавлять запись, если такой же записи ещё нет в списке:
private void button1_Click (object sender, EventArgs e) { String r = comboBox1.Text; if (comboBox1.FindString (r) == -1) comboBox1.Items.Add (r); }
Кнопка 2 будет удалять выбранный в списке элемент, если таковой есть:
private void button2_Click (object sender, EventArgs e) { if (comboBox1.SelectedIndex != -1) comboBox1.Items.Remove (comboBox1.SelectedItem); }
Кнопка 3 выполнит работу по сохранению файла с использованием поточного класса StreamWriter
. Для простоты используем файл с фиксированным именем data.txt
, располагающийся в текущей папке.
private void button3_Click (object sender, EventArgs e) { try { System.IO.StreamWriter file = new System.IO.StreamWriter ("data.txt"); for (int i = 0; i < comboBox1.Items.Count; i++) file.WriteLine (comboBox1.Items [i].ToString ()); file.Close (); } catch (Exception) { MessageBox.Show ("Не могу записать data.txt"); } }
Кнопка 4 отвечает за загрузку элементов списка из файла data.txt
. Чтобы можно было закрыть дескриптор файла после чтения данных, применим поточный класс StreamReader
:
private void button4_Click (object sender, EventArgs e) { try { System.IO.StreamReader file = new System.IO.StreamReader ("data.txt"); String line; comboBox1.Items.Clear (); while (( line = file.ReadLine () ) != null) comboBox1.Items.Add (line); file.Close (); } catch (Exception) { MessageBox.Show ("Не могу открыть data.txt"); } }
Осталось обеспечить ввод только разрешённых символов, для этого достаточно добавить обработчик события KeyPress
(там доступно свойство KeyChar
, в отличие от KeyCode
в обработчике события KeyDown
) для списка comboBox1
:
private void comboBox1_KeyPress (object sender, KeyPressEventArgs e) { char c = e.KeyChar; if (Char.IsLetterOrDigit (c) || c == (char) Keys.Back || c == (char) Keys.Enter) return; else e.Handled = true; }
Задача решена полностью.
Скачать пример Ex8_1 в архиве .zip с проектом C# Visual Studio 2019 (11 Кб)
Проект Ex8_2. На графической канве отобразить работу светофора с задержкой между состояниями «красный-жёлтый-зелёный» 1 сек.
Форма – пустое окно Windows Forms.
Для решения задачи используем канву формы и программно созданный таймер.
Опишем таймер, счётчик состояний и размер элемента светофора в классе формы:
private Timer timer1; private int cnt; private const int size = 120; //ширина и высота окружностей
По событию загрузки формы (Load
) настроим размеры окна и инициализируем таймер:
private void Form1_Load (object sender, EventArgs e) { this.ClientSize = new System.Drawing.Size (size, size*3); this.DoubleBuffered = true; timer1 = new Timer (); timer1.Interval = 1000; timer1.Tick += (sendr, args) => { Invalidate (); cnt = ( cnt + 1 ) % 3; }; timer1.Enabled = true; cnt = 0; }
Обработчик события Tick
таймера мы встроили в оператор назначения как стрелочную функцию. Обратите внимание, что этот обработчик таймера только вызывает перерисовку формы (вызов Invalidate()
, отправляющий сообщение стандартному методу пререрисовки Paint()
) и меняет счётчик состояний cnt
, а саму отрисовку будет делать метод Paint
:
private void Form1_Paint (object sender, PaintEventArgs e) { Pen [] pens = new Pen [] { Pens.Red, Pens.Yellow, Pens.Green }; for (int i = 0; i < 3; i++) e.Graphics.DrawEllipse (pens [i], 0, i * size, size, size); //контуры 3 кружков Brush [] brushes = new Brush [] { Brushes.Red, Brushes.Yellow, Brushes.Green }; e.Graphics.FillEllipse (brushes [cnt], 0, cnt * size, size, size); //текущий закрасить }
Для простоты непосредственно в функции описаны массивы перьев Pen
и кистей Brush
нужных цветов. Но лучше вынести эти массивы тоже в свойства класса, а создать их один раз в конструкторе формы.
Альтернативный подход (без привязки к методу Paint
) – в обработчике события таймера программно создавать Bitmap
нужной размерности, выполнять отрисовку на нём, а затем назначать его компоненте PictureBox
.
Задача решена полностью.
Скачать пример Ex8_2 в архиве .zip с проектом C# Visual Studio 2019 (11 Кб)
Проект Ex8_3. Поддержка динамического списка компонент TextBox произвольной размерности. Реализовать добавление и удаление компонент.
Форма – пустая Windows Forms. В качестве примера будем создавать поля ввода TextBox
в месте щелчка мышью по форме и удалять их при щелчке мышью на самих полях.
Нам не понадобится отдельно сохранять поля ввода в каком-либо списке, хотя мы могли бы сделать это, например, так:
using System.Collections.Generic; //... List <TextBox> F; //динамический список System.Collections.Generic.List объектов типа TextBox //... F = new List <TextBox>(); //конструктор списка //... F.Add (T); //где T - созданный TextBox
Дело в том, что у формы уже есть контейнер Controls
с методами Add
и Remove
.
В классе формы дополнительно опишем только счётчик контролов:
int cnt; //счётчик объектов
Инициализируем счётчик в конструкторе формы:
public Form1 () { InitializeComponent (); cnt = 0; }
Щелчку по форме мышью соответствует событие MouseClick
. Достаточно в обработчике этого события формы создать программно новый TextBox
и добавить его в список компонент формы:
private void Form1_MouseClick (object sender, MouseEventArgs e) { TextBox T = new TextBox (); T.Text = "Text" + ( cnt++ ); T.Location = new Point (e.X, e.Y); T.Parent = this; this.Controls.Add (T); }
Длина списка не ограничена. Однако если мы хотим удалять компоненты TextBox
по какому-то событию, например, по щелчку на них, придётся всем создаваемым TextBox
программно назначать обработчик этого события, так что вставим соответствующий код в метод Form1_MouseClick
(перед добавлением поля ввода в список контролов):
T.Click += (sendr, args) => { this.Controls.Remove ((TextBox)sendr); };
Задача решена полностью.
Альтернативным, но избыточным решением, как сказано выше, были бы статические или динамические массивы компонент.
Скачать пример Ex8_3 в архиве .zip с проектом C# Visual Studio 2019 (10 Кб)
Проект Ex8_4. Реализовать простейшее движение объекта («героя») по форме (двумерному «лабиринту»). Лабиринт состоит из отдельных полей, среди которых есть проходимые и не проходимые.
Сделаем всё максимально просто согласно условию задачи.
Нам понадобится растянутый на всю клиентскую часть формы PictureBox
(свойство Dock = Fill
) и таймер, у которого установлены свойства Enabled = true
и Interval = 200
.
В классе формы опишем нужные данные:
public const int width = 10, height = 10, k = 16; //размеры игровой доски и одного поля public int [,] field = new int [width, height]; //сама игровая доска public int [] hero = new int [] { 1, 1}; //координаты героя public Bitmap bitfield = new Bitmap (k * width, k * height ); //битмап для отрисовки public Graphics gr; //графический контекст
Массив в C# автоматически инициализируется нулями, поэтому достаточно выставить в значение «1» те элементы массива поля, которые соответствуют «стенам». Сделаем это в конструкторе формы, там же установим размер окна и получим графический контекст:
public Form1 () { InitializeComponent (); //установим размер окна и получим графический контекст: this.ClientSize = new Size (k * width, k * height); gr = Graphics.FromImage (bitfield); //выставим все крайние поля в единицы: for (int i = 0; i < width; i++) { field [i, 0] = 1; field [i, height - 1] = 1; } for (int i = 0; i < height; i++) { field [0, i] = 1; field [width - 1, i] = 1; } //выставьте и некоторые другие поля в единицы... }
Обработчик нажатия клавиши формы будет получать текущее положение героя и менять его, если этому не мешают препятствия (в нашем случае — «стены»):
private void Form1_KeyDown (object sender, KeyEventArgs e) { //обрабатываем нажатия клавиш со стрелками int x = hero [0], y = hero [1]; switch (e.KeyCode) { case Keys.Left: if (x > 0 && field [x - 1, y] == 0) x--; break; case Keys.Right: if (x < width - 1 && field [x + 1, y] == 0) x++; break; case Keys.Up: if (y > 0 && field [x, y-1] == 0) y--; break; case Keys.Down: if (x < height - 1 && field [x , y+1] == 0) y++; break; } hero[0] = x; hero [1] = y; }
Обработчик события таймера будет просто запрашивать отрисовку, которую мы, на случай развития приложения, вынесем в отдельный метод DrawMe
:
private void TickTimer_Tick (object sender, EventArgs e) { //по таймеру просто запрашиваем отрисовку DrawMe (); } public void DrawMe () { //метод для отрисовки поля и героя gr.Clear (Color.Black); for (int i = 0; i < width; i++) for (int j = 0; j < height; j++) if (field [i, j] == 1) { gr.FillRectangle (Brushes.Green, i * k, j * k, k, k); gr.DrawRectangle (Pens.Black, i * k, j * k, k, k); } gr.FillEllipse (Brushes.Red, hero[0] * k, hero [1] * k, k, k); pictureBox1.Image = bitfield; }
Задача решена полностью, вот что вышло:
вид приложения, стены — только по краям поля
Скачать пример Ex8_4 в архиве .zip с проектом C# Visual Studio 2019 (11 Кб)
13.05.2023, 10:04 [2936 просмотров]
К этой статье пока нет комментариев, Ваш будет первым