Какое событие класса control отвечает за изменение элемента
Перейти к содержимому

Какое событие класса control отвечает за изменение элемента

  • автор:

Элемент Control в WinRT

Ранее я обозначил различие между классами, производными от FrameworkElement, и классами, производными от Control. Первые (например, TextBlock и Image) я называл «элементами», чтобы сохранить разделение этих двух категорий но сейчас требуется более глубокое объяснение.

Именно класс UIElement определяет все события пользовательского ввода от сенсорною экрана, мыши, пера и клавиатуры; это означает, что не только элементы управления, но и обычные элементы могут взаимодействовать с пользователем самым нетривиальным образом.

С другой стороны, элементы не обделены средствами формирования макета, применения стилей или привязки данных. Класс FrameworkElement определяет такие макетные свойства, как Width, Height, HorizontalAlignment, VerticalAlignment и Margin, а также свойство Style и метод SetBinding.

Особенности Control

С точки зрения визуальной и функциональной классы, производные от FrameworkElement, представляет собой примитивы (атомы, если можно так выразиться), тогда как классы, производные от Control, представляют собой результат компоновки этих примитивов (молекулы в нашей аналогии). Объект Button обычно строится из Border и TextBlock; объект Slider состоит из пары элементов Rectangle и объекта Thumb, который сам является элементом управления — вероятно, построенным из Rectangle. Все, что имеет визуальное содержимое (помимо текста, растровой или векторной графики), почти наверняка является классом, производным от Control.

Одно из важнейших свойств, определяемых Control, называется Template. Как будет показано позже, оно позволяет полностью переопределить внешний вид элемента управления посредством определения вашего собственного визуального дерева (шаблона).

Например, визуальное переопределение кнопки (Button) может потребоваться в том случае, если кнопка должна быть круглой, а не прямоугольной. Визуальное переопределение TextBlock или Image не имеет смысла, потому что они не содержат ничего, кроме текста или графики. Чтобы добавить что-то свое в TextBlock или Image, следует определить Control; тем самым вы создаете визуальное дерево, включающее примитив элемента. И хотя вы можете определить класс, производный от FrameworkElement, вряд ли вам удастся сделать что-то с результатом. К нему невозможно применить визуальное Но если определить класс, производный от Control, вы сможете настроить внешний вид своего элемента управления, определив визуальное дерево в XAML.

Класс Control определяет набор свойств, которые он сам не использует. Эти свойства предназначены для классов, производных от Control, и относятся они в основном к TextBlock (CharacterSpacing, FontFamily, FontSize, FontStretch, FontStyle, FontWeight и Foreground) и Border (Background, BorderBrush, BorderThickness и Padding). He каждый класс, производный от Control, содержит текст или рамку, но если эти свойства понадобятся вам при создании нового элемента управления или нового шаблона для существующего элемента управления — они к вашим услугам. Класс Control также предоставляет два новых свойства с именами HorizontalContentAlignment и VerticalContentAlignment для определения визуального оформления элементов управления.

Классы, производные от Control, часто определяют новые свойства и события. Часто они обрабатывают события пользовательского ввода от мыши, пера и клавиатуры и преобразуют их во входные данные событий более высокого уровня. Например, класс ButtonBase (базовый для всех классов кнопок) определяет событие Click. Класс Slider определяет событие ValueChanged, сообщающее об изменении свойства Value. Класс TextBox определяет событие TextChanged, которое сообщает об изменении свойства Text.

В реальной жизни классы, производные от Control, чаще взаимодействуют с пользователями. Для удобства работы с входными данными пользователей Control предоставляет защищенные виртуальные методы, соответствующие всем событиям пользовательского ввода, определяемым UIElement. Например, UIElement определяет событие Tapped, a Control определяет защищенный виртуальный метод OnTapped(). Control также определяет свойство IsEnabled, чтобы элемент управления не принимал ввод пользователя в ситуации, в которой этот ввод неприменим, и определяет событие IsEnabledChanged, которое срабатывает при изменении этого свойства. Это единственное открытое событие, фактически определяемое в Control.

Идея «фокуса ввода» у элементов управления остается актуальной в Windows 8. Когда элемент управления обладает фокусом ввода, пользователь ожидает, что этот конкретный элемент управления будет получать большую часть событий клавиатуры. (Конечно, некоторые события клавиатуры — например, нажатие клавиши Windows — выходят за пределы фокуса ввода.) Для этой цели класс Control определяет метод Focus(), а также виртуальные методы OnGotFocus() и OnLostFocus().

