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;
我这这个技巧用例主要目的是挂钩某些内部私有事件,然后增加上一些自己的处理过程,这里我以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;
http://www.cnblogs.com/DxSoft/archive/2011/01/04/1925907.html
还有谁在使用delphi?
.....目前还在较低版本 Delphi 7 混迹 有空升级下 研究下LZ的东西
delphi到底会发展怎样?谁也说不清,但有一点是最明白不过的,很多人(当然也包括了)正用delphi7赚取大把的RMB
rttiContext: TRttiContext;
rtype: TRttiType;
rField: TRttiField;这部分是关键
rttiContext: TRttiContext;
rtype: TRttiType;
rField: TRttiField;
那么好!既然沙发就全部沙发到底吧!3天后揭帖!为了响应Delphi版的沙发风气,以后绝对只灌水!
我在用Delphi 7
TValue.From<TMyEnum>(EnumValue).ToString;
RTTI浅析 看了下,东西比较清楚,可惜我想用的一个没有
还在用delphi 7
继承并改良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
查看了反汇编代码,我受到了不小的打击。一个简单函数: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
我真是太受刺激了。