国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

用C#和VB.NET實現(xiàn)VS.NET或Office XP風格的菜單(三)

2024-07-10 13:00:25
字體:
來源:轉載
供稿:網(wǎng)友
用c#和vb.net實現(xiàn)vs.net或office xp風格的菜單

小氣的神 2001.08.18

3. “menuitemstyle”接口和vs.net風格的菜單項



這個project又將切換到c#語言。我是這樣想的:先針對普通菜單、office200風格、vs.net風格三種情況定義一個統(tǒng)一的接口(interface),其中包括畫icon(drawicon)、畫分割條(drawseparator)、畫菜單背景(drawbackground)、寫菜單項的文字(drawmenutext)等功能;普通、office2000和vs.net根據(jù)各自不同的情況實現(xiàn)這個接口的drawxxx的功能。然后從menuitem繼承一個子類,象第二部分講的那樣overrides 菜單項的兩個函數(shù):onmeasureitem和ondrawitem,根據(jù)不同的風格調用上面實現(xiàn)的接口中的drawxxx函數(shù)就可以了。最后我把這部分都分隔出來放在一個.cs文件中,單獨編譯成一個vsnet.menu.dll,你只用using vsnet.menu ; 然后就可以象在第一部分那樣象使用普通的menuitem那樣來用了,demo源代碼中你還可以看到我定義了iconmenuitem的類,它有一個方法:menuitemcreator(vsnet.menu.iconmenustyle stype , string stext , bitmap bmp , system.eventhandler eh)可以完成生成需要的menuitem。本來我想用資源文件或將圖片icon等資源放在一個專門的文件中,然后由這個類來負責從資源文件或外部的類中獲得資源createmenuitem。但是是第一版,你會看到例程中我仍然用原始的new bitmap()的方式直接從硬盤拿資源。當我看到它show出來時,先是很開心,然后發(fā)現(xiàn)還有許多要改進,想想其實做一個專業(yè)的菜單也需要花許多心思。

好吧讓我們看一下有關vs.net風格菜單項這部分主要的實現(xiàn)代碼:



public class vsnetstyle : menuitemstyledrawer

{

static color bgcolor = color.fromargb(246, 246, 246);

static color ibgcolor = color.fromargb(202, 202, 202);

static color sbcolor = color.fromargb(173, 173, 209);

static color sbbcolor = color.fromargb( 0, 0, 128);



static int textstart = 20;



public void drawcheckmark(graphics g, rectangle bounds, bool selected)

{

controlpaint.drawmenuglyph(g, new rectangle(bounds.x + 2, bounds.y + 2, 14, 14), menuglyph.checkmark);

}



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 + 2, color.black);

g.drawimage(icon, bounds.left + 1, bounds.top + 1);

}

else

{

g.drawimage(icon, bounds.left + 2, bounds.top + 2);

}

}

else

controlpaint.drawimagedisabled(g, icon, bounds.left + 2, bounds.top + 2, 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)

{

stringformat stringformat = new stringformat();

stringformat.hotkeyprefix = ((state & drawitemstate.noaccelerator) > 0) ? hotkeyprefix.hide : 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 + 2;

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, bounds.top + 2, stringformat);

}

}



menuitemstyledrawer就是那個公用的接口類,無論普通風格、office2000還是vs.net風格都要實現(xiàn)自己方式的接口,這個接口包括drawcheckmark、drawicon、drawmenutext、drawbackground、drawseparator等函數(shù),可以實現(xiàn)菜單項需要的各種函數(shù)。完成這部分后可以從menuitem繼承一個子類來象第二部分一樣處理了。看下面的代碼,具體考察一下熟悉的onmeasureitem和ondrawitem:

protected override void onmeasureitem(measureitemeventargs e)

{

base.onmeasureitem(e);



// make shortcut text 省略這部分代碼。

if (menustyle != iconmenustyle.standard)

{

if (text == "-")

{

e.itemheight = 8;

e.itemwidth = 4;

return;

}

int textwidth = (int)(e.graphics.measurestring(text + shortcuttext, systeminformation.menufont).width);

e.itemheight = systeminformation.menuheight;

if (parent == parent.getmainmenu())

e.itemwidth = textwidth - 5; // 5 is a magic number

else

e.itemwidth = math.max(160, textwidth + 50);

}

}



iconmenustyle.standard是個enum表明是普通風格、office2000或是vs。net的風格。這部分和我們第二部分看到的沒有什么不同。

protected override void ondrawitem(drawitemeventargs e)

{

base.ondrawitem(e);

graphics g = e.graphics;

rectangle bounds = e.bounds;

bool selected = (e.state & drawitemstate.selected) > 0;

bool toplevel = (parent == parent.getmainmenu());

bool hasicon = icon != null;



style.drawbackground(g, bounds, e.state, toplevel, hasicon);

if (hasicon)

style.drawicon(g, icon, bounds, selected, enabled, checked);

else

if (checked)

style.drawcheckmark(g, bounds, selected);



if (text == "-")

{

style.drawseparator(g, bounds);

}

else

{

style.drawmenutext(g, bounds, text, shortcuttext, enabled, toplevel, e.state);

}

}



剛剛我們說的menuitemstyledrawer接口的好處在這里顯示出來,整個過程顯得簡單明了,具體實現(xiàn)得代碼不是很多。當這個類完成后,剩下來的就是使用了它了,這部分象第一部分所述,你可以在一個頂級菜單項的子菜單項聲明成iconmenu類型的也就是我們實現(xiàn)的繼承menuitem的類,簡單的代碼象下面這樣:

private system.windows.forms.menuitem mitems1 ; system.drawing.bitmap bitmap1 = new bitmap( bmppathstr + "open.bmp") ;



mitems1 = imenuitem.menuitemcreator( menustyle , "&open" , bitmap1,

這個mitem1就是一個vs.net風格的菜單項了。具體的可以看附帶的project和屏幕截圖。



至此我們完成了用vb.net或c#完成一個有vs.net或office xp風格的菜單。三個部分是漸進的,如果你以前進行或實驗過第二部分討論的問題,那么第三部分唯一讓人感興趣的是menuitemstyledrawer接口的思路。對于整個新的.net的編程方式上說,原來的vb用戶可能會經(jīng)歷一個痛苦的過程,他們的第一反應是sub class、hook或是終極的api,而接觸過c++、mfc、delphi甚至vj++的用戶會很容易想到繼承,特別時delphi和vj的用戶入手應當最快了。想想會開始懷念以前vb的時光,因為對于這樣的問題,vb用戶總是拿著大錘,直接敲個大洞,然后拿到結果;而c++、mfc、dephi用戶則拿著一本說明書,一步一步按指示找到結果;結果可能一樣,但兩者的方式是截然不同的。好了,這些是題外話了。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 托克逊县| 湖州市| 东乡族自治县| 莱阳市| 白玉县| 崇州市| 屏南县| 额尔古纳市| 郯城县| 元谋县| 凉城县| 吴川市| 金川县| 阿坝| 宝兴县| 淮阳县| 彩票| 石棉县| 辽阳县| 棋牌| 集贤县| 息烽县| 门源| 平度市| 万州区| 时尚| 墨江| 当涂县| 南陵县| 崇义县| 利津县| 和硕县| 金秀| 汶川县| 定襄县| 香港| 天柱县| 铜山县| 泗水县| 攀枝花市| 军事|