Концепция фокуса ввода с клавиатуры связана с концепцией перехода между элементами управления при помощи клавиши Tab. Для этого класс Control определяет свойства IsTabStop, TabIndex и TabNavigation.

Многие классы, производные от Control, находятся в пространстве имен Windows.UI.Xaml.Controls, но некоторые из них размещаются в пространстве имен Windows.UI.Xaml.Controls.Primitives. Последнее обычно резервируется для элементов управления, используемых в составе других элементов управления, но это всего лишь рекомендация, а не требование.

Обычно производные классы наследуют непосредственно от Control, но четыре важных класса, производных от Control, определяют собственные субкатегории элементов управления:

Object DependencyObject UIElement FrameworkElement Control ContentControl ItemsControl RangeBase UserControl

Класс ContentControl (базовый для таких важных классов, как Button, ScrollViewer и AppBar) на первый взгляд не делает почти ничего, кроме определения свойства Content типа object. Например, для Button свойству Content задается то содержимое, которое должно отображаться внутри Button. Чаще всего это текст или растровое изображение, но может быть и панель с другим содержимым.

Интересно, что свойство Content класса ContentControl имеет тип object вместо UIElement. Этому есть причина. В содержимом Button можно разместить практически любой тип объекта, в том числе и шаблон (в форме визуального дерева), который сообщает Button, как следует выводить содержимое. Для Button эта возможность используется не так часто, но для других классов, производных от ItemsControl, ее важность возрастает.

ItemsControl — родительский класс для элементов управления, предназначенных для вывода коллекций объектов. К этой категории принадлежат как знакомые классы ListBox и ComboBox, так и новые элементы управления Windows 8 — FlipView, GridView и ListView.

Существует пара способов создания нестандартных элементов управления. Более простой способ заключается в определении стиля, но для более масштабных визуальных изменений потребуется шаблон. В некоторых случаях можно использовать наследование от класса существующего элемента, чтобы дополнить его новыми возможностями, или же наследовать от ContentControl или ItemsControl, если эти элементы управления предоставляют необходимую функциональность.

Но один из самых распространенных способов создания нестандартных элементов управления основан на наследовании от UserControl. Для специализированных библиотек элементов управления его лучше не применять, но он подходит для элементов управления, которые вы собираетесь использовать сами в контексте своего приложения.

Записная книжка программиста-новичка, C#, SQL, PHP и все-все-все

Я ведь это уже делал, но хрен теперь найдешь тот кусок кода, гуглим снова… Где бы найти простое и понятное руководство для начинающего, а не тонкости для мега-гуру?

Главная→C#→WinForms→ Как сделать собственный составной элемент управления (composite control) в WinForms

Рубрики

Свежие записи

  • Вырезаем числовую часть из начала строки в transact-sql
  • Пул соединений с базой данных в ADO.NET / OleDb — как избежать проблем с утечкой соединений в ASP.NET (перевод)
  • ASP .Net MVC, JQuery и AJAX — отсылаем данные на сервер
  • Разделитель тысяч и дробной части для decimal
  • Создаем расширенный Control в WinForms наследуясь от существующего
  • Вставка строк и изменение границ ячеек в Excel Interop из C#
  • Как прочитать данные из удаленного DataRow в DataTable
  • Проблемы с кодировкой при копировании русского текста из MS SQL Studio в Outlook/Word/Office
  • Как проверить, существует ли таблица в MS SQL Server перед удалением/созданием
  • Очень просто.
  • Получаем выбранные строки DataGridView, в котором выбраны только ячейки
  • Ошибка в коде привела к убыткам в 476 миллионов долларов и банкротству компании
  • Отслеживаем изменения выбранного значения в колонке ComboBox DataGridView (DataGridViewComboBoxColumn)
  • Excel 2010, Windows 7, два монитора и «ошибка при направлении команды приложению»
  • Удаляем default-ограничение (constraint) в Transact Sql

