用c#和vb.net實(shí)現(xiàn)vs.net或office xp風(fēng)格的菜單
小氣的神 2001.08.18
2.“owner-drawn menus”技術(shù)
這個(gè)例子是vb.net語法的.我去掉了和menu無關(guān)的class,原因是錯(cuò)誤太多,你會(huì)遇到類庫和命名空間的移植性的問題:
最多的是beta1 system.winforms 和beta 2 的system.windows.froms的命名空間問題;
然后是beta1中的bitand 、bitor等等bitxxx的函數(shù)在beta2中已去掉了bit又和vb中一樣了(據(jù)說beta1的這項(xiàng)改動(dòng)遭到了總多vb fans的投訴,說不能把vb也c?;?,bit是什么東東),這樣你需要把這類函數(shù)改掉;
然后是nameobjectcollectionbase從原來的system.collections中刪除了,beta2放在system.collections.specialized 中,真的有些昏倒,開始我還以為beta2中刪除了這個(gè)類。
最后是一些overrides和 overloads的問題,具體的看vs.net或framework sdk beta 2編譯時(shí)的提示就可以了,這方面ms做得不錯(cuò),task list中告訴你具體得建議,照做就是了。
具體一點(diǎn)你可以在framework sdk beta 2安裝目錄的doc目錄中找到這兩個(gè)文件,這是從beta1移植到beta2上不錯(cuò)的指導(dǎo)文件:apichangesbeta1tobeta2.htm 和change list - beta1 to beta2.doc 特別是這個(gè)doc文件洋洋灑灑90多頁,但很有幫助。
希望你還能在排除所有的錯(cuò)誤之后保持清醒,找到最核心有用的代碼,來分析。主要是cactionmenu.vb,焦點(diǎn)在onmeasureitem和ondrawitem這兩個(gè)函數(shù)或說事件處理程序上。onmeasureitem主要是處理menuitem的itemheight和itemwidth的,從它傳的measureitemeventargs參數(shù)數(shù)就知道。ondrawitem主要是如何畫菜單的問題。關(guān)鍵字overrides表明我們要在子類中重新定義menuitem中的這兩個(gè)方法。
從56行到58行是onmeasureitem函數(shù):
protected overrides sub onmeasureitem(byval e as system.windows.forms.measureitemeventargs)
if me.action.caption = "-" then
e.itemheight = 5
else
e.itemheight = 20
end if
dim fs as fontstyle
if me.defaultitem = true then fs = fs or fontstyle.bold
dim fnt as new font("tahoma", 8, fs)
dim sf as sizef = e.graphics.measurestring(me.action.caption, fnt)
fnt.dispose()
e.itemwidth = cint(sf.width) + 20
end sub
measureitemeventargs提供4個(gè)屬性graphis、index、itemheight和itemwidth。me相當(dāng)于c?;騤ava的this關(guān)鍵字。fnt.dispose()中dispose是一個(gè)很有意思的函數(shù)調(diào)用,在以往的windows編程中象字體、畫筆等許多資源都希望快使用快釋放,這個(gè)語句是用來控制gc(garbage collection)的,意思是我已使用完了這個(gè)設(shè)備或資源,gc你可以收回了。
從70到146行是有關(guān)onitemdraw函數(shù)的:
protected overrides sub ondrawitem(byval e as system.windows.forms.drawitemeventargs)
' colors, fonts
dim clrbgicon, clrbgtext, clrtext as color, fs as fontstyle, fnt as font
dim b as solidbrush, p as pen
dim fenabled as boolean = not ctype(e.state and drawitemstate.disabled, boolean)
dim fselected as boolean = ctype(e.state and drawitemstate.selected, boolean)
dim fdefault as boolean = ctype(e.state and drawitemstate.default, boolean)
dim fbreak as boolean = (me.action.caption = "-")
if fenabled and fselected and not fbreak then
clrbgicon = color.silver
clrbgtext = color.white
clrtext = color.blue
fs = fs or fontstyle.underline
else
clrbgicon = color.gray
clrbgtext = color.silver
clrtext = color.black
end if
if not fenabled then
clrtext = color.white
end if
if fdefault then
fs = fs or fontstyle.bold
end if
fnt = new font("tahoma", 8, fs)
' total background (partly to remain for icon)
b = new solidbrush(clrbgicon)
e.graphics.fillregion(b, new [region](e.bounds))
b.dispose()
' icon?
if not me.action.actionlist is nothing then
dim il as imagelist = me.action.actionlist.imagelist
if not il is nothing then
dim index as integer = me.action.image
if index > -1 and index < il.images.count then
dim rect as rectangle = e.bounds
with rect
.x += 2
.y += 2
.width = 16
.height = 16
end with
e.graphics.drawimage(il.images.item(index), rect)
end if
end if
end if
' text background
dim rf as rectanglef
with rf
.x = 18
.y = e.bounds.y
.width = e.bounds.width - .x
.height = e.bounds.height
end with
b = new solidbrush(clrbgtext)
e.graphics.fillregion(b, new [region](rf))
b.dispose()
' text/line
rf.y += 3 : rf.height -= 3
if not fbreak then
b = new solidbrush(clrtext)
e.graphics.drawstring(me.action.caption, fnt, b, rf)
fnt.dispose()
b.dispose()
else
p = new pen(color.black)
rf.y -= 1
e.graphics.drawline(p, rf.x, rf.y, rf.right, rf.y)
p.dispose()
end if
' border
if fenabled and fselected and not fbreak then
p = new pen(color.black)
e.graphics.drawrectangle(p, e.bounds)
p.dispose()
end if
end sub
drawitemeventargs參數(shù)給了你和菜單相關(guān)的所有環(huán)境和信息,它包括6個(gè)屬性:bounds、font、forecolor、graphics、index、states。如果你以前用過windows下的gdi函數(shù),那一定很熟悉這些函數(shù),不是很復(fù)雜只需要你一點(diǎn)點(diǎn)算術(shù)知識(shí)和美術(shù)觀點(diǎn)就可以了,如果你是第一次那么在紙上畫幾個(gè)矩形塊就可以了理解和做的很好,比起以前tc下的菜單編程容易得多。主要是作者是如何把icon畫在菜單上的,然后是根據(jù)不同的states表現(xiàn)一下菜單的forecolor, bounds就是菜單項(xiàng)最前面的表示選中等等的小方塊。
好了第二部分涉及到了大部分技術(shù)細(xì)節(jié)了,這里你需要關(guān)注的是,如何畫出來,下一部分我們來看如何畫的好看些,象vs.net或office xp那樣子。