Как поставить иконку в MenuItem C#?

125
10 октября 2021, 22:50

Вроде бы простой вопрос, только я не нашел соответствующего свойства в списке. Возможно ли это вообще? Прошу не предлагать ToolStripMenuItem.

Answer 1

После обсуждения в комментариях мой ответ такой:

Не используйте устаревшие компоненты MainMenu и MenuItem.

Возьмите более новые MenuStrip и ToolStripMenuItem. В них уже предусмотрено использование изображений.

Если кто-то хочет помучиться и реализовать код правильной отрисовки картинки на MenuItem с использованием события DrawItem - желаю удачи (и поставлю плюсик). Но считаю это мазохизмом и ненужной тратой времени.

Answer 2

Можно нарисовать, но если беретесь рисовать, то готовьтесь рисовать не только иконку, но и все эффекты, вроде нажато/не нажато, активно/не активно и т.д. и т.п. для всех интересующих вас статусов.

В примере я не буду приводить все возможные варианты, только необходимый минимум.

//включаем пользовательскую отрисовку
mi.OwnerDraw = true;
//событие, которое срабатывает перед отрисовкой элемента меню для определения его размера
mi.MeasureItem += Mi_MeasureItem;
//событие рисования элемента
mi.DrawItem += Mi_DrawItem;
private void Mi_MeasureItem(object sender, MeasureItemEventArgs e)
{
    //вычисляем размер кнопки меню и фиксируем
    e.ItemWidth = GetContentWidth();
    e.ItemHeight = GetContentHeight();
    //методы вычисления размера контента придется писать самостоятельно
    //Если контент содержит только текст, можно использовать e.Graphics.MeasureString(...)
}

//ну и наконец рисуем контент
private void Mi_DrawItem(object sender, DrawItemEventArgs e)
{
    e.Graphics.DrawImage(Properties.Resources.MyButtonImage, e.Bounds.X, e.Bounds.Y, e.Bounds.Height, e.Bounds.Height);
    e.Graphics.DrawString((sender as MenuItem).Text, DefaultFont, Brushes.Red, e.Bounds.X + e.Bounds.Height, e.Bounds.Y);
}

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

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

Правда вот необходимость такой кастомизации для меня остается под большим вопросом, т.к. для создания модных интерфейсов с рюшечками в каждом пикселе по желанию заказчика, проще (спорно) и быстрее (однозначно) использовать WPF, UWP или их кросс-платформенные аналоги, вроде AvaloniaUI. Я не отдаю предпочтения какому-то конкретному UI-фреймворку, просто у каждого инструмента есть своя область применения, а действительно красивые и настраиваемые интерфейсы на любой вкус - это не про WinForms. Нет, разумеется все возможно, вопрос сколько понадобится времени для качественной реализации необходимых визуальных эффектов.

READ ALSO
Списки в c# и как их читать?

Списки в c# и как их читать?

у меня достаточно лёгий вопрос (наверное), как считать значения с списка при заданном значении? Например у меня есть список, очень большой...

165
Ошибка при неявном преобразовании [дубликат]

Ошибка при неявном преобразовании [дубликат]

Пишу класс рациональных чиселПри неявном преобразовании возникает ошибка (StackOverflowException), причину которой понять не получается

131
Почему выдается ошибка?

Почему выдается ошибка?

Код вырван из контекста, но я думаю не имеет смысла копировать сюда всю программуЕсть код PHP, который обрабатывает данные, введенные в форму:

260