Опубликован: 13.07.2010 | Доступ: свободный | Студентов: 890 / 20 | Оценка: 4.40 / 4.20 | Длительность: 77:34:00
Самостоятельная работа 18:

Нестандартные формы и стандартные диалоги

Распределение кода по отдельным файлам

Мы программируем большую задачу по изучению стандартных диалогов и весь код размещаем в двух файлах: 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. Вот они

Публичные свойства класса ColorDialog
Свойство Тип Пояснения
Color System.Drawing.Color Выбранный пользователем цвет
AllowFullOpen bool При значении true, установленном по умолчанию, окно готово раскрываеться в расширенном варианте с возможностью выбора любых дополнительных цветов
AnyColor bool Любой цвет
FullOpen bool Раскрывается в расширенном варианте
SolidColorOnly bool Только основные цвета
ShowHelp bool Отобразить кнопку справки
CustomColors int[ ] Массив дополнительных цветов

Булевыми значениями этих публичных свойств мы и будем управлять из вкладки ColorDialog.

  • Поместите на вкладку ColorDialog необходимые элементы управления и настройте их в соответствии с таблицей
Свойства элементов вкладки ColorDialog
Элемент Свойство Значение
Panel Name panelColorDialog
  Dock Left
  BorderStyle Fixed3D
Label Name lblColorDialog
  Text Булевы свойства диалога ColorDialog:
  TextAlign MiddleCenter
CheckBox Name AllowFullOpen
  Text AllowFullOpen
  Checked true
CheckBox Name AnyColor
  Text AnyColor
CheckBox Name FullOpen
  Text FullOpen
CheckBox Name SolidColorOnly
  Text SolidColorOnly
CheckBox Name ShowHelp
  Text ShowHelp
Label Name lblColorTitle
  Text Наименование выбранного цвета:
Label Name lblColorName
  Text DefaultColor
  AutoSize true
Button Name btnResetColorDialog
  AutoSize true
  Text Reset
Button Name btnShowColorDialog
  AutoSize true
  Text Show

В итоге пользовательский интерфейс вкладки должен выглядеть примерно так


  • Из панели 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()
  • Запустите приложение для каждой формы и убедитесь, что иконки присоединяются к окну формы, например


  • Перейдите к следующей части работы (если она уже есть)