Written by flexitime

PS: 有鉴于几位热心网友的意见,所以还是决定写一下一些技术相关的BLOG,并希望能有网友不吝赐教

DevExpress是一个十分有名的Delphi控件套装,这个套件很多时候都是带有原码的,而我这篇文章正如题目所述的问题,是研究在dxBar中动态添加菜单。其实要完成这件事情并不困难,只是几行代码就说明问题了,但为什么要写这篇文章呢,主要的目的在于说明如何在没有其它资料可查的情况下,通过查源代码找到问题的解决方法。

首先,要使用TdxBar,我们要先在Form上添加一个TdxBarManager的控件,双击这个控件会弹出一个对话框,在ToolBar这一页上点击New..,再输入这个这个Bar的名字(例如 dxbMainMenu),这样就可以生成一个TdxBar了,如果要把这个TdxBar设置成为主菜单的话,那么只需要设置一下IsMainMenu属性为true即可。如果要手工在这个TdxBar实例dxbMainMenu上添加一些菜单项的话,那么可以通过在dxbMainmenu的右键菜单中选择对应的Add SubItem, Add Button等选项去完成。这里不再逐一细表了。
现在关键的问题在于如何在这个TdxBar中通过代码动态添加这些菜单项。
按照一般的思路,我们会有以下几种方案去考虑这个问题
第一.在dxBar中寻找有没有对应的方法,这些方法的名字可能是Add,Insert等等,但十分可惜的事,dxBar中并没有提供这些方法。
第二.我们看一下刚才手工生成的那些对像如 TdxBarSubItem有没有Parent或dxBar的对像,因为有可能会这样的方式来产生相应的菜单:
Bar := TdxBar.Create(nil);
Bar.dxBar := dxbmainMenu; 或 Bar.Parent := dxbmainMenu;
等等,但仍然是找不到合适的对像。
既然,以上常规的方式都找不到正确的方法,那么我们换一个角度去考虑,刚才dxBar其实是由dxBarManager生成出来的。因此,有解决的方法可能会通过dxBarManager才能完成。我们可以在dxBarManager找到一些与Add相关的方法
AddButton
AddSubitem
AddItem
AddToolBar
其中AddToolBar肯定不是我们想要的东西,那么我们通过DevExpress提供的源码(dxBar.pas)查一下这几个方法的实现:
function TdxBarManager.AddButton: TdxBarButton;
begin
 Result := TdxBarButton(AddItem(TdxBarButton));
end;
 
function TdxBarManager.AddItem(AClass: TdxBarItemClass): TdxBarItem;
var
 ACategoryIndex: Integer;
begin
 Result := AClass.Create(Self);
 ACategoryIndex := Categories.IndexOf(dxSBAR_DEFAULTCATEGORYNAME);
 if ACategoryIndex = -1 then
    ACategoryIndex := 0;
 Result.Category := ACategoryIndex;
end;
 
function TdxBarManager.AddSubItem: TdxBarSubItem;
begin
 Result := TdxBarSubItem(AddItem(TdxBarSubItem));
end;
通过代码,可以十分明显地知道,原来AddButton及AddSubItem都是调用AddItem的,而AddItem的作用是通过传入的特定的某些类名来产生相应的对象的,我们可以写以下的代码来试验一下
var
 asi : TdxBarSubItem;
begin
 asi := self.dxBarManager1.AddSubItem;
 asi.Caption := '菜单1';
….
很遗憾,这些代码根本不增加一个菜单子项。
线索似乎又断了,但回想一下,在dxBarManager中提供这个AddItem的方法肯定是有用的,要不然不会多此一举,因此,我们利用搜索的功能看一下那些地方调用了这个方法(最好在Delphi的环境中安装GExpert,利用它的Grep功能来搜),我们可以在同一个源文件中找到这样的内容
function TdxBarItemLinks.AddItem(AItemClass: TdxBarItemClass): TdxBarItemLink;
begin
 Result := Add(BarManager.AddItem(AItemClass));
end;
 
function TdxBarItemLinks.AddButton: TdxBarItemLink;
begin
 Result := Add(BarManager.AddButton);
