自画菜单的源代码(OwnerDraw Menu)(第一部分)

juqiang 2002-04-27 08:57:52
画checkmark、icon、text的部分,是从别处copy来的,忘记是谁的乐,呵呵!但是要注意GetShortCutName,用了一点小技巧。总之,OwnerDraw的菜单,所有的东西,都要自己来做。

public void DrawCheckmark(Graphics g, Rectangle bounds, bool selected)
{
// ControlPaint.DrawMenuGlyph(g, new Rectangle(bounds.X + 2, bounds.Y + 4, 14, 14), MenuGlyph.Checkmark);
Pen myPen1 = new Pen(Color.Black,2);
Pen myPen2 = new Pen(Color.Black,1);
g.DrawRectangle(myPen2,bounds.Left+1,bounds.Top+1,18,20);
g.DrawLine(myPen1,bounds.Left+8,bounds.Top+12,bounds.Left+12,bounds.Top+16);
g.DrawLine(myPen1,bounds.Left+12,bounds.Top+16,bounds.Left+16,bounds.Top+6);
myPen1.Dispose();
myPen2.Dispose();
}

public void DrawIcon(Graphics g, Image icon, Rectangle bounds, bool selected, bool enabled, bool ischecked)
{
if (enabled)
{
if (selected)
{
ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 4, Color.Black);
g.DrawImage(icon, bounds.Left + 1, bounds.Top + 3);
}
else
{
g.DrawImage(icon, bounds.Left + 2, bounds.Top + 4);
}
}
else
ControlPaint.DrawImageDisabled(g, icon, bounds.Left + 2, bounds.Top + 4, SystemColors.HighlightText);
}

public void DrawSeparator(Graphics g, Rectangle bounds)
{
int y = bounds.Y + bounds.Height / 2;
g.DrawLine(new Pen(SystemColors.ControlDark), bounds.X + SystemInformation.SmallIconSize.Width + 7, y, bounds.X + bounds.Width - 2, y);
}

public void DrawBackground(Graphics g, Rectangle bounds, DrawItemState state, bool toplevel, bool hasicon)
{
bool selected = (state & DrawItemState.Selected) > 0;

if (selected || ((state & DrawItemState.HotLight) > 0))
{
if (toplevel && selected)
{ // draw toplevel, selected menuitem
g.FillRectangle(new SolidBrush(ibgcolor), bounds);
ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, bounds.Width, bounds.Height, Border3DStyle.Flat, Border3DSide.Top | Border3DSide.Left | Border3DSide.Right);
}
else
{ // draw menuitem, selected OR toplevel, hotlighted
g.FillRectangle(new SolidBrush(sbcolor), bounds);
g.DrawRectangle(new Pen(sbbcolor), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1);
}
}
else
{
if (!toplevel)
{ // draw menuitem, unselected
g.FillRectangle(new SolidBrush(ibgcolor), bounds);
bounds.X += SystemInformation.SmallIconSize.Width + 5;
bounds.Width -= SystemInformation.SmallIconSize.Width + 5;
g.FillRectangle(new SolidBrush(bgcolor), bounds);
}
else
{
// draw toplevel, unselected menuitem
g.FillRectangle(SystemBrushes.Menu, bounds);
}
}
}

public void DrawMenuText(Graphics g, Rectangle bounds, string text, string shortcut, bool enabled, bool toplevel, DrawItemState state)
{
Text = state.ToString();
StringFormat stringformat = new StringFormat();
stringformat.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show;//((state & DrawItemState.NoAccelerator)==DrawItemState.NoAccelerator) ? System.Drawing.Text.HotkeyPrefix.Hide : System.Drawing.Text.HotkeyPrefix.Show;
int textwidth = (int)(g.MeasureString(text, SystemInformation.MenuFont).Width);

int x = toplevel ? bounds.Left + (bounds.Width - textwidth) / 2: bounds.Left + TEXTSTART;
int y = bounds.Top + 6;
Brush brush = null;
if (!enabled)
brush = new SolidBrush(Color.FromArgb(120, SystemColors.MenuText));
else
brush = new SolidBrush(Color.Black);
g.DrawString(text, SystemInformation.MenuFont, brush, x, y, stringformat);
// g.DrawString(shortcut, SystemInformation.MenuFont, brush, bounds.Left + 130, y, stringformat);
textwidth = (int)(g.MeasureString(shortcut, SystemInformation.MenuFont).Width);
g.DrawString(shortcut, SystemInformation.MenuFont, brush, bounds.Right - 20 - textwidth, y, stringformat);
}

