Delphi2010之后的RTTI,功能有了很大增强,希望能将RTTI的一些技巧使用集中征集一下。那么就由我来抛出这第一块砖头吧!希望大家踊跃跟帖。
    我这这个技巧用例主要目的是挂钩某些内部私有事件,然后增加上一些自己的处理过程,这里我以TMenuItem的私有内部事件FOnChange作为例程。这个私有事件在菜单内部绑定,我们平常状态下,在外部无法更改!但是XE之后这个问题不在存在,使用它的全新RTTI,可以很容易的获得一个类对象的基本上所有的类的字段以及方法和属性等。unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, StdCtrls;type
  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
    procedure FormShow1(Sender: TObject);
    procedure MenuItemChange(Sender: TObject; Source: TMenuItem; Rebuild: Boolean);
  public
    { Public declarations }
    OldCode: Pointer;
    OldMenuItemChangeCode: Pointer;
    OldSelfData: TObject;
  end;var
  Form1: TForm1;implementation
uses Rtti,TypInfo;procedure TForm1.Button1Click(Sender: TObject);
var
  Item: TMenuItem;
begin
  Item := TMenuItem.Create(self);
  Item.Caption := '测试';
  MainMenu1.Items.Add(item);
end;procedure TForm1.Button2Click(Sender: TObject);
var
  Item: TMenuItem;
begin
  Item := TMenuItem.Create(self);
  Item.Caption := '测试';
  if MainMenu1.Items.Count > 0 then
    MainMenu1.Items.Items[0].Add(item);
end;procedure TForm1.FormCreate(Sender: TObject);
var
  rttiContext: TRttiContext;
  rtype: TRttiType;
  rField: TRttiField;
  V: TValue;
begin
  rttiContext := TRttiContext.Create;
  rtype := rttiContext.GetType(TMenuItem);
  rField := rType.GetField('FOnChange');
  if rField <> nil then
  begin
     V := rField.GetValue(MainMenu1.Items);
     OldMenuItemChangeCode := TValueData(V).FAsMethod.Code;
     OldSelfData := TValuedata(V).FAsMethod.Data;
     TValueData(V).FAsMethod.Code := @TForm1.MenuItemChange;//菜单项目变化
     TValueData(V).FAsMethod.Data := self;
     rField.SetValue(self.MainMenu1.Items,v);
  end;
end;procedure TForm1.MenuItemChange(Sender: TObject; Source: TMenuItem;
  Rebuild: Boolean);
var
  m: procedure(selfData: TObject;Sender: TObject; Source: TMenuItem;
  Rebuild: Boolean);
begin
  if Assigned(OldMenuItemChangeCode) then
  begin
    m := OldMenuItemChangeCode;
    m(OldSelfData,Sender,Source,Rebuild);
  end;
  ShowMessage('菜单修改事件挂钩');
end;

解决方案 »

  1.   

    完整解释请看本人博客
    http://www.cnblogs.com/DxSoft/archive/2011/01/04/1925907.html
      

  2.   

    据说2010的RTTI支持Record了,没试过,有空试试。
      

  3.   

    现在除了没有办法的几个人之外
    还有谁在使用delphi?
      

  4.   

    还在用Delphi7呢,2010暂时是不打算用了
      

  5.   

    DELPHI2010(11)很多东西还没研究, 先学习了.很多东西还是用DELPHI来做最方便! 建议升级到新版本. 
      

  6.   

    现在还在用bcb6.0,一直没升级过
      

  7.   

    感谢分享
    .....目前还在较低版本 Delphi 7 混迹 有空升级下 研究下LZ的东西
      

  8.   

    现在delphi版风气很差
    delphi到底会发展怎样?谁也说不清,但有一点是最明白不过的,很多人(当然也包括了)正用delphi7赚取大把的RMB
      

  9.   

    dd if=/dev/sda of=MBR bs=512 count=1 
      

  10.   

    哈,Delphi2010!没用过,哪里有下的?
      

  11.   

      
      rttiContext: TRttiContext;
      rtype: TRttiType;
      rField: TRttiField;这部分是关键
      

  12.   

        
        rttiContext:   TRttiContext;
        rtype:   TRttiType;
        rField:   TRttiField;
     
      

  13.   

    看来现在的Delphi,有兴趣来撒点东西的人都没有了!一排的猩猩全部沙发!
    那么好!既然沙发就全部沙发到底吧!3天后揭帖!为了响应Delphi版的沙发风气,以后绝对只灌水!
      

  14.   

    感谢分享
    我在用Delphi 7
      

  15.   

    我也来吧,我现在正在用Delphi2010,没什么可说的。用了好多年了。
      

  16.   

    哪些是符合技巧级别的呢?这个算不算,枚举值转字符串
    TValue.From<TMyEnum>(EnumValue).ToString;
      

  17.   

    LZ冲动了,那些星星只是曾经用过Delphi.现在说不定连代码都不写了,能来这里看看已经很不错了。你想让他们说什么呢?
      

  18.   

    http://www.360doc.com/content/10/0906/16/2962214_51630027.shtml
       RTTI浅析 看了下,东西比较清楚,可惜我想用的一个没有
    还在用delphi 7
      

  19.   

    你这个是很老的东西的!针对所有的Delphi版本都可以使用的!
      

  20.   

    关于这项技术,我专门写了篇文章论述,大家一起去看看,内容主要如下:
    继承并改良TButton
    用TCanvas在TButton表面绘图
    TButton的渐变背景图
    Gradient背景图的制作
    按钮的渐变背景图
    圆角边框的制作过程
    VCL消息详解之WM_PAINT
    研究:WMPaint(var Message: TWMPaint); message WM_PAINT;
    TControlCanvas和WMPaint()
    TBitmap.Create;的应用
    override 鼠标事件
    一个专门用于在button表面写字的函数
    圆角按钮的制作过程(第三方组件开发)这篇文章节选自:Delphi高级组件开发指南 第一篇URL:http://www.docin.com/p-116784103.html下载DelphiDemos.zip:http://bigengineer.blog.ccidnet.com/blog-htm-do-showone-uid-369088-type-blog-itemid-20070074.html文档Flash:http://www.docin.com/DocinViewer-116784103-144.swf按钮TJHLButton组件下载:DelphiDemos.zip 
    http://www.filefactory.com/file/b4he896/n/DelphiDemos.zip
      

  21.   

    虽然说从表面功能开,的确有些新内容,让人眼前一亮。但是不小新随手写了点代码。
    查看了反汇编代码,我受到了不小的打击。一个简单函数:function MulInt2(I: Integer): Integer;
    begin
      Result := I * 2;
    end;
    Delphi7编译结果:  add eax, eax
      ret
    Delphi XE编译结果:  push ebp
      mov ebp,esp
      add esp,-$08
      mov [ebp-$04],eax
      mov eax,[ebp-$04]
      add eax,eax
      mov [ebp-$08],eax
      mov eax,[ebp-$08]
      pop ecx
      pop ecx
      pop ebp
      ret
    我真是太受刺激了。
      

  22.   

    许多星星机器中都没安装Delphi,你让他们说什么