Свежие комментарии

  • Kirill к записи Самоучитель по C# для начинающих. 01. Основы языка, переменные, логика, циклы.
  • как избавиться от чувства вины к записи Как добавить строку/текст в начало файла в C# и .Net
  • DannyLef к записи Полезные расширения-плагины для WordPress
  • как избавиться от чувства вины к записи Как добавить строку/текст в начало файла в C# и .Net
  • gweg2ehgwEHERWQHQ к записи Простейшее диалоговое окно-вопрос (MessageBox) в WindowsForms

Архивы

Мета

Как сделать собственный составной элемент управления (composite control) в WinForms

Опубликовано 28.12.2012 автором Ведомир

Задача: сделать нестандартный элемент управления (control) для Windows Froms. Какой именно? Есть несколько разных вариантов, темой этой статьи будет собственный DateTimePicker, способный работать с пустыми датами. В качестве пустых дат будет активно использоваться описанный ранее класс DatePlus. Что мы хотим? По сути дела нам нужен Masked TextBox под ввод даты, кнопка для вызова всплывающего календаря и ряд служебных функций — упакованные в одну простую оболочку. Плюс на кнопке должна быть стрелка, разворачивающаяся вверх или вниз в зависимости от наличия календаря.

Добрый MSDN говорит, что нестандартные управляторы бывают трех типов:

— составные (composite), совмещающие несколько уже существующих, делаются наследованеим от UserControl
— расширенные, добавляющие что-то новое в существующий control, делаются наследованием от соотвествующего класса
— нестандартные (custom), в которых переделывается отрисовка на экран

Очевидно, что нам нужен составной элемент управления. Последний кусочек теории перед переходом к коду — с точки зрения операционной системы каждый элемент Windows Forms представляет собой отдельное окно. То есть у нас есть главное окно — форма, внутри которого сидят окна поменьше, внутри которых могут сидеть еще более мелкие окна (например GroupBox и несколько кнопок внутри).

В студии мы можем просто добавить в проект «Пользовательский элемент управления» и получить дизайнер, очень похожий на дизайнер обычной формы и кинуть на него MaskedTextBox, кнопку и календарь. По клику на кнопке должен появляться и исчезать календарь — добиться этого можно простым изменением размера control’а.

Здесь появляется первая проблема — стандартный календарь не выходит за пределы родительской формы. То есть если мы расположим наш замечательный датавзятор рядом с нижним или правым краем формы, календарь обрежется. Хочется, чтобы он красиво парил в виртуальном воздухе подобно всплывающему меню. Кликаем на кнопку — появляется, кликаем на кнопку или вне ее — исчезает. Вот в этих кликах собака и зарыта.

На Stackoverflow нам советуют наследоваться от базового элемента всплывающего меню ToolStripDropDown. Все замечательно всплывает и вылезает, но возникает масса проблем с автоматически закрытием всплывающего меню — оно запрятано где-то очень глубоко в недрах системы. Отслеживать его надо чтобы корректно отрабатывать ручное открытие и закрытие при клике на кнопку. Автозакрытие ведет себя очень странно и нелогично, последней каплей для меня стало то, что клике на кнопку оно происходит то раньше то позже собственно события клика на кнопку. В итоге я плюнул на извращенный код обхода всех этих глюков и нарисовал в дизайнере мини-форму с календарем внутри, которую уже и показываю/закрываю по клику.

calendar-form

Но куда именно это форму выводить? Ведь местоположения нашего управлятора мы заранее не знаем. Координаты для вывода формы придется пересчитывать из относительных кординат внутри родительского окна для контрола и обратно.

Point parentScreenPoint = this.Parent.PointToScreen(new Point(this.Location.X, this.Location.Y + this.Height)); _calendarForm.Location = parentScreenPoint;

Автозакрытие имитируется очень просто — вешаем вызов Hide на событие Deactivate

Так же на стоит забывать, что в MonthCalendar по умолчанию выбирается диапазон дат, а нам нужна только одна — при выборе даты диапазон надо схлопывать. Удобнее всего делать это изнутри формы.

private void Calendar_DateSelected(object sender, DateRangeEventArgs e)

Отлично. Все не просто всплывает и вылезает, но еще и открывается-закрывается. Начинаем тестировать с разным размером шрифта на форме и сталкиваемся с еще одним интересным глюком — MaskedTextBox масштабируется непропорционально своему содержимому. Проще говоря при увеличении размера шрифта строка содержимого перестает в него влезать и обрезается (можно конечно прокрутить до конца курсором). Лечится этот глюк и вовсе неожиданным способом — установкой прозрачного фонового цвета общего UserControl-контейнера.

