Стандартные меню приложений
Декларативное создание меню
-
Откройте
форму Form2 в режиме View Designer и
поместите из
панели Toolbox на форму экземпляр компонента MenuStrip с
именем menu
-
При
выделенном элементе меню в панели Properties раскройте свойство Items
-
В окне
редактора меню выберите из раскрывающегося списка элемент MenuItem и щелчком на кнопке Add добавьте
в коллекцию Items узел верхнего уровня
-
Присвойте
добавленному элементу через таблицу свойств редактора меню Name = itemFormat, Text = &Format и
щелчком на кнопке OK завершите редактирование -
При
выделенном элементе ItemFormat в панели Properties раскройте
свойство DropDownItems
-
В
окне редактора меню выберите из раскрывающегося списка элемент MenuItem и
щелчком на кнопке Add добавьте в коллекцию DropDownItems объект
команды меню -
Присвойте
добавленному элементу через таблицу свойств редактора меню Name = itemFont, Text = &Font и
щелчком на кнопке OK завершите редактирование -
Выполните
приложение и проверьте работоспособность Form2 на данном
этапе -
Поместите
из панели Toolbox экземпляр элемента Panel и настройте его
свойства так:
-
Выделите
объект panel и через панель Properties в режиме Events зарегистрируйте
для события Paint обработчик и именем PanelOnPaint
На этом декларативная часть работы закончена. Далее займемся программной частью.
Программирование меню
-
Перейдите
в режим View Code формы Form2 и добавьте перед конструктором
класса Form2 объявление ссылки на элемент меню
public partial class Form2 : Form
{
// Объявили поле-ссылку на объект команды меню
ToolStripMenuItem itemSelectedFont;
public Form2()
{
InitializeComponent();
}
private void PanelOnPaint(object sender, PaintEventArgs e)
{
}
}
Листинг
28.5.
Добавление поля-ссылки на экземпляр элемента меню
-
Добавьте
в конструктор класса Form2 после вызова функции инициализации
компонентов код динамического заполнения списка команд в
коллекцию команды Font
public Form2()
{
InitializeComponent();
// Заполнение коллекции объекта itemFont
// списком доступных шрифтов стиля "Обычный"
Graphics gr = CreateGraphics(); // Ссылка на контекст устройства
// Читаем все шрифты
FontFamily[] fonts = FontFamily.GetFamilies(gr);
// Перебираем шрифты и формируем команды меню Font
foreach (FontFamily font in fonts)
{
// Выбираем шрифты одного стиля "Обычный"
if (font.IsStyleAvailable(FontStyle.Regular))
{
// Добавляем в коллекцию команды Font
ToolStripMenuItem item =
(ToolStripMenuItem)itemFont.DropDownItems.Add(font.Name);
// Если встретился текущий шрифт формы,
// запоминаем эту команду и отмечаем флажком
if (font.Name == this.Font.Name)
{
itemSelectedFont = item;
itemSelectedFont.Checked = true;
}
}
}
gr.Dispose(); // Освобождаем ограниченный ресурс
}
Листинг
28.6.
Код динамического формирования команд меню в конструкторе класса Form2
-
Запустите
приложение и удостоверьтесь, что при раскрытии команды меню Font она уже заполнена элементами названий шрифтов
Теперь обеспечим нужную функциональность выбора шрифтов и отображения их названия на клиентской области панели panel.
-
Подпишите
добавленный в коллекцию команды Font элемент item на событие Click. Для этого наберите вручную!!!, чтобы правильно создать
обработчик, следующий код в конце условия if
public Form2()
{
....................................................
// Перебираем шрифты и формируем команды меню Font
foreach (FontFamily font in fonts)
{
// Выбираем шрифты одного стиля "Обычный"
if (font.IsStyleAvailable(FontStyle.Regular))
{
...............................................
// Следующую строчку введите вручную!!!
item.Click += new EventHandler(item_Click);
}
}
gr.Dispose(); // Освобождаем ограниченный ресурс
}
Листинг
28.7.
Регистрация обработчика для события Click в динамически формируемой команде
-
Заполните
обработчик item_Click() следующим
кодом, который будет сбрасывать флажок с выбранного ранее
шрифта и устанавливать его на новом выбранном шрифте
void item_Click(object sender, EventArgs e)
{
// Повышаем полномочия ссылки для адресации к выделенной команде
ToolStripMenuItem item = (ToolStripMenuItem)sender;
itemSelectedFont.Checked = false; // Сбрасываем предыдущий флажок
item.Checked = true; // Поднимаем новый флажок
itemSelectedFont = item;// Запоминаем отмеченную команду
panel.Invalidate(); // Перерисовываем панель с новым шрифтом
}
Листинг
28.8.
Код обработчика выделения нового шрифта в классе Font2
-
Найдите
созданный ранее обработчик события Paint панели и заполните
его кодом перерисовки панели с новым шрифтом
private void PanelOnPaint(object sender, PaintEventArgs e)
{
Graphics gr = e.Graphics; // Получаем контекст устройства
// Создаем новый шрифт по выбранному в меню с заведомо
// большим размером, чтобы потом подогнать уменьшением
float emSize = 100.0F;
System.Drawing.Font font =
new Font(itemSelectedFont.Text.Trim(), emSize);
String str = font.Name; // Строка для рисования
// Подгоняем размер текстового блока под ширину формы
float widthText = gr.MeasureString(str,
font = new Font(itemSelectedFont.Text, emSize)).Width;
while ((panel.ClientSize.Width - widthText) < 0.0F)
{
emSize -= 0.5F;
widthText = gr.MeasureString(str,
font = new Font(itemSelectedFont.Text, emSize)).Width;
}
// Настроим точку привязки текстового блока
System.Drawing.StringFormat fmt = new StringFormat();
fmt.Alignment = StringAlignment.Center; // По горизонтали
fmt.LineAlignment = StringAlignment.Center; // По вертикали
// Настроим точку привязки клиентской области панели
PointF point = new PointF(panel.ClientSize.Width / 2,
panel.ClientSize.Height / 2);
// Рисуем на панели название выбранного шрифта текущим цветом формы
gr.DrawString(str, font,
new SolidBrush(this.ForeColor), point, fmt);
}
Листинг
28.9.
Код обработчика перерисовки панели в классе Form2
-
В классе Form2 переопределите унаследованный виртуальный метод диспетчеризации OnResize() (ввод начните с ключевого слова override ) и заполните
его следующим кодом
protected override void OnResize(EventArgs e)
{
panel.Invalidate();
base.OnResize(e);
}
Листинг
28.10.
Переопределенный метод диспетчеризации события Resize формы
Этот метод нужен для перерисовки панели внутри формы при изменении пользователем ее размеров.
-
Запустите Form2 и удостовертесь в ее работоспособности,
результат будет таким
Обратите внимание, что мы обеспечили центрирование текста на панели и автоматическую его подгонку под размеры формы.
Упражнение 3. Меню с изображениями
Хотя информативность названий команд меню может оказаться достаточной, в современных меню применяются еще и смысловые пиктограммы. Это нужно для того, чтобы постепенно приучить пользователя к изображениям команд и безболезненно перевести его на более быстрый способ использования кнопок панели инструментов с теми же самыми изображениями.
Если распаковать этот архив, то используемые в меню изображения хранятся в папке bitmaps/commands, рассортированные по разной глубине цвета. Если в Вашей системе нет этих пиктограмм, то их можно найти в прилагаемом к данной лабораторной работе каталоге Source.
Служебные изображения в программе удобнее использовать как ресурсы, внедренные в исполнимую сборку и переносимые вместе с этой сборкой. Файл изображения добавляется к проекту командой Project/Add Existing Item, после чего оболочка физически скопирует его в каталог размещения проекта и он появится в панели Solution Explorer.
Далее можно использовать один из способов превращения этого файла в ресурс приложения: выделить этот файл и через панель Properties установить для него опцию Build Action равной Embedded Resource. Это заставит оболочку при компиляции внедрять указанный файл как ресурс в сборку приложения. Внутри самого кода приложения мы можем адресоваться к этому файлу.
Пусть, например, мы хотим использовать пиктограмму Open.bmp и добавили этот файл в проект. Доступ к изображению из кода программы можно осуществить разными способа, например, с помощью следующего кода
Bitmap bmCut = new Bitmap(this.GetType(), "path.Open.bmp");
Первый аргумент должен ссылаться на класс приложения, в нашем случае это порождающий класс текущего объекта. Второй аргумент, это имя файла изображения с путем относительно корневой папки проекта
Присоединить изображение к элементу меню можно присвоением ссылки свойству Image соответствующей команды, например
itemCut.Image = bmCut;
После таких действий пиктограмма элемента будет отображаться слева от текста меню на месте отображения флажка.
В данном упражнении разработаем простой редактор изображений, в котором можно будет загружать и сохранять файлы изображений, использовать буфер обмена и отображать рисунки несколькими способами. При этом задействуем ряд стандартных диалоговых окон. Для тренировки рассмотрим несколько способов загрузки изображений в элементы меню.
-
Откройте
файл Form3.cs в режиме View Designer и задайте свойству Text формы значение " Простой редактор изображений " -
Поместите
на форму компонент PictureBox и настройте его так: Name = pictureBox, Dock = Fill
В дальнейшем экземпляр элемента управления PictuteBox будет служить контейнером при просмотре изображений в нашем законченном упражнении.
Декларативная часть создания меню
Меню для нашего упражнения мы создадим, чередуя декларативный и программный способ. Мы с вами знаем, что при декларативном способе создания объектов работу по написанию кода за нас выполняет оболочка в закулисной части класса формы, который имеет расширение Designer.cs. По большому счету разницы нет, как создавать код: с помощью графического инструмента или непосредственно вручную. Главное знать, что писать и как позиционировать объекты. При создании меню проблемы с позиционированием не возникает, главное - порядок следования компонентов. Но познакомиться с графическими возможностями оболочки по созданию меню не помешает.
-
Поместите
на форму компонент MenuStrip с именем menu и
настройте его декларативно в соответствии с приведенным ниже
деревом свойств
Создавать декларативным способом новые элементы меню любого уровня удобнее, если навести курсор справа от заготовки команды и раскрыть список предлагаемых типов, затем выделенный элемент меню можно настроить через панель Properties.


