Delphi增强RTTI使用技巧征集
Delphi2010之后的RTTI,功能有了很大增强,希望能将RTTI的一些技巧使用集中征集一下。那么就由我来抛出这第一块砖头吧!希望大家踊跃跟帖。
我这这个技巧用例主要目的是挂钩某些内部私有事件,然后增加上一些自己的处理过程,这里我以TMenuItem的私有内部事件FOnChange作为例程。这个私有事件在菜单内部绑定,我们平常状态下,在外部无法更改!但是XE之后这个问题不在存在,使用它的全新RTTI,可以很容易的获得一个类对象的基本上所有的类的字段以及方法和属性等。
unit Unit1;
interface
uses
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;
rttiContext: TRttiContext; rtype: TRttiType; rField: TRttiField;
[解决办法]
好谢谢分享
------解决方案--------------------
谢谢分享
[解决办法]
感谢分享
我在用Delphi 7
[解决办法]
支持这个,谁说没人用很多人在用的
[解决办法]