Еще один глюк можно будет увидеть прямо в дизайнере — при копировании элемента через Ctrl + перетаскивание мышью базовый контейнер нашего элемента управления будет растягиваться. Кроме того его сложно позиционировать относительно других элементов. Лечим следующим образом:

1. Обнуляем в внутренних элементов свойство Margin редактируем Location чтобы поставить их вплотную к границам и поджимаем сам UserControl

2. Ставим AutoScaleMode в Front, AutoSize -> true, AutoSizeMode -> GrowAndShrink

Последний глюк связан с тем, что календарь у нас будет находиться в отдельной форме и размер шрифта не будет передаваться, соответственно размер календаря не будет меняться вслед за размером самого элемента управления и базовой формы. Задать его в конструкторе мы не сможем, так как в наш управлятор размер шрифта придет позже. Самое просто — задавать его при выводе календаря на экран.

_calendarForm.Font = new Font(_calendarForm.Font.Name, this.Font.Size);

Что нам осталось? Стрелка на кнопке! Придется менять картинку во время выполнения программы и проще всего это сделать, добавив в элемент управления ImageList через дизайнер и там же загрузить картинки. Код для смены тривиален.

_calendarForm.VisibleChanged += new EventHandler(_calendarForm_VisibleChanged); // . void _calendarForm_VisibleChanged(object sender, EventArgs e) < _calendarForm.Font = new Font(_calendarForm.Font.Name, this.Font.Size); if (_calendarForm.Visible) < _calendarButton.BackgroundImage = _arrowsImageList.Images["arrow-01-up.png"]; >else < _calendarButton.BackgroundImage = _arrowsImageList.Images["arrow-01-down.png"]; >>

Чем больше свободы, тем больше проблем. Если пользователь вводит дату текстом, то он может ввести ее неправильно! Причем встает отдельный вопрос о том, что надо считать правильным — например можно ли пользователю вводить дату из будущего? Иногда можно иногда нельзя. Поэтому имеет смысл ввести отдельный параметр для регулировки ввода даты из будущего и вывести его в панель свойств дизайнера VisualStudio

private bool _allowFuture = false; [Description("AllowFuture"), Category("Behavior")] public bool AllowFuture < get < return _allowFuture; >set < _allowFuture = value; >>

Добавить функцию для проверки даты на правильность.

public bool DateCorrect < get < bool dateCorrect = false; dateCorrect = DatePlus.DateCorrect(EnteredDateString); if (dateCorrect && !AllowFuture) < DatePlus date = new DatePlus(EnteredDateString); if (date.InFuture) < dateCorrect = false; >> return dateCorrect; > >

И наконец корректно обработать проставление даты в календарь, учитывая что диапазон дат календаря тоже ограничен и если дата вылезает за его пределы, то в календарь ее ставить не надо

