在很多应用都是界面左侧是一个树形菜单,右侧则是内容展示区,不管是 web 应用或者客户端应用都随处可见这种布局。从技术实现上来说, web 应用有 frameset 、程序的 extjs 等框架可以很容易实现,而客户端应用传统的 mdi 实现不能实现此效果,为此需要程序员另辟蹊径。之前做的一个项目 C# 客户端连 J2EE 应用,即实现了左边树形菜单右边 Form 展示区的类 MDI ,技术关键是利用反射,根据树形菜单中的 Form 路径创建出 Form 窗体,在右侧的 Tabcontrol 加以展示,其中些许关键代码在此贴上。
1、 界面样子,由于不能贴图,用 table 简单表示
应用程序名称, logo 展示区 | |
常用功能按键区(退出、修改密码等) | |
树形菜单, tree | Form 展示区, tabcontrol |
状态信息,操作信息 |
2、 树形菜单操作,设计树形菜单加载、菜单选中事件处理等
操作树形菜单的关键就是获取 tree node 保存的菜单路径信息,即 form 路径信息(通常是 namespace.classname ),这里将 form 路径信息存放到了 node.tag 属性中。下述所示为选中 tree node 触发的事件代码。
/// <summary> /// 点击节点打开相应的窗口,利用反射实现 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void tree_Menu_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node.Tag == null ) return ; string funcModulePath = (String) e.Node.Tag;
funcModulePath = funcModulePath.Trim();
// 如果该form 已经加载,则在tabcontrol 中选中对应的tab 页 foreach (TabPage a in this .panelTab1.Controls) { if (a.Tag == null ) continue ; if (((String )a.Tag) == funcModulePath) { this .panelTab1.SelectedTab = a; return ; } }
TabPage newPage = new System.Windows.Forms.TabPage (); newPage.Text = e.Node.Text + this .panelTab1.Space; newPage.Tag = nodeTag.Func_module; this .panelTab1.Controls.Add(newPage); this .panelTab1.SelectedIndex = this .panelTab1.Controls.Count - 1; // 利用反射构建窗体 Type type; Form obj; try { type = this .getAssemblyType(funcModulePath); obj = (Form )Activator .CreateInstance(type); // 设置窗口属性 System.Reflection.PropertyInfo windowState = type.GetProperty("WindowState" ); windowState.SetValue(obj, FormWindowState .Maximized, null );
System.Reflection.PropertyInfo formBorderStyle = type.GetProperty("FormBorderStyle" ); formBorderStyle.SetValue(obj, FormBorderStyle .None, null );
System.Reflection.PropertyInfo topLevel = type.GetProperty("TopLevel" ); topLevel.SetValue(obj, false , null );
System.Reflection.PropertyInfo dock = type.GetProperty("Dock" ); dock.SetValue(obj, DockStyle .Fill, null );
System.Reflection.PropertyInfo tag = type.GetProperty("Tag" ); tag.SetValue(obj, nodeTag, null );
System.Reflection.PropertyInfo autoscroll = type.GetProperty("AutoScroll" ); autoscroll.SetValue(obj, true , null );
// 将窗体显示到tabcontrol 中 newPage.Controls.Add(obj);
System.Reflection.MethodInfo showMethod = type.GetMethod("Show" , new Type [] { }); showMethod.Invoke(obj, null ); } catch (Exception ex) { MessageBox .Show(ex.Message); } finally { type = null ; obj = null ; } } |
3、 tabcontrol 的美化
vs2005 自带的 tabcontrol 控件实在是不这么好看,因此需继承 tabcontrol ,并且扩展它,这里就不再赘述。