?? specialmenuprovider.cs
字號:
SizeF sz;
Font fnt=
inf.Item.DefaultItem?new Font(e.Font,FontStyle.Bold):
SystemInformation.MenuFont;//set font to BOLD if Item is a DefaultItem
if (inf.Item.Text!="")
{
sz=e.Graphics.MeasureString(inf.Item.Text,fnt);//draw text
e.Graphics.DrawString(inf.Item.Text,fnt,
inf.Disabled?Brushes.Gray:Brushes.Black,
inf.Rct.X+inf.Rct.Height+5,
inf.Rct.Y+(inf.Rct.Height-(int)sz.Height)/2,fmt);
}
if (inf.Item.Shortcut!=Shortcut.None && inf.Item.ShowShortcut)
{
string shc=GetShortcutString((Keys)inf.Item.Shortcut);
sz=e.Graphics.MeasureString(shc,fnt);//draw shortcut
e.Graphics.DrawString(shc,fnt,
inf.Disabled?Brushes.Gray:Brushes.Black,
inf.Rct.Right-(int)sz.Width-16,
inf.Rct.Y+(inf.Rct.Height-(int)sz.Height)/2);
}
#endregion
}
}
#endregion
#region provideproperty::NewStyleActive
/// <summary>
/// Specifies wheter NewStyle-Drawing is enabled or not
/// </summary>
[Description("Specifies wheter NewStyle-Drawing is enabled or not")]
[Browsable(false)]
public bool GetNewStyleActive(MenuItem control)
{
return true;//make sure every new item is selected
}
/// <summary>
/// Specifies wheter NewStyle-Drawing is enabled or not
/// </summary>
public void SetNewStyleActive(MenuItem control, bool value)
{
if (!value)
{
if (_menuitems.Contains(control))//remove it from the collection
{
_menuitems.Remove(control);
}
//reset to system drawing
control.OwnerDraw=false;
control.MeasureItem-=new MeasureItemEventHandler(control_MeasureItem);
control.DrawItem-=new DrawItemEventHandler(control_DrawItem);
}
else
{
//add it or change the value
if (!_menuitems.Contains(control))
_menuitems.Add(control,new MenuItemInfo(true,null));
else
((MenuItemInfo)_menuitems[control]).NewStyle=true;
//set to owner drawing
control.OwnerDraw=true;
control.MeasureItem+=new MeasureItemEventHandler(control_MeasureItem);
control.DrawItem+=new DrawItemEventHandler(control_DrawItem);
}
}
#endregion
#region provideproperty::MenuGlyph
/// <summary>
/// Specifies the image displayed next to the MenuItem
/// </summary>
[Description("Specifies the image displayed next to the MenuItem")]
[DefaultValue(null)]
public Image GetMenuGlyph(MenuItem control)
{
MenuItemInfo ret=(MenuItemInfo)_menuitems[control];
if (ret==null) return null;
return ret.Glyph;
}
/// <summary>
/// Specifies the image displayed next to the MenuItem
/// </summary>
public void SetMenuGlyph(MenuItem control, Image value)
{
if (value==null)
{
if (_menuitems.Contains(control))//set the image property in the collection to NULL
{
((MenuItemInfo)_menuitems[control]).Glyph=null;
if(((MenuItemInfo)_menuitems[control]).NewStyle==false)
_menuitems.Remove(control);
}
}
else
{
//add the MenuItem to the collection or change the image value
if (!_menuitems.Contains(control))
{
_menuitems.Add(control,new MenuItemInfo(true,value));
control.OwnerDraw=true;
control.MeasureItem+=new MeasureItemEventHandler(control_MeasureItem);
control.DrawItem+=new DrawItemEventHandler(control_DrawItem);
}
else
((MenuItemInfo)_menuitems[control]).Glyph=value;
}
}
#endregion
#region hooker
[Browsable(false)]
public Form OwnerForm
{
get{return _owner;}
set
{
if (_hook!=IntPtr.Zero)//uninstall hook
{
Win32.UnhookWindowsHookEx(_hook);
_hook=IntPtr.Zero;
}
_owner = value;
if (_owner != null)
{
if (_hookprc == null)
{
_hookprc = new Win32.HookProc(OnHookProc);
}
_hook = Win32.SetWindowsHookEx(Win32.WH_CALLWNDPROC,//install hook
_hookprc, IntPtr.Zero, Win32.GetWindowThreadProcessId(_owner.Handle, 0));
}
}
}
/// <summary>
/// process all message posted to the application
/// </summary>
private int OnHookProc(int code, IntPtr wparam, ref Win32.CWPSTRUCT cwp)
{
if (code == 0)
{
switch (cwp.message)
{
case Win32.WM_CREATE://a window is created
{
StringBuilder builder1 = new StringBuilder(0x40);
int num2 = Win32.GetClassName(cwp.hwnd, builder1, builder1.Capacity);
string text1 = builder1.ToString();
if (string.Compare(text1,"#32768",false) == 0)//test if the class name
//identifies the control as a MenuItem
{
this.lastHook = new MenuHook(this,_lastwidth);
this.lastHook.AssignHandle(cwp.hwnd);
_lastwidth=0;
/*
* We don't use a local variable, because the GC
* would destroy it immediately afte leaving the
* function. Instead we use one private variable
* ,because there's always only one ContextMenu
* on the Desktop and the Hooker is destroyed
* when another ContextMenu lights up.
*/
}
break;
}
case Win32.WM_DESTROY://owner is destroyed, unhook all
{
if ((cwp.hwnd == _owner.Handle) && _hook!=IntPtr.Zero)
{
Win32.UnhookWindowsHookEx(_hook);
_hook = IntPtr.Zero;
}
break;
}
}
}
return Win32.CallNextHookEx(_hook, code, wparam, ref cwp);
}
#endregion
#region helper
/// <summary>
/// gets the brush to draw the image-band next to each menuitem
/// </summary>
[Browsable(false)]
public LinearGradientBrush MarginBrush
{
get
{
lnbrs.LinearColors=_cols[0];
lnbrs.Transform=new Matrix(_margin,0f,0f,1f,1f,0f);
return lnbrs;
}
}
/// <summary>
/// gets the width of the image-band next to each menuitem
/// </summary>
[Browsable(false)]
public int MarginWidth
{
get{return _margin;}
}
/// <summary>
/// returns the Pen used to paint the border of a menuitem
/// </summary>
[Browsable(false)]
public Pen BorderPen
{
get{return border;}
}
private string GetShortcutString(Keys shortcut)
{
return TypeDescriptor.GetConverter(typeof(Keys))
.ConvertToString(shortcut);
}
#endregion
#region public properties
/// <summary>
/// the color of the border of the selection frame and the popup menu itself
/// </summary>
[DefaultValue(typeof(Color),"0,0,128")]
[Category("Colors")]
[Description("the color of the border of the selection frame and the popup menu itself")]
public Color BorderColor
{
get{return border.Color;}
set{border.Color=Color.FromArgb(255,value);}
}
/// <summary>
/// specifies the lighter color of a preselected menuitem
/// </summary>
[DefaultValue(typeof(Color),"255,244,204")]
[Category("Colors")]
[Description("specifies the lighter color of a preselected menuitem")]
public Color HotLightGradientLight
{
get{return _cols[2][0];}
set{_cols[2][0]=Color.FromArgb(255,value);}
}
/// <summary>
/// specifies the darker color of a preselected menuitem
/// </summary>
[DefaultValue(typeof(Color),"255,214,154")]
[Category("Colors")]
[Description("specifies the darker color of a preselected menuitem")]
public Color HotLightGradientDark
{
get{return _cols[2][1];}
set{_cols[2][1]=Color.FromArgb(255,value);}
}
/// <summary>
/// the color on the right side of a mainmenu
/// </summary>
[DefaultValue(typeof(Color),"195,218,249")]
[Category("Colors")]
[Description("the color on the right side of a mainmenu")]
public Color BandGradientLight
{
get{return _cols[1][0];}
set{_cols[1][0]=Color.FromArgb(255,value);}
}
/// <summary>
/// the color on the left side of a mainmenu
/// </summary>
[DefaultValue(typeof(Color),"158,190,245")]
[Category("Colors")]
[Description("the color on the left side of a mainmenu")]
public Color BandGradientDark
{
get{return _cols[1][1];}
set{_cols[1][1]=Color.FromArgb(255,value);}
}
/// <summary>
/// sets or gets the lighter color of the image-band next to each menuitem
/// </summary>
[DefaultValue(typeof(Color),"227,239,255")]
[Category("Colors")]
[Description("sets or gets the lighter color of the image-band next to each menuitem")]
public Color ItemGradientLight
{
get{return _cols[0][0];}
set{_cols[0][0]=Color.FromArgb(255,value);}
}
/// <summary>
/// sets or gets the darker color of the image-band next to each menuitem
/// </summary>
[DefaultValue(typeof(Color),"135,173,228")]
[Category("Colors")]
[Description("sets or gets the darker color of the image-band next to each menuitem")]
public Color ItemGradientDark
{
get{return _cols[0][1];}
set{_cols[0][1]=Color.FromArgb(255,value);}
}
#endregion
}
/// <summary>
/// This class is used to hook the events posted to a context/popup menu
/// </summary>
internal class MenuHook:NativeWindow
{
#region variablen
private SpecialMenuProvider _parent=null;
private int _lastwidth=0;
#endregion
public MenuHook(SpecialMenuProvider parent, int lastwidth)
{
if (parent==null)
throw new ArgumentNullException();//parent property mustn't be NULL
_parent=parent;//MenuExtender with drawing paramenters
_lastwidth=lastwidth;//width of the topItem unfolding the Menu or 0
}
#region controller
/// <summary>
/// Hook window messages of a context/popup menu
/// </summary>
/// <param name="m">windows message</param>
protected override void WndProc(ref Message m)
{
switch(m.Msg)
{
case Win32.WM_NCPAINT://menu unfolding
{
IntPtr windc = Win32.GetWindowDC(m.HWnd);
Graphics gr = Graphics.FromHdc(windc);
this.DrawBorder(gr);
Win32.ReleaseDC(m.HWnd, windc);
gr.Dispose();
m.Result = IntPtr.Zero;
break;
}
case Win32.WM_PRINT://user presses 'PRINT'
{
base.WndProc(ref m);
IntPtr dc = m.WParam;
Graphics gr = Graphics.FromHdc(dc);
this.DrawBorder(gr);
Win32.ReleaseDC(m.HWnd, dc);
gr.Dispose();
break;
}
default:
{
base.WndProc(ref m);
break;
}
}
}
#endregion
/// <summary>
/// This draws the missing parts in the margin of a menuitem
/// </summary>
/// <param name="gr">the graphics surface to draw on</param>
private void DrawBorder(Graphics gr)
{
//calculate the space of the context/popup menu
Rectangle clip=Rectangle.Round(gr.VisibleClipBounds);
clip.Width--; clip.Height--;
int margin=_parent.MarginWidth;
//fill the missing gradient parts using extender's brush
gr.FillRectangle(_parent.MarginBrush,clip.X+1,clip.Y+1,2,clip.Height-2);
gr.FillRectangle(_parent.MarginBrush,clip.X+1,clip.Y+1,margin,2);
gr.FillRectangle(_parent.MarginBrush,clip.X+1,clip.Bottom-2,margin,2);
//fill the other edges white, so using old windows style will not change the appearance
gr.FillRectangle(Brushes.White,clip.X+margin+1,clip.Y+1,clip.Width-margin-1,2);
gr.FillRectangle(Brushes.White,clip.X+margin+1,clip.Bottom-2,clip.Width-margin-1,2);
gr.FillRectangle(Brushes.White,clip.Right-2,clip.Y+1,2,clip.Height);
//draw the border with a little white line on the top,
//then it looks like a tab unfolding.
//in contextmenus: _lastwidth==0
gr.DrawLine(Pens.White,clip.X+1,clip.Y,clip.X+_lastwidth-2,clip.Y);
gr.DrawLine(_parent.BorderPen,clip.X,clip.Y,clip.X,clip.Bottom);
gr.DrawLine(_parent.BorderPen,clip.X,clip.Bottom,clip.Right,clip.Bottom);
gr.DrawLine(_parent.BorderPen,clip.Right,clip.Bottom,clip.Right,clip.Y);
gr.DrawLine(_parent.BorderPen,clip.Right,clip.Y,clip.X+_lastwidth-1,clip.Y);
}
}
/// <summary>
/// This class provides static access to some Win32 API
/// </summary>
internal abstract class Win32
{
[DllImport("user32.dll", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
public static extern int CallNextHookEx(IntPtr hookHandle, int code, IntPtr wparam, ref CWPSTRUCT cwp);
[DllImport("user32.dll", EntryPoint="GetClassNameA", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
public static extern int GetClassName(IntPtr hwnd, StringBuilder className, int maxCount);
[DllImport("user32", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
public static extern IntPtr GetWindowDC(IntPtr hwnd);
[DllImport("user32.dll", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
public static extern int GetWindowThreadProcessId(IntPtr hwnd, int ID);
[DllImport("user32", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
public static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("user32.dll", EntryPoint="SetWindowsHookExA", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
public static extern IntPtr SetWindowsHookEx(int type, HookProc hook, IntPtr instance, int threadID);
[DllImport("user32.dll", CharSet=CharSet.Ansi, SetLastError=true, ExactSpelling=true)]
public static extern bool UnhookWindowsHookEx(IntPtr hookHandle);
public const int WH_CALLWNDPROC = 4;
public const int WM_CREATE = 1;
public const int WM_DESTROY = 2;
public const int WM_NCPAINT = 0x85;
public const int WM_PRINT = 0x317;
[StructLayout(LayoutKind.Sequential)]
public struct CWPSTRUCT
{
public IntPtr lparam;
public IntPtr wparam;
public int message;
public IntPtr hwnd;
}
public delegate int HookProc(int code, IntPtr wparam, ref Win32.CWPSTRUCT cwp);
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -