韩小明@xiammy的专栏

没水的地方挖井,有水的地方修渠

韩小明ID:xiammy
438152次访问,排名107好友11人,关注者66
毕业后一直在广联达工作
xiammy的文章
原创 174 篇
翻译 0 篇
转载 22 篇
评论 1131 篇
韩小明的公告
作者毕业于浙江大学,非常热爱体育运动。现在尤其热爱羽毛球运动。在休息时间非常热爱技术文章写作。
最近垃圾评论泛滥,为了不污染大家的视听,暂时关闭评论,请大家理解。
欢迎转载,但请注意,除非特别声明,本站采用Creative Commons License许可:署名,非商业。

最近评论
liquankun:瑞星还是不咋地!
白花了几个月的钱
外国的杀软不一定比国产的好!
但是国产的就是比不上国外的!
没办法!技术赶不上人家 还竟搞内讧
不经历大灾难 就不知道什么是团结!



正真的高手是不用杀毒软件的,没什么好不好的,是你自己技术不行而已
wangdei:http://www.bt285.cn BT下载 有300W部BT种子.
http://www.yaonba.com.cn NBA中文网 有200W条NBA直播
http://www.5a520.cn 小说520网 有300W部小说
http://www.bt285.cn/yazhou/ 亚洲BT 有BT亚洲
http://www.bjxlz.cn p……
hemir:不但不知道团结提高,倒是会找枪手到处胡闹。弄的整个环境乌烟瘴气的。
hemir:不但不知道团结提高,倒是会找枪手到处胡闹。弄的整个环境乌烟瘴气的。
hemir:枪手太多,大家都还是相信自己的眼睛吧。个人认为360做的不错。国内的杀毒软件确实不怎么地……
文章分类
收藏
    相册
    图书
    链接
    宗刚的专栏(RSS)
    快乐学习(RSS)
    陈亮亮的专栏(RSS)
    朋友
    张恂论 OO
    言之有李(RSS)
    赵伟的小家
    存档
    订阅我的博客
    XML聚合  FeedSky

    原创 苛评VCL: 失望的TMenu收藏

    新一篇: 苛评VCL: 混乱的TStream | 旧一篇: 苛评VCL: 接口与TObject

    TMenu是什么?他是VCL中封装的TMainMenu和TPopupMenu的基类。与其说对TMenu失望,其实是对VCL中对TMainMenu和TPopupMenu的失望。

    为什么呢?这基本上还得归咎于微软自己。微软在推出Windows的同时,却坚决的在推Office系列产品。而且Office的更新速度和Windows几乎一样快。更重要的是,Office系列产品的界面风格,特别是菜单,和标准Windows的完全不同。

    当微软的Office推广地非常好的时候,我们都在渴望也能设计出一样的界面。对于只是外表改变的需求来讲,很自然地可以考虑重新覆盖TMenuItem的Draw方法。

    可是,当你真的想这么干的时候,你会发现两件事,一件让你高兴,一件让你失望。先说高兴的事吧:

    负责Draw工作的两个方法:AdvancedDrawItem和MeasureItem都是声明的Virtual类型的函数。也就是说,我们完全可以通过覆盖这些方法的方式去实现。而且,显然的,TMenuItem的设计者,显然已经考虑到这样的扩展了。

    而且,通过观察AdvancedDrawItem的实现,你更可以发现你需要修改的代码点。

      if (ParentMenu <> nil) and (ParentMenu.OwnerDraw or (ImageList <> nil)) and
        (Assigned(FOnAdvancedDrawItem) or Assigned(FOnDrawItem)) then
      begin
        DrawItem(ACanvas, ARect, Selected);
        
    if Assigned(FOnAdvancedDrawItem) then
          FOnAdvancedDrawItem(Self, ACanvas, ARect, State);
      end 
    else
        
    if (ParentMenu <> nil) and (not ParentMenu.IsRightToLeft) then
          NormalDraw
        
    else
          BiDiDraw;

    请注意看NormalDraw和BiDiDraw。那么我们的OfficeDraw只要并列选择就可以了。当然了,如果要完全放弃原来的画法,那就更容易了。

    遗憾的是,我们必须听另一个让人失望的事。那就是,Menus单元中,所有创建TMenuItem的地方,都是直接调用TMenuItem.Create的方式。如果你想派生一个TOfficeMenuItem类,你无法找到能创建你的类的地方。

    这种情况,一般的设计就是,在TMenu类中有一个虚拟方法,返回一个类型为TMenuItem的实例。至于用哪个具体的类型,可以有TMenu的派生类来决定。比如,你自定一个TOfficeMenu,当创建TMenuItem的实例的时候,使用TOfficeMenuItem创建。简单一点就是下面的代码:

    function CreateMenuItem: TMenuItem; override;

    而实现的时候,简单用下面的代码实现:

    Result := TOfficeMenuItem.Create;

    每当我不得不面对这个现实的时候,我就开始考虑是不是有办法绕过去。有一种办法,是实现TMenuItem的OnDrawItem事件。还有一种办法,就是直接使用HOOK的方式替换TMenuItem类。

    我能想到的上面两个方法,都只算是在特定应用中解决问题的办法。作为热衷组件化设计的我来讲,显然更愿意自己实现一个TOfficeMenu和TOfficeMenuItem。并且不是仅仅通过修改事件,而是完全通过面向对象的多态性来完成这个功能。

    失望TMenu是因为其扩展性方面的欠考虑,因为此,导致VCL中默认就代用两种方式。而第三方蓬勃发展的如TBX系列和Raze系列界面控件,也都证明了其设计方面的欠缺。

    其实我们也可正好可以思考一下,设计,应该考虑好开闭原则。特别是“对未来的派生是开放的”这一点。怎么样的设计都可以完成目前的功能。可是能不能考虑到以后的扩展,那就是设计的好坏了。

     

    发表于 @ 2007年02月04日 01:24:00|评论(loading...)|编辑

    新一篇: 苛评VCL: 混乱的TStream | 旧一篇: 苛评VCL: 接口与TObject

    评论

    #Stanley_Xu 发表于2007-02-05 18:54:10  IP: 141.24.49.*
    LZ可以参考一下 TntControls 包中 TTntMenuItem 的思路。不过我还是不太明白你想表达的意思。市面上还有 xpmenu 也可以画office的效果。这类控件的处理方法难道有问题吗?

    我只是觉得vcl里面带image的菜单是模仿系统菜单在那里重绘。这个有点欠妥。应该考虑使用标准的api来实现。不相信可以去看看vista下面,菜单不伦不类的样子。
    #xiammy 发表于2007-02-05 20:43:58  IP: 221.216.175.*
    呵呵,谢谢推荐TTntMenuItem
    其实这里面我不是在说一个实现的问题,而是说一个设计的问题。我只是更想OO一点去完成一个功能扩展。
    #Rural_Boy 发表于2007-05-16 12:08:46  IP: 125.92.162.*
    无知小辈的无知之言.连看几篇" 苛评", 绕来绕去没离开过 有关 Office 风格界面的问题.所讲鸡毛蒜皮,更错误层出不穷.

    当小辈的不能说大话. 没想过自己来设计 VCL 会怎样吗?
    #Rural_Boy 发表于2007-05-16 12:10:08  IP: 125.92.162.*
    补充:

    那么喜欢 office 风格,不会自己去写一些出来?
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © 韩小明