请发表友善的回复…
发表回复
cppTrier 2003-01-11
- 打赏
- 举报
谢谢大家,发现自己还有好多东西要学啊! :)
Lin8Sheng8Wen 2003-01-11
- 打赏
- 举报
DrawItemEventArgs参数给了你和菜单相关的所有环境和信息,它包括6个属性:Bounds、Font、ForeColor、Graphics、Index、States。如果你以前用过Windows下的GDI函数,那一定很熟悉这些函数,不是很复杂只需要你一点点算术知识和美术观点就可以了,如果你是第一次那么在纸上画几个矩形块就可以了理解和做的很好,比起以前TC下的菜单编程容易得多。主要是作者是如何把Icon画在菜单上的,然后是根据不同的States表现一下菜单的ForeColor, Bounds就是菜单项最前面的表示选中等等的小方块。
好了第二部分涉及到了大部分技术细节了,这里你需要关注的是,如何画出来,下一部分我们来看如何画的好看些,象VS.NET或Office XP那样子。
3. “MenuItemStyle”接口和VS.NET风格的菜单项
这个Project又将切换到C#语言。我是这样想的:先针对普通菜单、Office200风格、VS.NET风格三种情况定义一个统一的接口(interface),其中包括画Icon(DrawIcon)、画分割条(DrawSeparator)、画菜单背景(DrawBackground)、写菜单项的文字(DrawMenuText)等功能;普通、Office2000和VS.NET根据各自不同的情况实现这个接口的Drawxxx的功能。然后从MenuItem继承一个子类,象第二部分讲的那样Overrides 菜单项的两个函数:OnMeasureItem和OnDrawItem,根据不同的风格调用上面实现的接口中的DrawXXX函数就可以了。最后我把这部分都分隔出来放在一个.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出来时,先是很开心,然后发现还有许多要改进,想想其实做一个专业的菜单也需要花许多心思。
好吧让我们看一下有关VS.NET风格菜单项这部分主要的实现代码:
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风格都要实现自己方式的接口,这个接口包括DrawCheckmark、DrawIcon、DrawMenuText、DrawBackground、DrawSeparator等函数,可以实现菜单项需要的各种函数。完成这部分后可以从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接口的好处在这里显示出来,整个过程显得简单明了,具体实现得代码不是很多。当这个类完成后,剩下来的就是使用了它了,这部分象第一部分所述,你可以在一个顶级菜单项的子菜单项声明成IconMenu类型的也就是我们实现的继承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用户可能会经历一个痛苦的过程,他们的第一反应是Sub Class、Hook或是终极的API,而接触过C++、MFC、DELPHI甚至VJ++的用户会很容易想到继承,特别时DELPHI和VJ的用户入手应当最快了。想想会开始怀念以前VB的时光,因为对于这样的问题,VB用户总是拿着大锤,直接敲个大洞,然后拿到结果;而C++、MFC、DE
好了第二部分涉及到了大部分技术细节了,这里你需要关注的是,如何画出来,下一部分我们来看如何画的好看些,象VS.NET或Office XP那样子。
3. “MenuItemStyle”接口和VS.NET风格的菜单项
这个Project又将切换到C#语言。我是这样想的:先针对普通菜单、Office200风格、VS.NET风格三种情况定义一个统一的接口(interface),其中包括画Icon(DrawIcon)、画分割条(DrawSeparator)、画菜单背景(DrawBackground)、写菜单项的文字(DrawMenuText)等功能;普通、Office2000和VS.NET根据各自不同的情况实现这个接口的Drawxxx的功能。然后从MenuItem继承一个子类,象第二部分讲的那样Overrides 菜单项的两个函数:OnMeasureItem和OnDrawItem,根据不同的风格调用上面实现的接口中的DrawXXX函数就可以了。最后我把这部分都分隔出来放在一个.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出来时,先是很开心,然后发现还有许多要改进,想想其实做一个专业的菜单也需要花许多心思。
好吧让我们看一下有关VS.NET风格菜单项这部分主要的实现代码:
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风格都要实现自己方式的接口,这个接口包括DrawCheckmark、DrawIcon、DrawMenuText、DrawBackground、DrawSeparator等函数,可以实现菜单项需要的各种函数。完成这部分后可以从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接口的好处在这里显示出来,整个过程显得简单明了,具体实现得代码不是很多。当这个类完成后,剩下来的就是使用了它了,这部分象第一部分所述,你可以在一个顶级菜单项的子菜单项声明成IconMenu类型的也就是我们实现的继承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用户可能会经历一个痛苦的过程,他们的第一反应是Sub Class、Hook或是终极的API,而接触过C++、MFC、DELPHI甚至VJ++的用户会很容易想到继承,特别时DELPHI和VJ的用户入手应当最快了。想想会开始怀念以前VB的时光,因为对于这样的问题,VB用户总是拿着大锤,直接敲个大洞,然后拿到结果;而C++、MFC、DE
Lin8Sheng8Wen 2003-01-11
- 打赏
- 举报
2.“Owner-drawn menus”技术
这个例子是VB.NET语法的.我去掉了和Menu无关的Class,原因是错误太多,你会遇到类库和命名空间的移植性的问题:
最多的是Beta1 System.WinForms 和Beta 2 的System.Windows.Froms的命名空间问题;
然后是Beta1中的BitAnd 、BitOR等等Bitxxx的函数在Beta2中已去掉了Bit又和VB中一样了(据说Beta1的这项改动遭到了总多VB Fans的投诉,说不能把VB也C#化,Bit是什么东东),这样你需要把这类函数改掉;
然后是NameObjectCollectionBase从原来的system.collections中删除了,Beta2放在system.collections.specialized 中,真的有些昏倒,开始我还以为Beta2中删除了这个类。
最后是一些Overrides和 Overloads的问题,具体的看VS.NET或Framework SDK Beta 2编译时的提示就可以了,这方面MS做得不错,Task list中告诉你具体得建议,照做就是了。
具体一点你可以在Framework SDK Beta 2安装目录的Doc目录中找到这两个文件,这是从Beta1移植到Beta2上不错的指导文件:APIChangesBeta1toBeta2.htm 和Change List - Beta1 to Beta2.doc 特别是这个doc文件洋洋洒洒90多页,但很有帮助。
希望你还能在排除所有的错误之后保持清醒,找到最核心有用的代码,来分析。主要是CActionMenu.vb,焦点在OnMeasureItem和OnDrawItem这两个函数或说事件处理程序上。OnMeasureItem主要是处理MenuItem的ItemHeight和ItemWidth的,从它传的MeasureItemEventArgs参数数就知道。OnDrawItem主要是如何画菜单的问题。关键字Overrides表明我们要在子类中重新定义MenuItem中的这两个方法。
从56行到58行是OnMeasureItem函数:
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个属性Graphis、Index、ItemHeight和ItemWidth。Me相当于C#或Java的this关键字。fnt.Dispose()中Dispose是一个很有意思的函数调用,在以往的Windows编程中象字体、画笔等许多资源都希望快使用快释放,这个语句是用来控制GC(garbage collection)的,意思是我已使用完了这个设备或资源,GC你可以收回了。
从70到146行是有关OnItemDraw函数的:
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
这个例子是VB.NET语法的.我去掉了和Menu无关的Class,原因是错误太多,你会遇到类库和命名空间的移植性的问题:
最多的是Beta1 System.WinForms 和Beta 2 的System.Windows.Froms的命名空间问题;
然后是Beta1中的BitAnd 、BitOR等等Bitxxx的函数在Beta2中已去掉了Bit又和VB中一样了(据说Beta1的这项改动遭到了总多VB Fans的投诉,说不能把VB也C#化,Bit是什么东东),这样你需要把这类函数改掉;
然后是NameObjectCollectionBase从原来的system.collections中删除了,Beta2放在system.collections.specialized 中,真的有些昏倒,开始我还以为Beta2中删除了这个类。
最后是一些Overrides和 Overloads的问题,具体的看VS.NET或Framework SDK Beta 2编译时的提示就可以了,这方面MS做得不错,Task list中告诉你具体得建议,照做就是了。
具体一点你可以在Framework SDK Beta 2安装目录的Doc目录中找到这两个文件,这是从Beta1移植到Beta2上不错的指导文件:APIChangesBeta1toBeta2.htm 和Change List - Beta1 to Beta2.doc 特别是这个doc文件洋洋洒洒90多页,但很有帮助。
希望你还能在排除所有的错误之后保持清醒,找到最核心有用的代码,来分析。主要是CActionMenu.vb,焦点在OnMeasureItem和OnDrawItem这两个函数或说事件处理程序上。OnMeasureItem主要是处理MenuItem的ItemHeight和ItemWidth的,从它传的MeasureItemEventArgs参数数就知道。OnDrawItem主要是如何画菜单的问题。关键字Overrides表明我们要在子类中重新定义MenuItem中的这两个方法。
从56行到58行是OnMeasureItem函数:
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个属性Graphis、Index、ItemHeight和ItemWidth。Me相当于C#或Java的this关键字。fnt.Dispose()中Dispose是一个很有意思的函数调用,在以往的Windows编程中象字体、画笔等许多资源都希望快使用快释放,这个语句是用来控制GC(garbage collection)的,意思是我已使用完了这个设备或资源,GC你可以收回了。
从70到146行是有关OnItemDraw函数的:
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
Lin8Sheng8Wen 2003-01-11
- 打赏
- 举报
转载,希望有帮助
VS.NET或Office XP中的菜单都是非常漂亮的,反正我很喜欢。可惜VS.NET没有带制作这种菜单的控件或组件,不知正式版本会不会提供一个模板和向导。至今还记得刚学计算机语言时自己用Turbo C制作菜单的感受,那些矩形框函数和象素操作的确很迷人,况且那时是如此的流行菜单。
这篇文章中我会介绍有关在Framework SDK Beta 2 中制作自己风格的菜单,所以你最好已安装了Framework SDK Beta 2,VS.NET Beta 2 不一定是必须的。附带的Zip包中的例子都是VS.NET Project的。
整个的文章包括三部分:
开始我会涉及到在Winform中最基本的一些菜单的概念。
然后会有一个以前接触过的有关菜单的例子,它是For Beta 1的。老实说我没有想到Beta1 到Beta2有许多函数和命名空间发生了变化,以前我在Beta1中测试过这个例子,很顺利。这次在Beta2中会有许多错误,我提供了两个Project,一个是原来的Project的,一个是我修改后For Beta 2的。这种移植很枯燥,但可以很快熟悉新的Beta2的类库和函数,Show出来的菜单还不错,感觉是Office2000风格的菜单。如果你有兴趣可以试一试这个过程,会获益非浅的,这个例子还包括按钮的,原来的作者其实是在Demo控件的“Owner-drawn menus”技术;不过我只对菜单部分感兴趣。
最后一部分是制作VS.NET或XP风格的例子,上面那个例子的效果不能使我完全满意,然后我重新写了另外一个,不过我对最后的结果还不是很满意,因为我的没有上一个例子那么完整,例子中我只显示了这个风格的菜单,对于事件响应、状态栏更新、tooltips、菜单的状态(enabled state)等处理都没有考虑,我把这些归结为时间问题,并承诺自己下次把它做得更好。
1.Framework SDK Beta 2中菜单分成两类一类是普通的菜单叫:MainMenu,在VS.NET的Toolsbox中有这样一个对应的菜单控件,拖下它到你的窗体中,设置一下属性就可以所见所得了,这个版本的比VS.Studio98 系列的要好用和漂亮的多。另一类叫:ContextMenu菜单,也就是常用的弹出菜单。对于VB6来说所有的普通菜单在VS.NET中是可以兼容和自动升级成MainMenu类型的菜单,但对于PopMenu的菜单是不能转换成ContextMenu类型的菜单,你必须自己重新修改代码实现。这里我们主要是针对MainMenu的,其实原理一样。
最简单的菜单你可以这样做:
using System;
using System.Windows.Forms;
public class frmVB6 : Form {
private MainMenu muMain ; // MainMenu
public static int Main(string[] Args) {
Application.Run(new frmVB6());
return 0;
}
public frmVB6() {
// The following code sets up the form properties.
this.Text = "Form1";
this.Height = 213 + SystemInformation.CaptionHeight;
this.Width = 312;
this.StartPosition = FormStartPosition.WindowsDefaultLocation;
MenuItem mItemFile = new MenuItem() ;
mItemFile.Text = "&File" ;
MenuItem mItemExit = new MenuItem() ;
mItemExit.Text = "E&xit" ;
muMain = new MainMenu() ;
muMain.MenuItems.Add( mItemFile ) ;
muMain.MenuItems.Add( mItemExit) ;
this.Menu = muMain ;
}
}
手工方式保存它为一个.cs文件然后在编译它:
csc /t:winexe /r:System.dll /r:System.Windows.Forms.Dll /r:System.Drawing.Dll Form1Menu.cs
VS.NET下只用New一个新的WinForm项目,然后在默认窗体中放入MainMenu控件,然后设置完属性,F5就可以了,完全不用一行代码。
如果要生成一个主菜单和一个菜单的子菜单项目,主要是MenuItems.AddRange的方法,看下面的代码:
this.mainMenu1 = new System.Windows.Forms.MainMenu();
this.menuItem1 = new System.Windows.Forms.MenuItem();
this.menuItem2 = new System.Windows.Forms.MenuItem();
this.menuItem3 = new System.Windows.Forms.MenuItem();
this.menuItem4 = new System.Windows.Forms.MenuItem();
// mainMenu1
this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem1, this.menuItem2});
// menuItem1
this.menuItem1.Index = 0;
this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem3, this.menuItem4});
this.menuItem1.Index = 0 ;
this.menuItem1.Text = "&File";
// menuItem2
this.menuItem2.Index = 1;
this.menuItem2.Text = "Help";
// menuItem3
this.menuItem3.Index = 0;
this.menuItem3.Text = "Open";
this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);
// menuItem4
this.menuItem4.Index = 1;
this.menuItem4.Text = "Exit";
this.menuItem4.Click += new System.EventHandler(this.menuItem4_Click);
this.Menu = this.mainMenu1;
如代码所示MenuItem1(File)和MenuItem2(Help)被AddRange到MainMenu1中成为了顶级的菜单,MenuItem3(Open)和MenuItem4(Exit)被AddRange到MenuItem1(File)中成为了File菜单下的子菜单项。
this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);表明MenuItem3点击时激发的事件处理程序,一般的事件处理程序象下面这样:
private void menuItem3_Click(object sender, System.EventArgs e)
{
MessageBox.Show ( " My Click Open" ) ;
}
我们关心的其实是MenuItem,让它用我们的方式画出有VS.NET或XP风格的菜单就可以了,更简单的说就是实现一个MenuItem的继承类,扩展它Draw的部分。好吧,让我们深入一点看看第二部分。
VS.NET或Office XP中的菜单都是非常漂亮的,反正我很喜欢。可惜VS.NET没有带制作这种菜单的控件或组件,不知正式版本会不会提供一个模板和向导。至今还记得刚学计算机语言时自己用Turbo C制作菜单的感受,那些矩形框函数和象素操作的确很迷人,况且那时是如此的流行菜单。
这篇文章中我会介绍有关在Framework SDK Beta 2 中制作自己风格的菜单,所以你最好已安装了Framework SDK Beta 2,VS.NET Beta 2 不一定是必须的。附带的Zip包中的例子都是VS.NET Project的。
整个的文章包括三部分:
开始我会涉及到在Winform中最基本的一些菜单的概念。
然后会有一个以前接触过的有关菜单的例子,它是For Beta 1的。老实说我没有想到Beta1 到Beta2有许多函数和命名空间发生了变化,以前我在Beta1中测试过这个例子,很顺利。这次在Beta2中会有许多错误,我提供了两个Project,一个是原来的Project的,一个是我修改后For Beta 2的。这种移植很枯燥,但可以很快熟悉新的Beta2的类库和函数,Show出来的菜单还不错,感觉是Office2000风格的菜单。如果你有兴趣可以试一试这个过程,会获益非浅的,这个例子还包括按钮的,原来的作者其实是在Demo控件的“Owner-drawn menus”技术;不过我只对菜单部分感兴趣。
最后一部分是制作VS.NET或XP风格的例子,上面那个例子的效果不能使我完全满意,然后我重新写了另外一个,不过我对最后的结果还不是很满意,因为我的没有上一个例子那么完整,例子中我只显示了这个风格的菜单,对于事件响应、状态栏更新、tooltips、菜单的状态(enabled state)等处理都没有考虑,我把这些归结为时间问题,并承诺自己下次把它做得更好。
1.Framework SDK Beta 2中菜单分成两类一类是普通的菜单叫:MainMenu,在VS.NET的Toolsbox中有这样一个对应的菜单控件,拖下它到你的窗体中,设置一下属性就可以所见所得了,这个版本的比VS.Studio98 系列的要好用和漂亮的多。另一类叫:ContextMenu菜单,也就是常用的弹出菜单。对于VB6来说所有的普通菜单在VS.NET中是可以兼容和自动升级成MainMenu类型的菜单,但对于PopMenu的菜单是不能转换成ContextMenu类型的菜单,你必须自己重新修改代码实现。这里我们主要是针对MainMenu的,其实原理一样。
最简单的菜单你可以这样做:
using System;
using System.Windows.Forms;
public class frmVB6 : Form {
private MainMenu muMain ; // MainMenu
public static int Main(string[] Args) {
Application.Run(new frmVB6());
return 0;
}
public frmVB6() {
// The following code sets up the form properties.
this.Text = "Form1";
this.Height = 213 + SystemInformation.CaptionHeight;
this.Width = 312;
this.StartPosition = FormStartPosition.WindowsDefaultLocation;
MenuItem mItemFile = new MenuItem() ;
mItemFile.Text = "&File" ;
MenuItem mItemExit = new MenuItem() ;
mItemExit.Text = "E&xit" ;
muMain = new MainMenu() ;
muMain.MenuItems.Add( mItemFile ) ;
muMain.MenuItems.Add( mItemExit) ;
this.Menu = muMain ;
}
}
手工方式保存它为一个.cs文件然后在编译它:
csc /t:winexe /r:System.dll /r:System.Windows.Forms.Dll /r:System.Drawing.Dll Form1Menu.cs
VS.NET下只用New一个新的WinForm项目,然后在默认窗体中放入MainMenu控件,然后设置完属性,F5就可以了,完全不用一行代码。
如果要生成一个主菜单和一个菜单的子菜单项目,主要是MenuItems.AddRange的方法,看下面的代码:
this.mainMenu1 = new System.Windows.Forms.MainMenu();
this.menuItem1 = new System.Windows.Forms.MenuItem();
this.menuItem2 = new System.Windows.Forms.MenuItem();
this.menuItem3 = new System.Windows.Forms.MenuItem();
this.menuItem4 = new System.Windows.Forms.MenuItem();
// mainMenu1
this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem1, this.menuItem2});
// menuItem1
this.menuItem1.Index = 0;
this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem3, this.menuItem4});
this.menuItem1.Index = 0 ;
this.menuItem1.Text = "&File";
// menuItem2
this.menuItem2.Index = 1;
this.menuItem2.Text = "Help";
// menuItem3
this.menuItem3.Index = 0;
this.menuItem3.Text = "Open";
this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);
// menuItem4
this.menuItem4.Index = 1;
this.menuItem4.Text = "Exit";
this.menuItem4.Click += new System.EventHandler(this.menuItem4_Click);
this.Menu = this.mainMenu1;
如代码所示MenuItem1(File)和MenuItem2(Help)被AddRange到MainMenu1中成为了顶级的菜单,MenuItem3(Open)和MenuItem4(Exit)被AddRange到MenuItem1(File)中成为了File菜单下的子菜单项。
this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);表明MenuItem3点击时激发的事件处理程序,一般的事件处理程序象下面这样:
private void menuItem3_Click(object sender, System.EventArgs e)
{
MessageBox.Show ( " My Click Open" ) ;
}
我们关心的其实是MenuItem,让它用我们的方式画出有VS.NET或XP风格的菜单就可以了,更简单的说就是实现一个MenuItem的继承类,扩展它Draw的部分。好吧,让我们深入一点看看第二部分。
TheAres 2003-01-11
- 打赏
- 举报
To poetc(伊公子):
下载这个我修改好的.
http://www23.brinkster.com/c2me/VSNetMenu-VSNetMenu_src.rar
下载这个我修改好的.
http://www23.brinkster.com/c2me/VSNetMenu-VSNetMenu_src.rar
poetc 2003-01-09
- 打赏
- 举报
还是不行;
XmlNodeList topMenus = doc.DocumentElement.ChildNodes;//出错
未处理的“System.Xml.XmlException”类型的异常出现在 system.xml.dll 中
其他信息:系统错误。
改<?xml version="1.0" encoding="gb2312"?>的encoding为utf8才能显示非中文菜单。
XmlNodeList topMenus = doc.DocumentElement.ChildNodes;//出错
未处理的“System.Xml.XmlException”类型的异常出现在 system.xml.dll 中
其他信息:系统错误。
改<?xml version="1.0" encoding="gb2312"?>的encoding为utf8才能显示非中文菜单。
TheAres 2003-01-09
- 打赏
- 举报
To poetc(伊公子):
你的XML修改可能有问题,参考我的这个修改.
<?xml version="1.0" encoding="gb2312"?>
<!-- edited with XML Spy v4.1 U (http://www.xmlspy.com) by Carlos H. Perez (Self) -->
<MainMenu>
<Menu Name="地方(&F)" Shortcut="" Icon="" Checked="False" Radio="False" Enabled="True">
<Menu Name="新疆" Shortcut="CtrlN" Icon=""
后面都一样,看明白格式就行了.
你的XML修改可能有问题,参考我的这个修改.
<?xml version="1.0" encoding="gb2312"?>
<!-- edited with XML Spy v4.1 U (http://www.xmlspy.com) by Carlos H. Perez (Self) -->
<MainMenu>
<Menu Name="地方(&F)" Shortcut="" Icon="" Checked="False" Radio="False" Enabled="True">
<Menu Name="新疆" Shortcut="CtrlN" Icon=""
后面都一样,看明白格式就行了.
stdao 2003-01-08
- 打赏
- 举报
他们提供的程序都有源代码,修改下源代码就行了。try it yourself.
poetc 2003-01-08
- 打赏
- 举报
如果是中文菜单项怎么办?
poetc 2003-01-08
- 打赏
- 举报
版主:我今天老提交不了;
to:stdao(道可道)你这个跟VSNetMenu的菜单实现是一样的吧?
to:stdao(道可道)你这个跟VSNetMenu的菜单实现是一样的吧?
poetc 2003-01-08
- 打赏
- 举报
我用的是VSNetMenu,我对不懂xml,问题就在上面;
1:<Menu Name="&New" ...改成:<Menu Name="&新建"...
2,//原来:<Menu Name="&New" Shortcut="CtrlN" Icon="" Checked="False" Radio="False" Enabled="False"/>
//修改成:<Menu Name="&New" Shortcut="CtrlN" Text="设置" ...>
//并改ProcessMenuItem
在public static MenuItem ProcessMenuItem(XmlElement xmlelement)
{
string menuName = xmlelement.Attributes["Name"].InnerXml;
if ( menuName.IndexOf("&") != -1 )
menuName = menuName.Replace("&", "&");
string menuShortcutString = xmlelement.Attributes["Shortcut"].InnerXml;
string menuIcon = xmlelement.Attributes["Icon"].InnerXml;
string menuChecked = xmlelement.Attributes["Checked"].InnerXml;
string menuRadio = xmlelement.Attributes["Radio"].InnerXml;
string menuEnabled = xmlelement.Attributes["Enabled"].InnerXml;
string name=xmlelement.Attributes["Text"].InnerXml;
//...
}
//
1,2中,我改MainMenu.xml中<?xml version="1.0" encoding="UTF-8"?>的encoding则:
未处理的“System.Xml.XmlException”类型的异常出现在 system.xml.dll 中
其他信息:系统错误。
出错语句是下面语句:
public static MenuItem[] CreateMainMenu()
{
string menuFile = Application.StartupPath + "\\" + "mainmenu.xml";
XmlDocument doc = new XmlDocument();
doc.Load(menuFile);
XmlNodeList topMenus = doc.DocumentElement.ChildNodes;//就是这句
MenuItem[] menuItems = new MenuItem[topMenus.Count];
int i = 0;
foreach ( XmlElement element in topMenus )
{
menuItems[i++] = ProcessMenuItem(element);
}
return menuItems;
}
不改菜单项上中文显示不出来.
1:<Menu Name="&New" ...改成:<Menu Name="&新建"...
2,//原来:<Menu Name="&New" Shortcut="CtrlN" Icon="" Checked="False" Radio="False" Enabled="False"/>
//修改成:<Menu Name="&New" Shortcut="CtrlN" Text="设置" ...>
//并改ProcessMenuItem
在public static MenuItem ProcessMenuItem(XmlElement xmlelement)
{
string menuName = xmlelement.Attributes["Name"].InnerXml;
if ( menuName.IndexOf("&") != -1 )
menuName = menuName.Replace("&", "&");
string menuShortcutString = xmlelement.Attributes["Shortcut"].InnerXml;
string menuIcon = xmlelement.Attributes["Icon"].InnerXml;
string menuChecked = xmlelement.Attributes["Checked"].InnerXml;
string menuRadio = xmlelement.Attributes["Radio"].InnerXml;
string menuEnabled = xmlelement.Attributes["Enabled"].InnerXml;
string name=xmlelement.Attributes["Text"].InnerXml;
//...
}
//
1,2中,我改MainMenu.xml中<?xml version="1.0" encoding="UTF-8"?>的encoding则:
未处理的“System.Xml.XmlException”类型的异常出现在 system.xml.dll 中
其他信息:系统错误。
出错语句是下面语句:
public static MenuItem[] CreateMainMenu()
{
string menuFile = Application.StartupPath + "\\" + "mainmenu.xml";
XmlDocument doc = new XmlDocument();
doc.Load(menuFile);
XmlNodeList topMenus = doc.DocumentElement.ChildNodes;//就是这句
MenuItem[] menuItems = new MenuItem[topMenus.Count];
int i = 0;
foreach ( XmlElement element in topMenus )
{
menuItems[i++] = ProcessMenuItem(element);
}
return menuItems;
}
不改菜单项上中文显示不出来.
poetc 2003-01-08
- 打赏
- 举报
我用的是VSNetMenu,我对不懂xml,问题就在上面;
1:<Menu Name="&New" ...改成:<Menu Name="&新建"...
2,//原来:<Menu Name="&New" Shortcut="CtrlN" Icon="" Checked="False" Radio="False" Enabled="False"/>
//修改成:<Menu Name="&New" Shortcut="CtrlN" Text="设置" ...>
//并改ProcessMenuItem
在public static MenuItem ProcessMenuItem(XmlElement xmlelement)
{
string menuName = xmlelement.Attributes["Name"].InnerXml;
if ( menuName.IndexOf("&") != -1 )
menuName = menuName.Replace("&", "&");
string menuShortcutString = xmlelement.Attributes["Shortcut"].InnerXml;
string menuIcon = xmlelement.Attributes["Icon"].InnerXml;
string menuChecked = xmlelement.Attributes["Checked"].InnerXml;
string menuRadio = xmlelement.Attributes["Radio"].InnerXml;
string menuEnabled = xmlelement.Attributes["Enabled"].InnerXml;
string name=xmlelement.Attributes["Text"].InnerXml;
//...
}
//
1,2中,我改MainMenu.xml中<?xml version="1.0" encoding="UTF-8"?>的encoding则:
未处理的“System.Xml.XmlException”类型的异常出现在 system.xml.dll 中
其他信息:系统错误。
是下面中语句:
public static MenuItem[] CreateMainMenu()
{
string menuFile = Application.StartupPath + "\\" + "mainmenu.xml";
XmlDocument doc = new XmlDocument();
doc.Load(menuFile);
XmlNodeList topMenus = doc.DocumentElement.ChildNodes;//就是这句
MenuItem[] menuItems = new MenuItem[topMenus.Count];
int i = 0;
foreach ( XmlElement element in topMenus )
{
menuItems[i++] = ProcessMenuItem(element);
}
不改菜单项上中文显示不出来.
1:<Menu Name="&New" ...改成:<Menu Name="&新建"...
2,//原来:<Menu Name="&New" Shortcut="CtrlN" Icon="" Checked="False" Radio="False" Enabled="False"/>
//修改成:<Menu Name="&New" Shortcut="CtrlN" Text="设置" ...>
//并改ProcessMenuItem
在public static MenuItem ProcessMenuItem(XmlElement xmlelement)
{
string menuName = xmlelement.Attributes["Name"].InnerXml;
if ( menuName.IndexOf("&") != -1 )
menuName = menuName.Replace("&", "&");
string menuShortcutString = xmlelement.Attributes["Shortcut"].InnerXml;
string menuIcon = xmlelement.Attributes["Icon"].InnerXml;
string menuChecked = xmlelement.Attributes["Checked"].InnerXml;
string menuRadio = xmlelement.Attributes["Radio"].InnerXml;
string menuEnabled = xmlelement.Attributes["Enabled"].InnerXml;
string name=xmlelement.Attributes["Text"].InnerXml;
//...
}
//
1,2中,我改MainMenu.xml中<?xml version="1.0" encoding="UTF-8"?>的encoding则:
未处理的“System.Xml.XmlException”类型的异常出现在 system.xml.dll 中
其他信息:系统错误。
是下面中语句:
public static MenuItem[] CreateMainMenu()
{
string menuFile = Application.StartupPath + "\\" + "mainmenu.xml";
XmlDocument doc = new XmlDocument();
doc.Load(menuFile);
XmlNodeList topMenus = doc.DocumentElement.ChildNodes;//就是这句
MenuItem[] menuItems = new MenuItem[topMenus.Count];
int i = 0;
foreach ( XmlElement element in topMenus )
{
menuItems[i++] = ProcessMenuItem(element);
}
不改菜单项上中文显示不出来.
TheAres 2003-01-08
- 打赏
- 举报
To poetc(伊公子):
Could you please post some code here to let us know what did you do?
And which exampe did you use?
Could you please post some code here to let us know what did you do?
And which exampe did you use?
stdao 2003-01-08
- 打赏
- 举报
then try:
http://www.codeproject.com/cs/miscctrl/ToolBox.asp
It is so wonderful.
http://www.codeproject.com/cs/miscctrl/ToolBox.asp
It is so wonderful.
poetc 2003-01-08
- 打赏
- 举报
我改xml文件中Menu Name;但用中文总出错。改encoding也不成;WHY?
我现在只能不能xml,:(
我现在只能不能xml,:(
poetc 2003-01-08
- 打赏
- 举报
:)
现在明白啦
现在明白啦
TheAres 2003-01-07
- 打赏
- 举报
下面两个是 "vs.net那种" 菜单
Visual Studio .NET Menu Style
http://www.codeproject.com/cs/menu/vsnetmenu.asp
DotNetMagic 1.7
http://www.crownwood.net/index.html
http://www.crownwood.net/features.html
Visual Studio .NET Menu Style
http://www.codeproject.com/cs/menu/vsnetmenu.asp
DotNetMagic 1.7
http://www.crownwood.net/index.html
http://www.crownwood.net/features.html
yarshray 2003-01-07
- 打赏
- 举报
绘制菜单
方法如下
http://www.csharphelp.com/archives/archive282.html
类似菜单如下:
http://www.codeproject.com/useritems/MenuImage.asp
方法如下
http://www.csharphelp.com/archives/archive282.html
类似菜单如下:
http://www.codeproject.com/useritems/MenuImage.asp