Delphi增强RTTI使用技巧征集

不得闲 2011-01-04 11:56:41
加精
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;

...全文
2631 90 打赏 收藏 转发到动态 举报
写回复
用AI写文章
90 条回复
切换为时间正序
请发表友善的回复…
发表回复
wixsky 2011-11-26
  • 打赏
  • 举报
回复
还是用 XE 比较好
lyhoo163 2011-01-27
  • 打赏
  • 举报
回复
空谈,均无实质东西。
Crossgate_J 2011-01-20
  • 打赏
  • 举报
回复
第一页占个位
space_ss 2011-01-19
  • 打赏
  • 举报
回复
听说 d7 的编译器 支持 反射
xeqtrl982 2011-01-18
  • 打赏
  • 举报
回复
[Quote=引用 69 楼 lw549 的回复:]

LZ冲动了,那些星星只是曾经用过Delphi.现在说不定连代码都不写了,能来这里看看已经很不错了。你想让他们说什么呢?
[/Quote]
许多星星机器中都没安装Delphi,你让他们说什么
zwjchina 2011-01-15
  • 打赏
  • 举报
回复
不好意思,我弄错了。XE的优化开关默认是关闭的。
zwjchina 2011-01-15
  • 打赏
  • 举报
回复
虽然说从表面功能开,的确有些新内容,让人眼前一亮。但是不小新随手写了点代码。
查看了反汇编代码,我受到了不小的打击。

一个简单函数:

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


我真是太受刺激了。
myhotdog 2011-01-15
  • 打赏
  • 举报
回复
关于这项技术,我专门写了篇文章论述,大家一起去看看,内容主要如下:
继承并改良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
no543216789 2011-01-14
  • 打赏
  • 举报
回复
2012是神马版本
guduhen 2011-01-14
  • 打赏
  • 举报
回复
我喜欢经典 D7就好了
UndefinedCoder 2011-01-12
  • 打赏
  • 举报
回复
用这东西,很难保持兼容性啊。
勿粘果 2011-01-11
  • 打赏
  • 举报
回复
没看出来有什么用处
啥子时候要用到那个东东在实际的项目中
linchb_ 2011-01-11
  • 打赏
  • 举报
回复
delphi 2010
zhurino2 2011-01-10
  • 打赏
  • 举报
回复
为什么都用老版本呢?!
东东 2011-01-10
  • 打赏
  • 举报
回复
我也来吧,我现在正在用Delphi2010,没什么可说的。用了好多年了。
linghengmao 2011-01-10
  • 打赏
  • 举报
回复
我们公司还在用D6呢。
不得闲 2011-01-10
  • 打赏
  • 举报
回复
[Quote=引用 73 楼 zkroy36 的回复:]

http://www.360doc.com/content/10/0906/16/2962214_51630027.shtml
RTTI浅析 看了下,东西比较清楚,可惜我想用的一个没有
还在用delphi 7
[/Quote]
你这个是很老的东西的!针对所有的Delphi版本都可以使用的!
zkroy36 2011-01-10
  • 打赏
  • 举报
回复
http://www.360doc.com/content/10/0906/16/2962214_51630027.shtml
RTTI浅析 看了下,东西比较清楚,可惜我想用的一个没有
还在用delphi 7
不得闲 2011-01-10
  • 打赏
  • 举报
回复
晚上回去接掉!反正都是做沙发的!如果坐出腰椎病,那就是我的罪过了!
不得闲 2011-01-10
  • 打赏
  • 举报
回复
[Quote=引用 69 楼 lw549 的回复:]

LZ冲动了,那些星星只是曾经用过Delphi.现在说不定连代码都不写了,能来这里看看已经很不错了。你想让他们说什么呢?
[/Quote]
确实冲动了!
加载更多回复(44)

5,386

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