我的方法是重寫MenuItem類,在寫的過程中發現用GDI+實際測量出來的文本的大小不是很准確,還有文本也不能很好對齊,固在代碼裡可以時常看到很多多加上去的數字.我想原理就不用我講了吧,下面的代碼注釋的很清楚了:
CODE:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace OfficeMenu
{
/// <summary>
/// Class1 的摘要說明。
/// </summary>
public class OfficeMenuItem:MenuItem
{
public OfficeMenuItem(bool IsApplyOfficeMenu,string ItemText)
{
if(IsApplyOfficeMenu)
{
this.Text=ItemText;
this.OwnerDraw=true;
font=new Font("宋體",9f,GraphicsUnit.Point);
}
else
{
this.Text=ItemText;
this.OwnerDraw=false;
}
}
private Font font;
private StringFormat strFormat=new StringFormat();
private string ItemText="";
private string iconPath="";
//定義繪制的時候的各種筆刷
private LinearGradientBrush TopMenuHostLightBrush;
private SolidBrush TopMenuDefaultBrush;
private SolidBrush FontDefaultBrush;
private LinearGradientBrush TopMenuSelectedBrush;
private SolidBrush MenuDefaultBrush;
private SolidBrush MenuDefaultSelectedBrush;
private SolidBrush MenuCheckBrush;
private LinearGradientBrush MenuSideBarBrush;
private SolidBrush MenuDefaultGrayedBrush;
//定義繪制的時候所需的各種線條
private Pen TopMenuPen;
private Pen MenuDefaultPen;
//定義需要的矩形結構
private Rectangle SideBarRect;
private Rectangle CheckedRect;
private Rectangle TopMenuRect;
private Rectangle ShortcutRect;
//定義圖標
public string IconPath
{
get
{
return iconPath;
}
set
{
iconPath=value;
}
}
//判斷菜單是否是頂級菜單
private bool CheckIsTop()
{
if(typeof(MainMenu)==this.Parent.GetType())
{
return true;
}
else
{
return false;
}
}
//獲取菜單的快捷鍵
private string GetShortCut()
{
string shortcut="";
try
{
if(this.ShowShortcut==true && (!this.IsParent) && (!(this.Shortcut==Shortcut.None)))
{
shortcut=this.Shortcut.ToString();
shortcut=shortcut.Replace("Ctrl","Ctrl+");
shortcut=shortcut.Replace("Alt","Alt+");
shortcut=shortcut.Replace("Shift","Shift+");
}
}
catch
{
return "";
}
return shortcut;
}
//重寫測量函數
protected override void OnMeasureItem(MeasureItemEventArgs e)
{
base.OnMeasureItem (e);
try
{
ItemText=this.Text;
SizeF SizeMenuText;
if(this.ItemText=="-") //設置分割線的高度
{
e.ItemHeight=5;
return;
}
string getedShortcut=this.GetShortCut();
if(!this.CheckIsTop()) //如果不是頂級菜單
{
SizeMenuText=e.Graphics.MeasureString(ItemText+"".PadRight(4,' ')+getedShortcut,this.font);
e.ItemWidth=Convert.ToInt32(SizeMenuText.Width)+26;
}
else
{
SizeMenuText=e.Graphics.MeasureString(ItemText,this.font);
e.ItemWidth=Convert.ToInt32(SizeMenuText.Width)-4;
}
if(this.Visible)
{
e.ItemHeight=Convert.ToInt32(SizeMenuText.Height)+6;
}
else
{
e.ItemHeight=0;
}
}
catch
{
e.ItemHeight=20;
e.ItemWidth=80;
}
}
//重寫繪圖函數
protected override void OnDrawItem(DrawItemEventArgs e)
{
if(this.Visible)
{
base.OnDrawItem (e);
Rectangle MenuRect=e.Bounds;
ItemText=this.Text;
Graphics g=e.Graphics;
//繪制邊框時需要的特殊矩形
SideBarRect=new Rectangle(MenuRect.X,MenuRect.Y,25,MenuRect.Height);
//繪制選擇框時需要的矩形
CheckedRect=new Rectangle(MenuRect.X+1,MenuRect.Y+1,24,MenuRect.Height-2);
//繪制頂菜單時需要的矩形
TopMenuRect=new Rectangle(MenuRect.X+1,MenuRect.Y+3,MenuRect.Width,MenuRect.Height);
//繪制shortcut用到的矩形
ShortcutRect=new Rectangle(MenuRect.X,MenuRect.Y+4,MenuRect.Width-10,MenuRect.Height);
//定義繪制的時候的各種筆刷
TopMenuHostLightBrush=new LinearGradientBrush(MenuRect,Color.White,Color.FromArgb(220,134,56),90f); //頂級菜單發生HOTLIGHT 時顯示的顏色
TopMenuDefaultBrush=new SolidBrush(SystemColors.Control); //頂級菜單默認的顏色
FontDefaultBrush=new SolidBrush(Color.Black); //字體默認的顏色
TopMenuSelectedBrush=new LinearGradientBrush(MenuRect,Color.White,Color.FromArgb(95,109,126),90f); //頂級菜單選中時的顏色
MenuDefaultBrush=new SolidBrush(Color.White); //默認菜單的顏色
MenuDefaultSelectedBrush=new SolidBrush(Color.FromArgb(247,218,157)); //菜單選中時的顏色
MenuCheckBrush=new SolidBrush(Color.FromArgb(225,143,70)); //當菜單CHECKED屬性為真的時顯示的顏色
MenuSideBarBrush=new LinearGradientBrush(SideBarRect,Color.White,Color.FromArgb(149,160,174),0f);//繪制側欄
MenuDefaultGrayedBrush=new SolidBrush(Color.FromArgb(105,105,105));//菜單不可用時
//定義繪制的時候所需的各種線條
TopMenuPen=new Pen(Brushes.Black,1f); //頂級菜單的邊框
MenuDefaultPen=new Pen(new SolidBrush(Color.FromArgb(60,60,115)),1f); //正常選擇時的邊框
//開始繪制****************************************************
if(this.CheckIsTop() && this.ItemText!="-") //如果是頂級菜單
{
bool IsDraw=false;//定義一個變量保證正常顯示的只繪制一次 避免浪費資源
strFormat.Alignment=StringAlignment.Center;
if(IsDraw==false) //繪制正常顯示時的圖像
{
g.FillRectangle(TopMenuDefaultBrush,MenuRect);
g.DrawString(ItemText,this.font,FontDefaultBrush,TopMenuRect,strFormat);
}
//繪制HOTLIGHT時的圖像
if((e.State & DrawItemState.HotLight)==DrawItemState.HotLight) //突出顯示時
{
g.FillRectangle(TopMenuHostLightBrush,MenuRect);
g.DrawRectangle(TopMenuPen,MenuRect.X,MenuRect.Y,MenuRect.Width-1,MenuRect.Height-1);
g.DrawString(ItemText,this.font,FontDefaultBrush,TopMenuRect,strFormat);
IsDraw=true;
}
//繪制菜單選中時的圖像
if((e.State & DrawItemState.Selected)==DrawItemState.Selected)
{
g.FillRectangle(TopMenuSelectedBrush,MenuRect);
g.DrawRectangle(TopMenuPen,MenuRect.X,MenuRect.Y,MenuRect.Width-1,MenuRect.Height-1);
g.DrawString(ItemText,this.font,FontDefaultBrush,TopMenuRect,strFormat);
IsDraw=true;
}
}
else //非頂級菜單時
{
if(this.ItemText!="-")
{
bool IsDraw=false;
if(IsDraw==false) //正常顯示時
{
g.FillRectangle(MenuDefaultBrush,MenuRect);
g.FillRectangle(MenuSideBarBrush,MenuRect.X,MenuRect.Y,25,MenuRect.Height);
g.DrawString(ItemText,this.font,FontDefaultBrush,MenuRect.X+26,MenuRect.Y+4);
//繪制shortcut
string shortcut=this.GetShortCut();
strFormat.Alignment=StringAlignment.Far;
g.DrawString(shortcut,this.font,FontDefaultBrush,ShortcutRect,strFormat);
//繪制圖標
this.DrawIcon(g);
}
if((e.State & DrawItemState.Selected)==DrawItemState.Selected) //選中時
{
this.DrawItem_Selected(g,MenuRect,ItemText);
IsDraw=true;
}
if((e.State & DrawItemState.Grayed)==DrawItemState.Grayed) //不可用時
{
g.DrawString(ItemText,this.font,MenuDefaultGrayedBrush,MenuRect.X+26,MenuRect.Y+4);
IsDraw=true;
}
if(!this.IsParent)
{
if((e.State & DrawItemState.Checked)==DrawItemState.Checked) //選擇時
{
g.FillRectangle(MenuCheckBrush,CheckedRect);
g.DrawRectangle(new Pen(Brushes.Black,1f),MenuRect.X+1,MenuRect.Y+1,23,MenuRect.Height-3);
g.DrawString("√",this.font,FontDefaultBrush,MenuRect.X+3,MenuRect.Y+4);
IsDraw=true;
}
if(this.Checked==true && ((e.State & DrawItemState.Selected)==DrawItemState.Selected)) //選中且Checked屬性為真時
{
g.FillRectangle(new SolidBrush(Color.FromArgb(255,91,91)),CheckedRect);
g.DrawRectangle(new Pen(Brushes.Black,1f),MenuRect.X+1,MenuRect.Y+1,23,MenuRect.Height-3);
g.DrawString("√",this.font,FontDefaultBrush,MenuRect.X+3,MenuRect.Y+4);
IsDraw=true;
}
}
}
else //畫分割線
{
SolidBrush PartitionLineBrush=new SolidBrush(Color.FromArgb(128,128,128));
Pen PartitionPen=new Pen(PartitionLineBrush,1f);
g.FillRectangle(MenuDefaultBrush,MenuRect);
g.FillRectangle(MenuSideBarBrush,MenuRect.X,MenuRect.Y,25,MenuRect.Height);
g.DrawLine(PartitionPen,new Point(MenuRect.X+27,MenuRect.Y+2),new Point(MenuRect.X+27+(MenuRect.Width-26),MenuRect.Y+2));
}
}
}
}
//畫圖標
private void DrawIcon(Graphics g)
{
if(this.CheckIsTop()==false && this.IconPath!="" && this.IsParent==false && this.Checked==false)
{
try
{
Bitmap iconImage=new Bitmap(this.IconPath);
int imageWidth=iconImage.Width;
int imageHeight=iconImage.Height;
if(imageWidth<=CheckedRect.Width && imageHeight<=CheckedRect.Height)
{
int ImageRecWidthMistake=CheckedRect.Width-imageWidth;
float Mistake_2=(float)ImageRecWidthMistake/2f;
g.DrawImage(iconImage,CheckedRect.X+(int)Mistake_2,CheckedRect.Y,imageWidth,imageHeight);
}
else
{
g.DrawImage(iconImage,CheckedRect);
}
}
catch
{
throw new IconNotFindException("不能創建圖標,可能是路徑不能也可能是不支持此格式");
}
}
}
//由於再繪制的過程中選中的動作時需要執行兩次一樣的代碼 固在這裡用了一個函數
private void DrawItem_Selected(Graphics g,Rectangle rec,string itemtext)
{
SolidBrush tmpBrush;
if(this.Enabled)
{
tmpBrush=FontDefaultBrush;
}
else
{
tmpBrush=MenuDefaultGrayedBrush;
}
//正常顯示
g.FillRectangle(MenuDefaultSelectedBrush,rec);
g.DrawRectangle(MenuDefaultPen,rec.X,rec.Y,rec.Width-1,rec.Height-1);
g.DrawString(itemtext,this.font,tmpBrush,rec.X+26,rec.Y+4);
//顯示shortcut
string shortcut=this.GetShortCut();
strFormat.Alignment=StringAlignment.Far;
g.DrawString(shortcut,this.font,tmpBrush,ShortcutRect,strFormat);
//畫圖標
this.DrawIcon(g);
}
}
//自定義異常
public class IconNotFindException:ApplicationException
{
public IconNotFindException(string message)
:base(message)
{
}
}
}