if (DateCorrect && !Empty && Date.DateTime > _calendarForm.Calendar.MinDate && Date.DateTime

Ввод неправильного значения надо отследить и расстрелять убедить пользователя не делать таких гадостей. Относительно надежное отслеживания выхода пользователя с MaskedTextBox мне удалось получить отслеживанием событий Validated и MouseLeave. Они нередко происхолдя друг за другом, так что видимость окна с сообщением об ошибке тоже надо отслеживать, чтобы не выводить окно два раза.

if (!DateCorrect && !_wrongDateBox.Visible)

Если же неправильная строка все-таки введена то волевым решением отдается пустая дата.

Чтобы собрать все вместе приведу тестовый проект WinForms со всеми вышеописанными классами, собранными в отдельный dll и тестовой формой

Какое событие класса control отвечает за изменение элемента

Класс Control является базовым для всех классов, с помощью которых строится пользовательский интерфейс. К таким классам относятся формы, кнопки, меню, поля ввода и другие.

В классе Control реализованы базовые возможности интерфейсных элементов. В нём есть методы для обработки информации, вводимой пользователем с помощью клавиатуры и мыши. Для объектов класса Control можно определять размер, положение, цвет фона, вид и цвет шрифта и многое другое.

Наиболее важные свойства класса Control :

BackColor — определяет цвет фона;

ForeColor — задаёт цвет символов;

Font — характеризует шрифт символов текста;

Location — содержит координаты левого верхнего угла элемента. Свойства Left и Top позволяют обратится к координатам верхнего угла поотдельности;

Size — определяет размеры элемента. Через свойства Height и Width можно обращаться к высоте и ширине по отдельности;

Enabled — определяет доступность элемента ( true — элемент доступен, false — не доступен, хотя может быть и видим, если имеет графическое представление. Как правило, недоступный элемент, например, пункт меню выглядит серым);

Visible — определяет видимость элемента ( true — элемент видим (и доступен!), false — не видим (и не доступен)).

Основные методы класса Control:

Focus() — задание фокуса ввода элементу управления. Результат: true — элемент получил фокус ввода, false — не получил. Данные, вводимые пользователем с помощью клавиатуры, направляются в элемент управления, который получил фокус ввода;

Show() — отображает элемент управления, свойство Visible становится равным true ;

Hide() — скрывает элемент управления,свойство Visible в этом случае устанавливается в значение false ;

Invalidate() — обновляет изображение элемента управления.

Некоторые события класса Control:

Click — событие, возникающее при щелчке мышью по элементу управления;

DoubleClick — событие, возникающее при двойном щелчке мышью;

MouseDown — событие, которое возникает при ходе левой клавиши мыши вниз (нажимание клавиши);

MouseUp — событие, которое возникает при ходе левой клавиши мыши вверх (отпускание клавиши);

MouseMove — событие, которое возникает при перемещении курсора мыши над объектом ;

KeyDown — событие, возникающее при нажатии клавиши на клавиатуре;

KeyUp — событие, возникающее при отпускании клавиши на клавиатуре;

Paint — событие, которое возникает в тот момент, когда весь элемент управления или его часть объявляется недействительной и требуется его перерисовка.

Элементы управления

Чтобы как-то взаимодействовать с пользователем, получать от пользователя ввод с клавиатуры или мыши и использовать введенные данные в программе, нам нужны элементы управления. WPF предлагает нам богатый стандартный набор элементов управления

Все элементы управления могут быть условно разделены на несколько подгрупп:

  • Элементы управления содержимым , например кнопки (Button), метки (Label)
  • Специальные контейнеры , которые содержат другие элементы, но в отличие от элементов Grid или Canvas не являются контейнерами компоновки — ScrollViewer,GroupBox
  • Декораторы , чье предназначение создание определенного фона вокруг вложенных элементов, например, Border или Viewbox.
  • Элементы управления списками , например, ListBox, ComboBox.
  • Текстовые элементы управления , например, TextBox, RichTextBox.
  • Элементы, основанные на диапазонах значений , например, ProgressBar, Slider.
  • Элементы для работ с датами , например, DatePicker и Calendar.
  • Остальные элементы управления , которые не вошли в предыдущие подгруппы, например, Image.

Все элементы управления наследуются от общего класса System.Window.Controls.Control и имеют ряд общих свойств. А общую иерархию элементов управления можно представить следующим образом:

Иерархия элементов управления в WPF

Вкратце рассмотрим, что представляют все эти типы в иерархии.

System.Threading.DispatcherObject

В основе WPF лежит модель STA (Single-Thread Affinity), согласно которой за пользовательский интерфейс отвечает один поток. И чтобы пользовательский интерфейс мог взаимодействовать с другими потоками, WPF использует концепцию диспетчера — специального объекта, управляющего обменом сообщениями, через которые взаимодействуют потоки. Наследование типов от класса DispatcherObject позволяет получить доступ к подобному объекту-диспетчеру и и другим функциям по управлению параллелизмом.

System.Windows.DependencyObject

Наследование от этого класса позволяет взаимодействовать с элементами в приложении через их специальную модель свойств, которые называются свойствами зависимостей (dependency properties). Эта модель упрощает применение ряда особенностей WPF, например, привязки данных. Так, система свойств зависимостей отслеживает зависимости между значениями свойств, автоматически проверяет их и изменяет при изменении зависимости.

System.Windows.Media.Visual

Класс Visual содержит инструкции, которые отвечают за отрисовку, визуализацию объекта.

System.Windows.UIElement

Класс UIElement добавляет возможности по компоновке элемента, обработку событий и получение ввода.

System.Windows.FrameworkElement

Класс FrameworkElement добавляет поддержку привязки данных, анимации, стилий. Также добавляет ряд свойств, связанных с компоновкой (выравнивание, отступы) и ряд других.

System.Windows.Controls.Control

Класс Control представляет элемент управления, с которым взаимодействует пользователь. Этот класс добавляет ряд дополнительных свойств для поддержки элементами шрифтов, цветов фона, шрифта, а также добавляет поддержку шаблонов — специального механизма в WPF, который позволяет изменять стандартное представление элемента, кастомизировать его.

И далее от класса Control наследуются непосредственно конкретные элементы управления или их базовые классы, которые получают весь функционал, добавляемый к типам в этой иерархии классов.

Рассмотрим некоторые из основных свойств, которые наследуются элементами управления.

Name

Данное свойство определяет имя элемента управления, через которое впоследствии можно будет обращаться к данному элементу, как в коде, так и в xaml разметке. Например, в xaml-коде у нас определена следующая кнопка:

Здесь у нас задан атрибут Click с названием метода обработчика button1_Click , который будет определен в файле кода C# и будет вызываться по нажатию кнопки. Тогда в связанном файле кода C# мы можем обратиться к этой кнопке:

private void button1_Click(object sender, RoutedEventArgs e)

Поскольку свойство Name имеет значение button1 , то через это значение мы можем обратиться к кнопке в коде.

FieldModifier

Свойство FieldModifier задает модификатор доступа к объекту:

В качестве значения используются стандартные модификатора доступа языка C#: private, protected, internal, protected internal и public. В данном случае объявление кнопок с модификаторами будет равноценно следующему их определению в коде:

private Button button1; internal Button button2;

Если для элемента не определен атрибут x:FieldModifier , то по умолчанию он равен «protected internal».

Visibility

Это свойство устанавливает параметры видимости элемента и может принимать одно из трех значений:

  • Visible — элемент виден и участвует в компоновке.
  • Collapsed — элемент не виден и не участвует в компоновке.
  • Hidden — элемент не виден, но при этом участвует в компоновке.

Различия между Collapsed и Hidden можно продемонстрировать на примере:

Свойства настройки шрифтов

  • FontFamily — определяет семейство шрифта (например, Arial, Verdana и т.д.)
  • FontSize — определяет высоту шрифта
  • FontStyle — определяет наклон шрифта, принимает одно из трех значений — Normal , Italic , Oblique .
  • FontWeight — определяет толщину шрифта и принимает ряд значений, как Black , Bold и др.
  • FontStretch — определяет, как будет растягивать или сжимать текст, например, значение Condensed сжимает текст, а Expanded — расстягивает.

Cursor

Это свойство позволяет нам получить или установить курсор для элемента управления в одно из значений, например, Hand , Arrow , Wait и др. Например, установка курсора в коде c#: button1.Cursor=Cursors.Hand;

FlowDirection

Данное свойство задает направление текста. Если оно равно RightToLeft, то текст начинается с правого края, если — LeftToRight, то с левого.

 RightToLeft LeftToRight 

Свойство FlowDirection в WPF

Цвета фона и шрифта

Свойства Background и Foreground задают соответственно цвет фона и текста элемента управления.

Простейший способ задания цвета в коде xaml: Background=»#ffffff» . В качестве значения свойство Background (Foreground) может принимать запись в виде шестнадцатеричного значения в формате #rrggbb , где rr — красная составляющая, gg — зеленая составляющая, а bb — синяя. Также можно задать цвет в формате #aarrggbb .

Либо можно использовать названия цветов напрямую:

Однако при компиляции будет создаваться объект SolidColorBrush , который и будет задавать цвет элемента. То есть определение кнопки выше фактически будет равноценно следующему:

SolidColorBrush представляет собой кисть, покрывающую элемент одним цветом. Позже мы подробнее поговорим о цветах. А пока надо знать, что эти записи эквивалентны, кроме того, вторая форма определения цвета позволяет задать другие кисти — например, градиент.

Это надо также учитывать при установке или получении цвета элемента в коде c#:

button1.Background = new SolidColorBrush(Colors.Red); button1.Foreground = new SolidColorBrush(Color.FromRgb(0,255, 0));

Класс Colors предлагает ряд встроенный цветовых констант, которыми мы можем воспользоваться. А если мы захотим конкретизировать настройки цвета с помощью значений RGB, то можно использовать метод Color.FromRgb .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *