我尝试在我的某个上下文菜单项中添加一个图标,但我无法做到。有人能帮助我吗?
这是我写的代码:
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;
}
}
答案 0 :(得分:10)
Lex Li's answer涵盖最简单的方式:从MainMenu
控件切换到MenuStrip
控件,该控件提供内置的,不在内的 - 支持为每个菜单项添加图标。不幸的是,正如我在a comment中所讨论的那样,这个解决方案会产生一些难看的后果。
特别是,如果您使用MenuStrip
控件,您的菜单将永远看起来很丑,并且在较新版本的Windows上不合适,因为它们是由.NET代码自定义绘制的,可能永远不会更新。当然,他们在Windows XP上看起来很光滑,但这已经是至少5年的旧闻了。从Windows Vista开始,菜单看起来完全不同,这也是您的用户对您的应用程序的期望。世界上最酷的图标不会让你看起来更现代。比较:
所以更复杂的解决方案是坚持MainMenu
控件,它实际上使用Windows自己绘制的菜单,但是编写一些处理添加图标的代码。
幸运的是,Wyatt O'Day已经为您编写了一个很棒的自定义控件。您所要做的就是下载它,将其放入您的项目,编译并开始使用它。它是开源的,在BSD许可下获得许可,并且它生成的菜单在所有版本的Windows 上看起来都是平台原生的。下载here from his website,或以his introduction and 100% accurate rant开头。
结果 awesome :
答案 1 :(得分:5)
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;
答案 2 :(得分:0)
您可以使用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;
}
}