end;
 
function TdxBarItemLinks.AddSubItem: TdxBarItemLink;
begin
 Result := Add(BarManager.AddSubItem);
end;
十分明显,在TdxBarItemLinks中调用了TdxBarMangerger的AddItem方法,但这个TdxBarItemLinks又是何方神圣呢?我们再去查这个TdxBarItemLinks的类,发现很多地方都有这个类的对象成员,其中包括我们想要的TdxBar类。
至此,我们可以测试一下以下的代码了:
var
 asi : TdxBarSubItem;
 il : TdxBarItemLink;
begin
 asi := self.dxBarManager1.AddSubItem;
 asi.Caption := '菜单1';
 dxbrMainMenu.ItemLinks.Add (asi);
end;
运行看看,这次真的可以在dxbrMainMenu中添加了一个菜单项了,虽然是一个空项,但没有关系,这是个好的开始。
我们再来看,这个新加上去菜单项是在菜单的末尾的,如果我们想把它放在前面的话,那么应该如何办呢?
一般来说在Delphi的习惯都是用Add或Append来进行追加,用Insert来插入,而刚好TdxBarItemLinks也正好符合这种说法,我们来看Insert的实现
function TdxBarItemLinks.Insert(AIndex: Integer): TdxBarItemLink;
begin
 Result := TdxBarItemLink(inherited Insert(AIndex));
end;
原来是调用基类的方法,而TdxBarItemLinks的基类是我们十分熟悉的VCL组件TCollection,而它的Insert代码如下,
function TCollection.Insert(Index: Integer): TCollectionItem;
begin
 Result := Add;
 Result.Index := Index;
end;
看代码就知道原来是调用Add方法,但这个Add方法是不带参数的,与我们刚才提到的方法有所不一样。
我们找回那两个Add方法来看看
function TdxBarItemLinks.Add: TdxBarItemLink;
begin
 Result := TdxBarItemLink(inherited Add);
end;
 
function TdxBarItemLinks.Add(AItem: TdxBarItem): TdxBarItemLink;
begin
 BeginUpdate;
 try
    Result := Add;
    Result.Item := AItem;
 finally
    EndUpdate;
 end;
end;
原来有参的Add方法也是调用这个无参的Add方法,而看到有参数的那个Add方法后,是否有些启示呢,我们可以利用TdxBarItemLink.Item来实现某些我们想要的功能,那么代码就变成这样了
var
 asi : TdxBarSubItem;
 il : TdxBarItemLink;
 abb : TdxBarButton;
begin
 asi := self.dxBarManager1.AddSubItem;
 asi.Caption := '菜单1';
 il := dxbrMainMenu.ItemLinks.Insert(0);
 il.Item := asi;
这样,就可以把生成出来的菜单项放在前面了。
现在我们来看看如何生成子项了,其实我们已经有了前面的基础,要生成子项也是十分容易的了,可以不用再查源程序了,直接就写出以下的代码
var
 asi : TdxBarSubItem;
 il, il2 : TdxBarItemLink;
 abb : TdxBarButton;
begin
 asi := self.dxBarManager1.AddSubItem;
 asi.Caption := '菜单1';
 il := dxbrMainMenu.ItemLinks.Insert(0);
 il.Item := asi;
 
 abb := self.dxBarManager1.AddButton;
 abb.Caption := '子项1';
 il2 := asi.ItemLinks.Insert(0);
 il2.Item := abb;
end;
至此,我们就完成了这个动态添加菜单的例子了。

