Как добавить значок в System.Windows.Forms.MenuItem?

Я пытался добавить значок в один из пунктов моего контекстного меню, но не смог этого сделать. Кто-нибудь может мне помочь?

Вот код, который я написал:

 private System.Windows.Forms.ContextMenu notifyContextMenu;
 private void foo() {
            if (notifyIcon == null) {
                notifyIcon = new System.Windows.Forms.NotifyIcon();   
            }

           if (notifyContextMenu == null) {
               notifyContextMenu = new System.Windows.Forms.ContextMenu();
               notifyContextMenu.MenuItems.Add("Exit");
               // How do I add an icon to this context menu item?
             }
            notifyIcon.ContextMenu =  notifyContextMenu;
          }
     }

Ответы на вопрос(3)

Лекс Ли ответ покрываетsimplest способ сделать это: переключиться сMainMenu контроль кMenuStrip элемент управления, который обеспечивает встроенную, встроенную поддержку для добавления значков к каждому пункту меню. К сожалению, как я уже говорил вкомментарий к его ответу, это решение имеет некоторые ужасные последствия.

В частности, если вы используетеMenuStrip контроль, ваши меню всегда будут выглядеть уродливыми и неуместными в более новых версиях Windows, потому что они специально нарисованы с помощью кода .NET, который, вероятно, никогда не будет обновлен. Конечно, на Windows XP они выглядят изящно, но это уже старые новости как минимум 5 лет. Начиная с Windows Vista меню выглядят совершенно по-другому, и это то же самое, что ожидает и ваш пользователь от вашего приложения. Самые крутые иконки в мире просто не помогут вам выглядеть более современно. Для сравнения:

& # XA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0;MenuStrip (and its little brother, ContextMenuStrip) look downright ugly on Windows Vista and later, compared to the platform native menus, as implemented with MainMenu (and its little brother, ContextMenu)

Таким образом, несколько более сложным решением является придерживатьсяMainMenu контроль, который на самом деле использует меню, нарисованные самой Windows, но напишите некоторый код, который обрабатывает добавление иконки

К счастью, Wyatt O 'Day уже написал отличный пользовательский элемент управления, который делает это для вас. Все, что вам нужно сделать, это загрузить его, поместить в свой проект, скомпилировать и начать его использовать. Это открытый исходный код, лицензированный по лицензии BSD, и он производит меню, которые выглядятplatform native on all versions of Windows, Загрузитьздесь с его сайтаили начните сего введение и 100% точная напыщенная речь.

Результатыawesome:

& # XA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0; & # xA0;Comparing the appearance of Wyatt's VistaMenu control on 4 different operating systems: Windows 7, Vista, XP, and 2000. On all 4, it looks just like the platform native menus, except with icons!

 20 мая 2012 г., 13:42
@Alex: Библиотека, на которую я ссылаюсь, имеет открытый исходный код, что означает, что вы можете посмотреть на код, посмотреть, что он делает, и использовать его в качестве примера для написания собственного кода.
 20 мая 2012 г., 11:31
Повторное использование чего-то вроде VistaMenu является лучшим вариантом. Согласен.
 Alexandre20 мая 2012 г., 13:31
@ Коди Грей, на самом деле я не хотел бы использовать стороннюю библиотеку только для контекстного меню. Я хочу решить эту проблему самостоятельно. Но как? Было бы здорово, если бы мое контекстное меню выглядело как меню Vista и содержало элементы меню с изображениями. Что я должен делать?

