Owner Draw Menus in C#

很多 Windows 应用程序中的控件可以手工绘制,来达到更加生动的效果,可以使用窗体组件的 ownerdraw 属性来达到这个目的。 Menu 就是一个这样的组件,它允许我们手工绘制其界面。

这篇文章的主要目的在于向你解释如何用特定的字体,图片,背景颜色以及其他的图形对象来绘制自己定制的菜单。

第一步:创建一个简单的 Windows Form 应用程序
点击文件 - > 新建 -> 项目 - > 创建一个新的 C # WindowsForm 应用程序 : OwnerDrawMenu

在默认的窗体上,添加一个 “ MainMenu ” 控件 , 创建如下形式的菜单

![](http://dev.csdn.net/article/21/C:/Documents and Settings\it11.BBKAV\桌面\pic1.gif)

在这里我们需要手工绘制的菜单不仅仅是顶级菜单,而且包括子菜单
对每个菜单项,设置其 OwnerDraw 属性为 “True”

对每个菜单项而言,手工绘制将调用如下两个函数 ..

DrawItem . 这个函数里将加入实际的绘图逻辑 .
Measure Item . 这个函数被调用于设置菜单项的高度和宽度值 .
在菜单项的事件列表里,我们将为其添加这两个事件函数 .

选择 “ File ” 菜单的属性页 .

点击 “ Event ” 标签页 .

双击 “ DrawItem ” 选项 . 这将为 “ File ” 菜单添加一个默认的绘制事件处理函数 .
private void mi_TopMenuItem_DrawItem(

object sender, System.Windows.Forms.DrawItemEventArgs e)

双击 “ MeasureItem ” 选项。这将为 “ File ” 菜单添加一个默认的测量事件处理函数
private void mi_TopMenuItem_MeasureItem(

object sender, System.Windows.Forms.MeasureItemEventArgs e)

现在我们需要为子菜单添加 DrawItem 和 MeasureItem 事件处理函数 . 对所有子菜单,我们创建不同的事件函数
选中“ Open ”子菜单,同样的添加两个事件处理函数
private void mi_SubMenuItem_MeasureItem(

object sender, System.Windows.Forms.MeasureItemEventArgs e)
private void mi_SubMenuItem_DrawItem(

object sender, System.Windows.Forms.DrawItemEventArgs e)

注意:这里我们并不是对每个菜单项都创建一个相应的事件处理函数,尽管你可以这样做。相反的,我们通过一个通用的事件处理函数( mi_TopMenuItem_DrawItem )来处理所有顶级菜单项( File/Options/Help )的 DrawItem 事件,一个通用的事件处理函数来处理所有顶级菜单项的 MeasureItem 事件;一个通用的事件处理函数( mi_SubMenuItem_DrawItem )来处理所有的子菜单项( Open/Close…About )的 DrawItem 事件,一个通用的事件处理函数( mi_SubMenuItem_MeasureItem )来处理所有的子菜单的 MeasureItem 事件。

下面是详细步骤 ..

对其他的两个顶级菜单项 “Options” 、 “Help” ,在窗体设计器中选中它,选其属性页,选到事件页 .

点击 DrawItem 事件右边的下拉列表,选中 mi_TopMenuItem_DrawItem.

点击 MeasureItem 事件右边的下拉列表,选中 mi_TopMenuItem_ MeasureItem.

对于每个子菜单,例如 “Close / Exit / Security / Network / About” ,选其属性页,选到事件页 .

点击 DrawItem 事件右边的下拉列表,选中 mi_SubMenuItem_DrawItem.

点击 MeasureItem 事件右边的下拉列表,选中 mi_SubMenuItem_ MeasureItem.

现在对于每个菜单项我们都为其添加了 DrawItem 和 MeasureItem 的事件处理函数 .

** 下面是顶级菜单的事件处理函数 **

|

private void mi_TopMenuItem_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)

{

Brush sysBgBrush = new SolidBrush(SystemColors.Control);

Brush focuseBgBrush = new SolidBrush(Color.CornflowerBlue);

Font normalFont = new Font("Ariel", 10);

Brush normalTxBrush = new SolidBrush(Color.Black);

Pen bdrPen1 = new Pen(normalTxBrush, 2);

Pen bdrPen2 = new Pen(normalTxBrush);

Rectangle rc = new Rectangle(e.Bounds.X+1 , e.Bounds.Y+1, e.Bounds.Width-5, e.Bounds.Height-1);

e.Graphics.FillRectangle(sysBgBrush , rc);

MenuItem mOrigin = (MenuItem)sender ;

string mItemText = mOrigin.Text ;

StringFormat sf = new StringFormat();

sf.Alignment = StringAlignment.Center ;

e.Graphics.DrawString(mItemText , normalFont, normalTxBrush , rc , sf );

//Console.WriteLine(e.State.ToString());

if ( e.State == (DrawItemState.NoAccelerator | DrawItemState.Selected)

|| e.State == ( DrawItemState.NoAccelerator | DrawItemState.HotLight) )

{

e.Graphics.FillRectangle( focuseBgBrush, rc);

e.Graphics.DrawString( mItemText , normalFont ,normalTxBrush, rc ,sf);

e.Graphics.DrawRectangle(bdrPen2, rc );

}

e.DrawFocusRectangle();

e.Graphics.DrawRectangle(bdrPen1, rc );

}

private void mi_TopMenuItem_MeasureItem(object sender, System.Windows.Forms.MeasureItemEventArgs e)

{

e.ItemHeight = 25;

e.ItemWidth = 75;

}


**
** ** 下面是子菜单的事件处理函数 **

private void mi_SubMenuItem_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)

{

Rectangle rc = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height);

Brush sysBgBrush = new SolidBrush(SystemColors.Control);

Brush focuseBrush = new SolidBrush(Color.CornflowerBlue);

Font normalFont = new Font("Veranda", 10);

Brush normalTxBrush = new SolidBrush(Color.Blue);

Font focuseFont = new Font("Veranda", 10, FontStyle.Bold|FontStyle.Underline);

Brush focuseTxBrush = new SolidBrush(Color.Yellow);

Pen sysBdPen = new Pen(sysBgBrush);

Pen focuseBdPen = new Pen(new SolidBrush(Color.Black));

//erase the previous track

e.Graphics.FillRectangle(sysBgBrush , rc);

MenuItem mOrigin = (MenuItem)sender ;

string mItemText = mOrigin.Text ;

StringFormat textFormat = new StringFormat();

textFormat.Alignment = StringAlignment.Far ;

textFormat.LineAlignment = StringAlignment.Center;

Rectangle rcText = rc ;

rcText.Width-=5 ;

<P class=code style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0cm; BORDER-TOP: medium none; PADDING-LEFT: 0cm; PAD


Published At
Categories with Web编程
Tagged with
comments powered by Disqus