动态添加DevExpress 套件中 dxBar的菜单项目相关推荐

  1. 向html中追加内容,将数据内容动态添加到HTML中

    // 申明一个数组用来装遍历的元素 var li = []; //遍历元素并加载到标签中 for(var i = 0; i var nav_li = ' '+navGroup.self_first_n ...

  2. vue给html动态添加属性,Vue中怎么动态添加类名?

    能够向组件添加动态类名是非常强大的功能.它使我们可以更轻松地编写自定义主题,根据组件的状态添加类,还可以编写依赖于样式的组件的不同变体. 添加动态类名与在组件中添加 prop :class=" ...

  3. JS从后台获取数据,前台动态添加tr标签中的td标签

    功能描述: 要求从后台查询该省份的所有城市,然后动态的再前台固定的tr标签中添加相应的td标签来展示城市基本信息: 文章目录 #一.前台jsp及js源码 jsp:在固定的tr标签中添加一个id,通过j ...

  4. ajax遍历数组对象数组对象数组,javascript - 从ajax json请求中,如何将对象动态添加到数组中,以便我可以遍历它们? - 堆栈内存溢出...

    您做对了,但是没有在正确的地方进行. jQuery.ajax不会等待响应,但会在请求得到响应时调用"成功"回调. 尝试这个: var i, venues, allVenues=[] ...

  5. DevExpress中实现代码动态添加MenuStrip菜单栏控件内容

    一.实现效果 二.实现操作 2.1.添加MenuStrip控件 2.2.编写动态添加菜单栏内容代码 /// <summary>/// 给菜单控件添加名称/// </summary&g ...

  6. vue 动态添加click_vue,在模块中动态添加dom节点,并监听

    vue向数组中动态添加数据 vue中数据更新通过v-model实现,向数组中添加数据通过push()实现,向shortcuts数组中动态添加newShortcut对象中的title和action th ...

  7. vue中使用动态添加路由(router.addRoutes)加载权限侧边栏的两种方式

    工作中我们经常会遇到这种需求,后台定义用户的权限数据,前端进行获取,并渲染在侧边栏导航上,不同权限的用户看到的侧边栏是不同的.即前端渲染的数据是随着后台的改变而改变的,做到真正的前后端分离. 一.拿到 ...

  8. asp.net动态添加控件学习

    看了老师的教程后,自己一点感悟记录下来: 1.在页面提交后,动态生成的控件会丢失, 但如果生成控件的代码在pageload中,就可以,原理是每次生成页面都执行生成. 2.动态按件或页面原来控件, 在页 ...

  9. 我的Python学习笔记(四):动态添加属性和方法

    一.动态语言相关概念 1.1 动态语言 在运行时代码可以根据某些条件改变自身结构 可以在运行时引进新的函数.对象.甚至代码,可以删除已有的函数等其他结构上的变化 常见的动态语言:Object-C.C# ...

最新文章

  1. 编写python程序一年365天_编写第一个Python程序
  2. django中使用原生sql
  3. 使用LD链接时候文件的顺序
  4. 在struts2 中通过ActionContext访问Session对象
  5. Zorin OS:Windows用户无痛转移Linux
  6. Java二维码的生成以及附加Logo
  7. 基于Java JAAS表单的身份验证
  8. ubuntu记录pdf手写笔记: 数位板(硬件)+xournal(软件)
  9. AES攻击方法 :差分密码分析 boomerang attack飞去来器攻击
  10. 在PC下载微信视频号里面的视频
  11. 小鸡腿U T7 NEERC2011
  12. bzoj1779 [Usaco2010 Hol]Cowwar 奶牛战争(网络流)
  13. 色彩空间(RGB, HSV, LAB, YUV)
  14. 高级驾驶辅助系统ADAS技术介绍
  15. 细菌完成图+比较基因组分析添好文
  16. AI与未来文明:人工智能能否重塑人类文化,改变社会生活?
  17. Unity Dotween常用方法详解
  18. OAI搭建——硬件准备
  19. Hgame-Week1
  20. 可汗学院的数学从零开始学习顺序?

热门文章

  1. 如何在word文档贴一手好看的代码
  2. NYOJ 354 问当n个物品合成一个时,最小重量是多少?
  3. 玩转MongoDB—搭建MongoDB集群
  4. 传感器实验——485空气温湿度
  5. Hadoop单节点搭建
  6. linux关机不用root用户,小白入门:Linux的重启命令和关机命令
  7. Flutter(五)——单一子元素组件
  8. Java枚举(enum)常用的用法总结
  9. 南卡A2降噪耳机评测:纯净外观清音入耳时刻静享万物声
  10. ICMP Destination unreachable(Host administratively prohibited)