private string GetShortcutName(MenuItem item)
{
string shortcut,ret = "";

shortcut = item.Shortcut.ToString();
if(shortcut.IndexOf("Alt")>=0)
{
ret = "Alt+" + shortcut.Substring(3);
}
else if(shortcut.IndexOf("CtrlShift")>=0)
{
ret = "Ctrl+Shift+" + shortcut.Substring(9);
}
else if(shortcut.IndexOf("Ctrl")>=0)
{
ret = "Ctrl+" + shortcut.Substring(4);
}
else if(shortcut.IndexOf("Shift")>=0)
{
ret = "Shift+" + shortcut.Substring(5);
}

return ret;
}


private void MenuDrawItemEvent(object sender,System.Windows.Forms.DrawItemEventArgs e)
{
MenuItem item = (MenuItem)sender;
string shortcut = GetShortcutName(item);
Graphics g = e.Graphics;
Rectangle bounds = e.Bounds;
bool selected = (e.State & DrawItemState.Selected) > 0;
bool toplevel = (item.Parent == item.Parent.GetMainMenu());
bool hasicon = (item.MergeOrder>0);

DrawBackground(g, bounds, e.State, toplevel, hasicon);
if (hasicon)
{
Bitmap myBmp = new Bitmap(imageList1.Images[item.MergeOrder - 1]);
DrawIcon(g, (Image)(myBmp), bounds, selected, item.Enabled, item.Checked);
}
else
{
if (item.Checked)
{
DrawCheckmark(g, bounds, selected);
}
}

if (item.Text == "-")
{
DrawSeparator(g,bounds);
}
else
{
DrawMenuText(g, bounds, item.Text, shortcut, Enabled, toplevel, e.State);
}


// if(e.State==DrawItemState.NoAccelerator)return;
}

private void MenuMeasureItemEvent(object sender, System.Windows.Forms.MeasureItemEventArgs e)
{
MenuItem item = (MenuItem)sender;
string shortcut = GetShortcutName(item);
if (item.Text == "-")
{
e.ItemHeight = 4;
}
else
{
e.ItemHeight = SystemInformation.MenuHeight+4;
}
int textwidth = (int)(e.Graphics.MeasureString(Text + shortcut, SystemInformation.MenuFont).Width);
if (item.Parent == item.Parent.GetMainMenu())
e.ItemWidth = textwidth - 5; // 5 is a magic number
else
e.ItemWidth = Math.Max(160, textwidth + 50);
}

private void SetMenuProperty(MenuItem item)
{
//递归设置每个menuItem的OwnerDraw的event
try
{
foreach(MenuItem tmp in item.MenuItems)
{
tmp.OwnerDraw = true;
tmp.DrawItem += new System.Windows.Forms.DrawItemEventHandler(MenuDrawItemEvent);
tmp.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(MenuMeasureItemEvent);
SetMenuProperty(tmp);
}
}
catch
{

}
}

private void Form1_Load(object sender, System.EventArgs e)
{
try
{
MainMenu myMainMenu = this.Menu;
foreach(MenuItem myItem in myMainMenu.MenuItems)
{
//如果屏蔽下面三句,那么mainmenu将不进行重画,下面的subMenuitems进行重画。但是如果不屏蔽,主菜单显示的焦点框不正确,怎么这么小?!
// myItem.OwnerDraw = true;
// myItem.DrawItem += new System.Windows.Forms.DrawItemEventHandler(MenuDrawItemEvent);
// myItem.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(MenuMeasureItemEvent);
SetMenuProperty(myItem);
}
}
catch
{

}
}
...全文
75 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
BitNomad 2002-04-27
  • 打赏
  • 举报
回复
我只想在menuitem上画东西呀!
也需要重载menu吗?
juqiang 2002-04-27
  • 打赏
  • 举报
回复
menuitem和menu,都要override
BitNomad 2002-04-27
  • 打赏
  • 举报
回复
我想把自画菜单作成是组件,我应该重载哪个类呢?是menu还是menuitem?

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