首 页IT知识库收藏内容
当前位置:翔宇亭IT乐园IT知识库C#窗体界面

在C#中使用组件实现office2003风格的菜单

减小字体 增大字体 作者:不详  来源:转载整理  发布时间:2011-05-14 06:59:30

本文介绍了使用C#开发Office2003风格菜单的方法。

本文用到的组件源码及测试程序下载地址

仅仅使用一行简单的程序,你就能够使你的Windows窗体的所有菜单和上下文菜单具有office2003的菜单外观。同样地,你也可以只用一行程序,就能为你的菜单加上漂亮的图标。本文实现的是一个具有该功能的组件。如果你想让你的菜单恢复原来的外观,也只须调用End方法即可。

组件的使用

要正确使用组件,必须先将你的组件加入到工具箱中。然后将该组件从工具箱中拖放放到form窗体中。这时会看到你的form的设计页中多出了一个名为OfficeMenus1的图标,说明已经将菜单组件加入到了form中。紧接着调用如下方法:

//开始显示office 2003菜单
OfficeMenus1.Start( FormName ); 注:FormName为要改变菜单风格的窗口名称。

同样,你也可以通过调用如下方法终止菜单的office2003风格,使之回到原始外观:

// 改变菜单的外观风格到原始状态
OfficeMenus1.End();

为菜单顶添加图标也很简单,只须为工程添加一个ImageList(图像列表控件),然后将OfficeMenu组件的ImageList属性更改为你添加的ImageList,使用如下代码实现:

// 为菜单添加图像
// OfficeMenus.AddPicture( MenuItem MenuItemToAddPictureTo, int ImageIndex );
OfficeMenus1.ImageList = imageList1;
OfficeMenus1.AddPicture(menuItem2, 1);

可以看出,只须如此几行代码就能轻松让你的菜单实现office2003风格。

组件的实现方法及原理

组件由三个类实现,这三个类分别为OfficeMenus,MainMenuItemDrawing和MenuItemDrawing,都位于命名空间Dev4Arabs中。由于实现代码较长,所以在此只给出了组件实现的思路。

组件实现的第一步是从System.ComponentModel.Component类派生类OfficeMenus。定义如下:

public class OfficeMenus : System.ComponentModel.Component

然后在类中定义两静态变量:

//图像列表用来存储菜单中用到的图标
       static ImageList _imageList;
        // 存储图片细节的一个名称集合
       static NameValueCollection picDetails = new NameValueCollection();

NameValueCollection的详细说明请查阅MSDN,该类主要用来使每个菜单的句柄与每个图标形成一一对应的关系,以便后面绘制菜单顶的图标时快速地找到某个菜单所对应的图标。

接下来定义公共接口方法start和End。

Start方法有一个Form类类型的参数,该方法从传入的参数中获得该窗口的主菜单。接下来为每一个主菜单下的MenuItem添加MeasureItem事件处理mainMenuItem_MeasureItem和DrawItem事件处理mainMenuItem_DrawItem,将MenuItem的OwnerDraw属性设置为true,并使用InitMenuItem(Menu mi)方法对每个MenuItem应用改变。然后再从form参数中获取该窗口的上下文菜单对象,对其调用InitMenuItem(Menu mi)应用改变。最后循环查找窗口中包含的每个子控件的上下文菜单,对其应用改变。

公共接口方法Start的实现原理如下:

public void Start(Form form)
{ 
  //从传入的父窗体中获得主菜单
  System.Windows.Forms.MainMenu menu = form.Menu;
  //循环每一个菜单项,为其添加事件处理
  foreach ( MenuItem mi in menu.MenuItems )
  {
    //订阅MesaureItem事件处理
    mi.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(mainMenuItem_MeasureItem);
    //订阅DrawItem事件处理
    mi.DrawItem += new System.Windows.Forms.DrawItemEventHandler(mainMenuItem_DrawItem);
    //将OwnerDraw属性设置为true
    mi.OwnerDraw = true;
    //使用InitMenuItem(Menu mi)方法对每个MenuItem应用改变
    InitMenuItem(mi);
  }
  ContextMenu cmenu = form.ContextMenu;
  if ( cmenu != null ) {InitMenuItem(cmenu);}
  foreach ( Control c in form.Controls ) {
    if ( c.ContextMenu != null )
      InitMenuItem(c.ContextMenu);}
  catch {}
}

End方法与这类似,只须将InitMenuItem换为UninitMenuItem.

为每个菜单应用改变的InitMenuItem方法的实现如下:

循环查找mi中的每个MenuItem,为其添加MeasureItem事件处理menuItem_MeasureItem和DrawItem事件处理menuItem_DrawItem(注意,此处的事件处理方法名称与Start中对主菜单的事件处理方法名称不同),并将OwnerDraw属性设置为true。使用递归调用对每个查找到的MenuItem调用InitMenuItem方法,这样便可以对菜单项下的所有级别的子菜单项都应用到改变。

private void InitMenuItem(Menu mi)
{
   foreach ( MenuItem m in mi.MenuItems )
   {
    // 订阅MesaureItem事件处理
    m.MeasureItem +=
     new System.Windows.Forms.MeasureItemEventHandler(this.menuItem_MeasureItem);
    // 订阅DrawItem事件处理
    m.DrawItem +=
     new System.Windows.Forms.DrawItemEventHandler(this.menuItem_DrawItem);
    // 将OwnerDraw设置为true
    m.OwnerDraw = true;

    // 通过递归调用该方法对所有的子菜单进行相同的设置
    InitMenuItem(m);
   }
}

[1] [2]  下一页

微信搜索“优雅的代码”关注本站的公众号,或直接使用微信扫描下面二维码关注本站公众号,以获取最新内容。

个人成长离不开各位的关注,你的关注就是我继续前行的动力。

知识评论评论内容只代表网友观点,与本站立场无关!

   评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
愿您的精彩评论引起共鸣,带来思考和价值。
用户名: 查看更多评论
分 值:100分 90分 80分 70分 60分 40分 20分
内 容:
验证码:
关于本站 | 网站帮助 | 广告合作 | 网站声明 | 友情连接 | 网站地图
本站部分内容来自互联网,如有侵权,请来信告之,谢谢!
Copyright © 2007-2024 biye5u.com. All Rights Reserved.