?? specialmenuprovider.cs
字號:
using System;
using System.ComponentModel;
using System.Collections;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace SpecialMenu
{
/// <summary>
/// Provides all MenuItems the appearance of Office 2003 MenuItems
/// </summary>
[ProvideProperty("NewStyleActive",typeof(MenuItem))]
[ProvideProperty("MenuGlyph",typeof(MenuItem))]
[ToolboxBitmap(typeof(SpecialMenuProvider),"images.SpecialMenuProvider.bmp")]
public class SpecialMenuProvider : Component,IExtenderProvider
{
#region types
/// <summary>
/// Used to store the provided properties in the Hashtable
/// </summary>
internal class MenuItemInfo
{
/// <summary>
/// Creates a new MenuItemInfo struct
/// </summary>
/// <param name="newstyle">specifies if the MenuItem should be painted using Office 2003 style or not</param>
/// <param name="glyph">the image to draw next to the MenuItem</param>
public MenuItemInfo(bool newstyle, Image glyph)
{
this.NewStyle=newstyle;
this.Glyph=glyph;
}
//Fields
public bool NewStyle;
public Image Glyph;
}
/// <summary>
/// Used to collect the information for drawing an Item
/// </summary>
internal class DrawItemInfo
{
/// <summary>
/// Creates a new DawItemInfo struct
/// </summary>
/// <param name="sender">reference to the MenuItem to be painted</param>
/// <param name="e">the DrawItemEventArgs with additional information</param>
/// <param name="glyph">the image to draw next to the item</param>
public DrawItemInfo(object sender, DrawItemEventArgs e, Image glyph)
{
this.Item=(MenuItem)sender;
this.Glyph=glyph;
this.Disabled=(e.State&DrawItemState.Disabled)==DrawItemState.Disabled;
this.Selected=(e.State&DrawItemState.Selected)==DrawItemState.Selected;
this.Checked=(e.State&DrawItemState.Checked)==DrawItemState.Checked;
this.HotLight=(e.State&DrawItemState.HotLight)==DrawItemState.HotLight;
this.Rct=e.Bounds;
}
/// <summary>
/// Evaluates, whether the currently drawn
/// item is an Item in the Top-band of a MainMenu, or not
/// </summary>
public bool IsTopItem
{
get{return Item.Parent==Item.Parent.GetMainMenu();}
}
/// <summary>
/// Gets the associated MainMenu, if possible
/// </summary>
public MainMenu MainMenu
{
get{return Item.Parent.GetMainMenu();}
}
//Fields
public Image Glyph;
public bool HotLight, Selected, Disabled, Checked;
public Rectangle Rct;
public MenuItem Item;
}
#endregion
#region variables
private Container components;//required for designer
private Hashtable _menuitems;//stores the associated menuitems
private Form _owner=null;//the owning form, used for hooking
private IntPtr _hook=IntPtr.Zero;//hook handle
private Win32.HookProc _hookprc=null;//hook delegate
private MenuHook lastHook=null;//reference to last MenuHook
private StringFormat fmt=new StringFormat();//used for painting
private const int _margin=26;//width of the image-band next to each item
private int _lastwidth=0;//width of the last TopItem
private LinearGradientBrush
lnbrs=new LinearGradientBrush(new Point(0,0),new Point(1,0),
Color.FromArgb(227,239,255),Color.FromArgb(135,173,228));//used for every kind of gradient filling
private Pen border=new Pen(Color.FromArgb(0,0,128));//used for boder/selectionframe painting
private SolidBrush hotbrs=new SolidBrush(Color.White);//used for every kind of plain filling
private static Color _imgageband1=Color.FromArgb(227,239,255);//圖片區(qū)顏色1
public static Color imgageband1
{
get
{
return _imgageband1;
}
set
{
_imgageband1=value;
}
}
private static Color _imgageband2=Color.FromArgb(135,173,228);//圖片區(qū)顏色2
public static Color imgageband2
{
get
{
return _imgageband2;
}
set
{
_imgageband2=value;
}
}
private static Color _mainmenuband1=Color.FromArgb(195,218,249);//主菜單區(qū)顏色1
public static Color mainmenuband1
{
get
{
return _mainmenuband1;
}
set
{
_mainmenuband1=value;
}
}
private static Color _mainmenuband2=Color.FromArgb(158,190,245);//主菜單區(qū)顏色2
public static Color mainmenuband2
{
get
{
return _mainmenuband2;
}
set
{
_mainmenuband2=value;
}
}
private static Color _hotlight1=Color.FromArgb(195,218,249);//熱區(qū)顏色1
public static Color hotlight1
{
get
{
return _hotlight1;
}
set
{
_hotlight1=value;
}
}
private static Color _hotlight2=Color.FromArgb(158,190,245);//熱區(qū)顏色2
public static Color hotlight2
{
get
{
return _hotlight2;
}
set
{
_hotlight2=value;
}
}
private Color[][] _cols=new Color[][]//color collection
{
new Color[]{imgageband1,imgageband2},//image band
new Color[]{mainmenuband1,mainmenuband2},//mainmenu band
new Color[]{hotlight1,hotlight2}//selection/hotlight
};
#endregion
/// <summary>
/// ctor
/// </summary>
public SpecialMenuProvider()
{
this.components = new System.ComponentModel.Container ();
_menuitems = new Hashtable();
fmt.HotkeyPrefix=System.Drawing.Text.HotkeyPrefix.Show;
}
/// <summary>
/// Free all used resources
/// </summary>
/// <param name="disposing">specifies, if managed resources are destroyed</param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
#region controller
/// <summary>
/// Can only extend MenuItems
/// </summary>
bool IExtenderProvider.CanExtend(object target)
{
return target is MenuItem;
}
/// <summary>
/// Used for making sure, the owning form is hooked
/// </summary>
public override ISite Site
{
get{return base.Site;}
set
{
base.Site = value;
if (this.Site != null)
{
IDesignerHost host1 = (IDesignerHost) this.Site.GetService(typeof(IDesignerHost));
if ((host1 != null) && (host1.RootComponent is Form))
{
this.OwnerForm = (Form) host1.RootComponent;
}
}
}
}
/// <summary>
/// Measures the item
/// </summary>
private void control_MeasureItem(object sender, MeasureItemEventArgs e)
{
MenuItem mnu=(MenuItem)sender;
if (mnu.Text=="-"){e.ItemHeight=3; return;}//MenuItem is Separator
string txt=mnu.Text.Replace(@"&","");//dont measure '&' because it is replaced by an underline segment
if (mnu.Shortcut!=Shortcut.None && mnu.ShowShortcut)
txt+=GetShortcutString((Keys)mnu.Shortcut);//Get MenuShortcut, if visible
int twidth=(int)e.Graphics.MeasureString(txt,mnu.DefaultItem?//Measure the string
new Font(SystemInformation.MenuFont,FontStyle.Bold)//if the item is the DefaultItem, BOLD Font is used
:SystemInformation.MenuFont
,PointF.Empty,fmt).Width;
if(mnu.Parent==mnu.Parent.GetMainMenu())//Item is in Top-Band of a MainMenu
{
e.ItemHeight=16;
e.ItemWidth=twidth+2;
}
else//item is in a context/popup menu
{
e.ItemHeight=23;
e.ItemWidth=twidth+45+_margin;
}
}
/// <summary>
/// Draw The Item
/// </summary>
private void control_DrawItem(object sender, DrawItemEventArgs e)
{
//collect the information used for drawing
DrawItemInfo inf=new DrawItemInfo(sender,e,
GetMenuGlyph((MenuItem)sender));
if (inf.IsTopItem)//draw TopItem
{
#region draw Band
Form frm=inf.MainMenu.GetForm();//owning form
int width=frm.ClientSize.Width+//width of the MainMenu + Width of one Form Border
(frm.Width-frm.ClientSize.Width)/2;
lnbrs.LinearColors=_cols[1];//use Band colors
lnbrs.Transform=new Matrix(-(float)width,0f,0f,1f,0f,0f);//scale the brush to the band
if (e.Index==inf.MainMenu.MenuItems.Count-1)//item is last in line, draw the rest, too
e.Graphics.FillRectangle(lnbrs,
inf.Rct.X,inf.Rct.Y,width-inf.Rct.X,inf.Rct.Height);
else//item is in line, just draw itself
e.Graphics.FillRectangle(lnbrs,inf.Rct);
#endregion
#region layout
//set the lastwidth field
_lastwidth=0; if (inf.Selected) _lastwidth=e.Bounds.Width;
#endregion
#region draw TopItem
inf.Rct.Width--;inf.Rct.Height--;//resize bounds
lnbrs.Transform=new Matrix(0f,inf.Rct.Height,1f,0f,0f,inf.Rct.Y);//scale brush
if (inf.Selected && !inf.Item.IsParent)//if the item has no subitems,
inf.HotLight=true;//unfolding tab appearance is wrong, use hotlight appearance instead
if (inf.HotLight && !inf.Disabled)//hot light appearance
{
lnbrs.LinearColors=_cols[2];//use hotlight colors
e.Graphics.FillRectangle(lnbrs,inf.Rct);//draw the background
e.Graphics.DrawRectangle(border,inf.Rct);//draw the border
}
else if (inf.Selected && !inf.Disabled)//unfolding tab appearance
{
lnbrs.LinearColors=_cols[0];//use band colors
e.Graphics.FillRectangle(lnbrs,inf.Rct);//draw the background
e.Graphics.DrawLines(border,new Point[]//draw a one-side-open reactangle
{
new Point(inf.Rct.X,inf.Rct.Bottom),
new Point(inf.Rct.X,inf.Rct.Y),
new Point(inf.Rct.Right,inf.Rct.Y),
new Point(inf.Rct.Right,inf.Rct.Bottom)
});
}
if (inf.Item.Text!="")//draw the text, no shortcut
{
SizeF sz;
sz=e.Graphics.MeasureString(inf.Item.Text.Replace(@"&",""),//use no DefaultItem property
e.Font);
e.Graphics.DrawString(inf.Item.Text,e.Font,//draw the text
inf.Disabled?Brushes.Gray:Brushes.Black,//grayed if the Item is disabled
inf.Rct.X+(inf.Rct.Width-(int)sz.Width)/2,
inf.Rct.Y+(inf.Rct.Height-(int)sz.Height)/2,fmt);
}
#endregion
}
else
{
#region draw background, margin and selection
lnbrs.LinearColors=_cols[0];//use band colors
lnbrs.Transform=new Matrix(_margin,0f,0f,1f,-1f,0f);//scale the brush
e.Graphics.FillRectangle(lnbrs,0,inf.Rct.Y,_margin-2,inf.Rct.Height);//draw the band
e.Graphics.FillRectangle(Brushes.White,_margin-2,inf.Rct.Y,//fill the backspace white
2+inf.Rct.Width-_margin,inf.Rct.Height);
if (inf.Item.Text=="-")//Item is a Separator
{
e.Graphics.DrawLine(new Pen(_cols[0][1]),//use the dark band color
inf.Rct.X+_margin+2,inf.Rct.Y+inf.Rct.Height/2,
inf.Rct.Right,inf.Rct.Y+inf.Rct.Height/2);
return;
}
if (inf.Selected && !inf.Disabled)//item is hotlighted
{
hotbrs.Color=_cols[2][0];//use hotlight color
e.Graphics.FillRectangle(hotbrs,//fill the background
inf.Rct.X,inf.Rct.Y,inf.Rct.Width-1,inf.Rct.Height-1);
e.Graphics.DrawRectangle(border,//draw the border
inf.Rct.X,inf.Rct.Y,inf.Rct.Width-1,inf.Rct.Height-1);
}
#endregion
#region draw chevron
if (inf.Checked)//item is checked
{
hotbrs.Color=_cols[2][1];//use dark hot color
e.Graphics.FillRectangle(hotbrs,//fill the background rect
inf.Rct.X+1,inf.Rct.Y+1,inf.Rct.Height-3,inf.Rct.Height-3);
e.Graphics.DrawRectangle(border,//draw the border
inf.Rct.X+1,inf.Rct.Y+1,inf.Rct.Height-3,inf.Rct.Height-3);
if (inf.Glyph==null)//if there is an image, no chevron will be drawed
{
e.Graphics.SmoothingMode=SmoothingMode.AntiAlias;//for a smooth form
e.Graphics.PixelOffsetMode=PixelOffsetMode.HighQuality;
if (!inf.Item.RadioCheck)//draw an check arrow
{
e.Graphics.FillPolygon(Brushes.Black,new Point[]
{
new Point(inf.Rct.X+7,inf.Rct.Y+10),
new Point(inf.Rct.X+10,inf.Rct.Y+13),
new Point(inf.Rct.X+15,inf.Rct.Y+8),
new Point(inf.Rct.X+15,inf.Rct.Y+10),
new Point(inf.Rct.X+10,inf.Rct.Y+15),
new Point(inf.Rct.X+7,inf.Rct.Y+12)
});
}
else//draw a circle
{
e.Graphics.FillEllipse(Brushes.Black,
inf.Rct.X+8,inf.Rct.Y+8,7,7);
}
e.Graphics.SmoothingMode=SmoothingMode.Default;
}
}
#endregion
#region draw image
if (inf.Glyph!=null)
{
if (!inf.Disabled)//draw image grayed
e.Graphics.DrawImageUnscaled(inf.Glyph,
inf.Rct.X+(inf.Rct.Height-inf.Glyph.Width)/2,
inf.Rct.Y+(inf.Rct.Height-inf.Glyph.Height)/2);
else
ControlPaint.DrawImageDisabled(e.Graphics,inf.Glyph,
inf.Rct.X+(inf.Rct.Height-inf.Glyph.Width)/2,
inf.Rct.Y+(inf.Rct.Height-inf.Glyph.Height)/2,
Color.Transparent);
}
#endregion
#region draw text & shortcut
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -