分享
 
 
 

Henry手记-.NET WinForm菜单DIY

王朝c#·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Henry手记-.NET WinForm菜单DIY

韩睿(2003.7.29)

天气很热,上海也达到了六十年来的最高温,为了防止出门中暑,只好闭关自修。趋着心情不错,写一点小东西以馈读者,希望大家在酷暑中获得一份轻松与惬意。

今天和大家讨论一下对菜单的改造。网上有不少好控件,都能实现在Menu里加入图片,但是少有更改Menu中的字体与颜色的。其实,我们通过对.net自带控件的操作,就可以实现加图片与改字体与颜色的目标。本文主要是讨论字体与颜色的更改。如下图所示:

通过菜单项的改变,窗体上的“天气真热”Label会相应地改变字体与前景色。

有的朋友会问,一般的控件不是只要设置font、forecolor、backcolor属性不就能达到Henry要做的事情了吗?但是Menu不行,原因是:Menu的父类是Component,不是Control!而那些属性是Control类的,如果Menu是从Control类继承下来的,当然就不会有我这篇小文的存在意义了。所以我们应该把Menu称为组件,以示与Control的派生控件相区别。大家以后使用控件时,也要注意一下它的父类是什么,以明确是否能进行某项功能的实现。

Menu内含三个类:MainMenu(主菜单)、ContextMenu(弹出菜单)、MenuItem(菜单项)其中,MainMenu和ContextMenu都是容器,MenuItem 类提供使我们得以配置菜单项的外观和功能的属性。因此,我们的工作主要就是针对MenuItem去的。上图实现的是在ContextMenu菜单,MainMenu的形式也是一样的。

现在我们是要做打破常规的事,所以要将MenuItem的OwnerDraw设为true,接管下绘制菜单项的重任,自已动手DIY一把。

那么我们来分析一下,当OwnerDraw设为true之后,哪些事件或方法是需要我们重写的。查一下MSDN就可以看到:DrawItem事件是当OwnerDraw设为true后发生的,接着查一下它的帮助,看一下事件处理程序中的事件数据是如何定义的。

[MSDN]:事件处理程序接收一个 DrawItemEventArgs 类型的参数,它包含与此事件相关的数据。下列 DrawItemEventArgs 属性提供特定于此事件的信息。

属性

说明

属性

说明

BackColor

获取所绘制的项的背景色

Graphics

获取要在其上绘制项的图形表面

Bounds

获取表示所绘制项的边界的矩形

Index

获取所绘制项的索引值

Font

获取分配给所绘制项的字体

State

获取所绘制项的状态

ForeColor

获取所绘制项的前景色

果然,我们需要的三个属性全都在这了!那么,我们实现这一事件不就行了?我按MSDN的例子实现了它,可是,出来的效果却不对,ContextMenu的宽度与高度都只有一点点大。看来是没有设置好MenuItem的宽与高了。

Item的宽与高在哪设置?MenuItem的属性中并没有这两项,找来找去,最后在MeasureItem事件中找到了。

属性

说明

Graphics

获取要测量的 Graphics 对象

Index

获取或设置需要有高度和宽度的项索引

ItemHeight

获取或设置由 Index 指定的项高度

ItemWidth

获取或设置由 Index 指定的项宽度

也就是说,我们想要绘制出MenuItem,必须先计算出将要绘制的Item的宽度与高度。在这里需要说明的是,项的宽度与高度不光是由文字部分决定的,还取决于item中的图片部分,所以我们的计算公式是:

项的宽度=图片的宽度+文字的宽度

项的高度=max (图片的高度,文字的高度)

本文没有加入自定义图片,只是加入了一个圆点的选项符号,它是由DrawMenuGlyph共享方法实现的。那么它的高度与宽度是如何界定的呢?很简单,使用SystemInformation.MenuCheckSize就可确定在选定菜单项旁显示选中标记的图像的尺寸。圆点的默认大小是高宽皆为13像素。DrawMenuGlyph是会根据我们给出的图片的位置大小绘制圆点的大小的。所以,我们还必须在DrawItem事件中给出图片的大小:

图片的高度=文字的高度

图片的宽度=图片的默认宽度*放大的倍数=图片的默认宽度*文字的高度\图片的默认高度

昏头昏脑地说了这么多,还是用代码来描述更为清晰:

Dim oldMenuItem As New MenuItem()

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Me.ContextMenu = New ContextMenu()

Dim MenuText As New ArrayList()

MenuText.Add("宋体")

MenuText.Add("黑体")

MenuText.Add("楷体_GB2312")

Dim MyMenuItem(MenuText.Count - 1) As MenuItem

Dim i As Integer

For i = 0 To MyMenuItem.Length - 1

MyMenuItem(i) = New MenuItem(MenuText(i))

MyMenuItem(i).OwnerDraw = True '每一项都要设

MyMenuItem(i).RadioCheck = True '每一项的选项钮都开启

'指向单击事件的处理程序

AddHandler MyMenuItem(i).Click, _

New EventHandler(AddressOf MenuItem_Click)

'指向MeasureItem事件的处理程序

AddHandler MyMenuItem(i).MeasureItem, _

New MeasureItemEventHandler(AddressOf MenuItem_MeasureItem)

'指向DrawItem事件的处理程序

AddHandler MyMenuItem(i).DrawItem, _

New DrawItemEventHandler(AddressOf MenuItem_DrawItem)

ContextMenu.MenuItems.Add(MyMenuItem(i))

Next i

'记录下初始选中的项

oldMenuItem = ContextMenu.MenuItems(0)

oldMenuItem.Checked = True

End Sub

Private Sub MenuItem_Click(ByVal obj As Object, ByVal e As EventArgs)

oldMenuItem.Checked = False '改变原有的菜单项的选取状态

oldMenuItem = CType(obj, MenuItem) '转型处理

oldMenuItem.Checked = True '设置现选中的菜单项的选取状态

Select Case oldMenuItem.Text '根据菜单内容设置label的色彩

Case "宋体"

Label1.ForeColor = Color.Red

Case "黑体"

Label1.ForeColor = Color.Green

Case "楷体_GB2312"

Label1.ForeColor = Color.Blue

End Select

'根据菜单内容设置label的字体

Label1.Font = New Font(oldMenuItem.Text, Label1.Font.Size)

Invalidate()

End Sub

Private Sub MenuItem_MeasureItem(ByVal obj As Object,ByVal e As MeasureItemEventArgs)

Dim mi As MenuItem = CType(obj, MenuItem)

Dim fnt As New Font(mi.Text, 12, FontStyle.Bold) '12是字体的大小

Dim szf As SizeF = e.Graphics.MeasureString(mi.Text, fnt, 1000)

'得到文本的宽度

e.ItemWidth = CInt(Math.Ceiling(szf.Width))

'得到文本的高度

e.ItemHeight = CInt(Math.Ceiling(szf.Height))

'项的宽度=文本的宽度+图片的宽度

e.ItemWidth += SystemInformation.MenuCheckSize.Width * _

e.ItemHeight \ SystemInformation.MenuCheckSize.Height

End Sub

Private Sub MenuItem_DrawItem(ByVal obj As Object, _

ByVal e As DrawItemEventArgs)

Dim mi As MenuItem = CType(obj, MenuItem)

Dim g As Graphics = e.Graphics

Dim

br As

Brush

Dim fnt As New Font(mi.Text, 12, FontStyle.Bold) '12是字体的大小

Dim rectCheck As Rectangle = e.Bounds '这样做是把选钮图片的高度设为文本的高度

rectCheck.Width = SystemInformation.MenuCheckSize.Width * _

rectCheck.Height \ SystemInformation.MenuCheckSize.Height

Dim rectText As Rectangle = e.Bounds

rectText.X += rectCheck.Width 'item的宽度=图片的宽度+文字的宽度

e.DrawBackground()'重写这个函数,可以实现选中项的XP效果

'绘制表示选中的圆点。如果想加入图片,请在这里考虑一下

If (e.State And DrawItemState.Checked) <> 0 Then

ControlPaint.DrawMenuGlyph(g, rectCheck, MenuGlyph.Bullet)

End If

'设置选项的前景色

If (e.State And DrawItemState.Selected) <> 0 Then

br = SystemBrushes.HighlightText '选中的会变成蓝底白字

Else

Select Case mi.Text

Case "宋体"

br = New SolidBrush(Color.Red)

Case "黑体"

br = New SolidBrush(Color.Green)

Case "楷体_GB2312"

br = New SolidBrush(Color.Blue)

End Select

End If

g.DrawString(mi.Text, fnt, br, RectangleF.op_Implicit(rectText))

End Sub

您动手试一下吧,很快就会明白实现的原理了。然后对其进行扩展,就能实现极富个性的菜单了。本文仅是起了一个头,更深入的研究,还需要您自己去钻研。

----

声明:本文版权与解释权归韩睿所有,如需转载,请保留完整的内容及此声明。

QQ: 18349592

E-Mail: henry7685@hotmail.com

请访问本人专栏:http://www.csdn.net/develop/author/netauthor/Latitude/

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有