Нестандартные формы и стандартные диалоги
Распределение кода по отдельным файлам
Мы программируем большую задачу по изучению стандартных диалогов и весь код размещаем в двух файлах: StandardDialogs.cs и StandardDialogs.Designer.cs. Для обозримости мы коды для отдельных вкладок упаковали в секции #region. Но у нас осталось еще много диалогов, поэтому для удобства разместим эти секции в отдельных файлах как отдельные части одного класса StandardDialogs.
- В панели Solution Explorer вызовите для корневого узла проекта контекстное меню и командой Add/New Item добавьте новый пустой файл с именем MessageBox.cs
- Откройте файл StandardDialogs.cs в режиме View Em, выполните команду меню Edit/Select All и скопируйте все содержимое в новый файл MessageBox.cs
- В файле MessageBox.cs вызовите для рабочей области контекстное меню и выполните команду Outlining/Collapse to Definitions, чтобы свернуть все секции кода
- Отредактируйте файл MessageBox.cs так, чтобы в свернутом состоянии он выглядел следующим образом (убрали базовый класс Form и ключевое слово public в объявлении класса)
- В панели Solution Explorer сделайте две копии теперь уже файла MessageBox.cs и присвойте им имена OpenFileDialog.cs, SaveFileDialog.cs
- Щелкните правой кнопкой мыши на вкладке StandardDialogs.cs редактора и выполните команду Close All But This, чтобы закрыть все иные ненужные вкладки
- Выбирайте поочередно в файле StandardDialogs.cs свернутые коды для соответствующих вкладок и перенесите (в новое скопировать, а в старом убрать) в свои одноименные файлы как члены частичного класса, открывая файлы в режиме View Em. В файле StandardDialogs.cs должен остаться только код для вкладки "Обзор"
- В панели Solution Explorer щелкните правой кнопкой мыши на корневом узле проекта и командой Add/New Folder добавьте новую папку с именем ItemsDialogs
- Удерживая клавишу Ctrl, выделите файлы MessageBox.cs, OpenFileDialog.cs, SaveFileDialog.cs и мышью переместите их в новую папку
- Выполните команду меню Window/Close All Documents, чтобы закрыть все редактируемые файлы
- Запустите приложение и убедитесь, что работоспособность его не изменилась, но код расфасован удобнее
Разработка вкладки ColorDialog
Диалоговое окно ColorDialog порождается классом System.Windows.Forms.ColorDialog. Оно позволяет выбрать цвет, который содержится в свойстве Color типа System.Drawing.Color и может открываться в обычном или расширенном варианте. Несколько других свойств типа Boolean управляют различными настройками диалогового окна ColorDialog. Вот они
Свойство | Тип | Пояснения |
---|---|---|
Color | System.Drawing.Color | Выбранный пользователем цвет |
AllowFullOpen | bool | При значении true, установленном по умолчанию, окно готово раскрываеться в расширенном варианте с возможностью выбора любых дополнительных цветов |
AnyColor | bool | Любой цвет |
FullOpen | bool | Раскрывается в расширенном варианте |
SolidColorOnly | bool | Только основные цвета |
ShowHelp | bool | Отобразить кнопку справки |
CustomColors | int[ ] | Массив дополнительных цветов |
Булевыми значениями этих публичных свойств мы и будем управлять из вкладки ColorDialog.
- Поместите на вкладку ColorDialog необходимые элементы управления и настройте их в соответствии с таблицей
В итоге пользовательский интерфейс вкладки должен выглядеть примерно так
- Из панели Toolbox поместите на форму двойным щелчком компонент ColorDialog и присвойте ему имя colorDialog
- Создайте для кнопки Show обработчик с именем btnShowColorDialog_Click
- Создайте для кнопки Reset обработчик с именем btnResetColorDialog_Click
- Упакуйте обработчики в секцию #region Вкладка ColorDialog...#endregion
- Через панель Solution Explorer создайте в папке ItemsDialogs копию файла SaveFileDialog.cs и присвойте ей имя ColorDialog.cs
- Разместите в файле ColorDialog.cs секцию #region с заготовками обработчиков btnShowColorDialog_Click и btnResetColorDialog_Click, автоматически помещенными оболочкой при создании в основную часть класса в файле StandardDialogs.cs, и заполните их кодом. Общее содержимое файла ColorDialog.cs должно быть примерно таким
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using System.IO; using System.Reflection; namespace FormsApp { partial class StandardDialogs { #region Вкладка ColorDialog // Поле для хранения дополнительных цветов int[] customColors = new int[16] { 0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF, 0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF, 0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF, 0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF }; private void btnShowColorDialog_Click(object sender, EventArgs e) { // Создаем совершенно новое диалоговое окно ColorDialog dlg = new ColorDialog(); // Настраиваем диалоговое окно dlg.CustomColors = customColors; foreach (Control ctrl in this.tabPage4.Controls) { // Ищем наши флажки на дочерней вкладке if (ctrl is CheckBox) { // Позиционируемся по имени флажка switch (ctrl.Name.ToString()) { case "AllowFullOpen": dlg.AllowFullOpen = ((CheckBox)ctrl).Checked; break; case "AnyColor": dlg.AnyColor = ((CheckBox)ctrl).Checked; break; case "FullOpen": dlg.FullOpen = ((CheckBox)ctrl).Checked; break; case "SolidColorOnly": dlg.SolidColorOnly = ((CheckBox)ctrl).Checked; break; case "ShowHelp": dlg.ShowHelp = ((CheckBox)ctrl).Checked; break; } } } // Инициируем предыдущий цвет dlg.Color = panelColorDialog.BackColor; // Показываем диалоговое окно и извлекаем // выбранный пользователем цвет if (dlg.ShowDialog() == DialogResult.OK) { panelColorDialog.BackColor = dlg.Color; lblColorName.Text = dlg.Color.Name; // Сохранить выбор дополнительных цветов customColors = dlg.CustomColors; } } private void btnResetColorDialog_Click(object sender, EventArgs e) { // Создаем псевдоним постоянно существующего экземпляра окна ColorDialog dlg = colorDialog; // Восстанавливаем окно dlg.Reset(); // Применяем рефлексию для перебора свойств в цикле // и передачи их значений флагам интерфейса PropertyInfo[] props = typeof(ColorDialog).GetProperties();// Получаем все свойства // Перебираем свойства foreach (PropertyInfo prop in props) { // Выбираем только логические свойства if (prop.PropertyType == typeof(bool)) { // Ищем все элементы-флажки с именем свойства // У нас только один флажок с уникальным именем Control[] controls = this.Controls.Find(prop.Name, true); // Извлекаем значение свойства и присваиваем флажку ((CheckBox)controls[0]).Checked = (bool)prop.GetGetMethod().Invoke(dlg, null); } } // Восстанавливаем элементы интерфейса panelColorDialog.BackColor = dlg.Color; lblColorName.Text = dlg.Color.Name; } #endregion } }Листинг 18.24. Содержимое файла ColorDialog.cs
Свойство CustomColors содержит массив из 16 четырехбайтных целых, в которых содержаться коды дополнительных цветов RGB -модели, представленных в окне 16 плашками. В каждом элементе массива младший байт соответствует цвету Red, затем Green и предпоследний байт - цвету Blue. Последний байт не используется. При создании массива мы сразу инициализировали RGB -байты единицами, что соответствует изначально белому цвету.
Для демонстрации того, что механизм сохранения дополнительных цветов работает, мы специально в обработчике кнопки Show каждый раз создаем диалоговое окно dlg заново и восстанавливаем в нем сохраненные в массиве customColors дополнительные цвета. Постоянное же диалоговое окно colorDialog мы используем только для сброса пользовательского интерфейса.
В обработчике btnResetColorDialog_Click() мы используем механизм отражения ( рефлексию ) для динамического анализа свойств порождающего класса диалогового окна и извлечения их значений из существующего объекта. Для этой цели мы подключили пространство имен System.Reflection. Элементы флажков методом Find() мы ищем во всей форме по их именам, совпадающим с именами свойств, и присваиваем им значения динамически извлеченных свойств. Это сделало программу несколько запутанной, но для большого количества элементов такой подход позволил бы значительно сократить объем кода. Кроме того, таким образом мы знакомимся с разными возможностями языка C#.
- Запустите приложение и испытайте работу вкладки ColorDialog
Добавление иконок к формам через файл ресурсов
На простом примере добавления иконок к формам познакомимся с файлами ресурсов оболочки. Этих файлов в проекте может быть сколько угодно и в них на этапе проектирования добавляются элементы, к которым из кода программы можно очень просто обращаться как к обычным свойствам класса (имя класса соответствует имени файла ресурсов). На этапе компиляции эти ресурсы вставляются в код исполнимой сборки и не требуют присутствия самих оригиналов, что улучшает переносимость приложения.
- В панели Solution Explorer вызовите контекстное меню для узла проекта и командой Add/New Folder создайте новую папку с именем Resources
- Вызовите контекстное меню для папки Resources и командой Add/New Item добавьте в нее файл ресурсов с именем Resource1.resx
- Двойным щелчком на файле Resource1.resx вызовите графический редактор ресурсов, раскройте в его верхней части выпадающий список Add Resource и опцией Add Existing File добавьте в каталог ресурсов проекта (и в файл ресурсов) две иконки из прилагаемого к данной работе каталога Source
- Установите в графическом редакторе ресурсов режим представления View Details и, поочередно выделяя добавленные ресурсы, через панель Properties присвойте им имена Icon1 и Icon2
- В панели Solution Explorer выделите файлы формы и через контекстное меню откройте их в режиме View Em
- Добавьте в конструктор каждой формы после вызова функции InitializeComponent() код присоединения соответствующей иконки из файла ресурсов, например, для конструктора Form1() код будет таким
public Form1() { InitializeComponent(); this.Icon = Resources.Resource1.Icon1; }Листинг 18.25. Присоединение иконки в конструкторе Form1()
- Запустите приложение для каждой формы и убедитесь, что иконки присоединяются к окну формы, например
- Перейдите к следующей части работы (если она уже есть)