чтобы добавить значок к пунктам меню.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    class Program
    {
        static void Main()
        {
            var menu = new ContextMenu();
            menu.Popup += MenuItem_Popup;
            SetMenuInfo(menu.Handle, new MENUINFO());
            var item = menu.MenuItems.Add("Exit", (sender, e) => Application.Exit());
            SetImage(item, Properties.Resources.Image1);

            var notifyIcon = new NotifyIcon
            {
                Icon = Properties.Resources.Icon1,
                ContextMenu = menu
            };
            notifyIcon.Visible = true;
            Application.Run();
            notifyIcon.Visible = false;
        }

        static Dictionary<MenuItem, IntPtr> MenuBitmaps = new Dictionary<MenuItem, IntPtr>();

        static void SetImage(MenuItem item, Image img)
        {
            using (var bmp = new Bitmap(img.Width, img.Height, PixelFormat.Format32bppPArgb))
            {
                using (var g = Graphics.FromImage(bmp)) g.DrawImage(img, 0, 0);
                MenuBitmaps[item] = bmp.GetHbitmap(Color.FromArgb(0));
            }
        }

        static void MenuItem_Popup(object sender, EventArgs e)
        {
            var info = new MENUITEMINFO();
            int i = 0;
            foreach (MenuItem item in ((Menu)sender).MenuItems)
                if (item.Visible)
                {
                    if (MenuBitmaps.TryGetValue(item, out info.hbmpItem))
                        SetMenuItemInfo(((Menu)sender).Handle, i, true, info);
                    i++;
                }
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern bool SetMenuInfo(IntPtr hMenu, MENUINFO lpcmi);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern bool SetMenuItemInfo(IntPtr hMenu, int uItem, bool fByPosition, MENUITEMINFO lpmii);
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public class MENUINFO
    {
        public int cbSize = Marshal.SizeOf(typeof(MENUINFO));
        public int fMask = 0x10; //MIM_STYLE
        public int dwStyle = 0x4000000; //MNS_CHECKORBMP
        public uint cyMax;
        public IntPtr hbrBack;
        public int dwContextHelpID;
        public IntPtr dwMenuData;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public class MENUITEMINFO
    {
        public int cbSize = Marshal.SizeOf(typeof(MENUITEMINFO));
        public int fMask = 0x80; //MIIM_BITMAP
        public int fType;
        public int fState;
        public int wID;
        public IntPtr hSubMenu;
        public IntPtr hbmpChecked;
        public IntPtr hbmpUnchecked;
        public IntPtr dwItemData;
        public IntPtr dwTypeData;
        public int cch;
        public IntPtr hbmpItem;
    }
}
Решение Вопроса

вместо этого следует использовать классы полосы меню.

+ Изменить

notifyContextMenu = new System.Windows.Forms.ContextMenu();
notifyContextMenu.MenuItems.Add("Exit");

в

notifyContextMenu = new System.Windows.Forms.ContextMenuStrip();
var exitMenuItem = notifyContextMenu.Items.Add("Exit");
exitMenuItem.Image = ...;

http://msdn.microsoft.com/en-us/library/system.windows.forms.toolstripitem.image.aspx

Наконец, прикрепите полосу контекстного меню к значку уведомления,

notifyIcon.ContextMenuStrip = notifyContextMenu;
 20 мая 2012 г., 11:29
Даже близко не к тому же ... (Я пробовал, переписывал, настраивал, пробовал еще. Не то же самое. Хуже, сколько бы ты ни делалlook как и родное меню, оно не будетbehave как родные меню.) Но, действительно, лучше ...
 20 мая 2012 г., 10:54
Ну, это не совсем так. Да,...Strip классы новее, но они будут создавать меню, которыеlook совершенно отвратительно в Windows Vista и позже. Вместо того чтобы просить Windows нарисовать меню, они все настраиваются с помощью кода .NET. Они хорошо выглядят в Windows XP и соответствуют настраиваемым меню, используемым в Office XP, но с тех пор технология продвинулась далеко. Использование этих уродливых меню в попытке предотвратить моральное старение кажется мне довольно глупым решением. Ваше приложение никогда не будет выглядеть правильно в современных версиях Windows.
 20 мая 2012 г., 11:22
Хотя встроенная оболочка лучше выглядит в Windows Vista и выше, того же эффекта можно добиться в классах стриптиза с помощью пользовательского средства визуализации,code.google.com/p/szotar/source/browse/trunk/Client/…

Ваш ответ на вопрос