5

我试图向我的上下文菜单项之一添加一个图标,但我做不到。有谁能够帮我?

这是我写的代码:

 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;
          }
     }
4

3 回答 3

13

Lex Li 的回答涵盖了执行此操作的最简单方法:从MainMenu控件切换到控件,该MenuStrip控件为向每个菜单项添加图标提供了内置的、开箱即用的支持。不幸的是,正如我在对他的回答的评论中所讨论的那样,这种解决方案会产生一些丑陋的后果。

特别是,如果您使用该MenuStrip控件,您的菜单在较新版本的 Windows 上将永远看起来难看且不合适,因为它们是由可能永远不会更新的 .NET 代码自定义绘制的。当然,它们在 Windows XP 上看起来很漂亮,但至少 5 年来这已经是老新闻了。从 Windows Vista 开始,菜单看起来完全不同,这也是您的用户对您的应用程序的期望。世界上最酷的图标不会让你看起来更现代。相比:

               MenuStrip(及其小兄弟 ContextMenuStrip)在 Windows Vista 及更高版本上看起来非常丑陋,与使用 MainMenu(及其小兄弟 ContextMenu)实现的平台本机菜单相比

所以更复杂的解决方案是坚持使用MainMenu控件,它实际上使用 Windows 本身绘制的菜单,但编写一些处理添加图标的代码。

幸运的是,Wyatt O'Day 已经为您编写了一个很棒的自定义控件。您所要做的就是下载它,将其放入您的项目中,编译并开始使用它。它是开源的,在 BSD 许可下获得许可,它生成的菜单在所有版本的 Windows 上看起来都是平台原生的从他的网站下载它,或者从他的介绍和 100% 准确的咆哮开始。

结果很棒

               比较 Wyatt 的 VistaMenu 控件在 4 种不同操作系统上的外观:Windows 7、Vista、XP 和 2000。在所有 4 种操作系统上,它看起来就像平台原生菜单,只是图标不同!

于 2012-05-20T09:06:03.893 回答
8

MainMenu/ContextMenu 已过时,您应该改用菜单条类。

改变

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;
于 2012-05-20T08:18:59.177 回答
2

您可以使用函数 SetMenuItemInfo 将图标添加到菜单项。

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;
    }
}
于 2018-10-23T18:11:22.070 回答