下面的方法保存回调函数于一个堆栈中,并与一个基于字串的列表相连,参数则保存在一个缓冲中。这种方法在分析器引擎中常常用到。
下面是该构件的源程序,它包含一个 stringlist。在此 stringlist 的对象数组中保存了一个堆栈的指针。
这些指针指向回调函数。开发者可以用它们来生成基于字串的触发器。触发器在缓冲属性被设置时触发。
这些处于堆栈内的指针允许开发者对他们作临时性的改变,并且要回到通常的调用方式也很轻松。
--- TriggerCB ---
unit TriggerCB;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
contnrs;
type
PFunc = function (msg:String) : Integer;
TTriggerType = ( ttPrefix, ttSubStr );
TTriggerList = class(TStringList)
private
list:TStringList;
public
procedure AddFunc(s: String; p: PFunc);
procedure AddTrigger(s: String; p: PFunc);
function GetFunc(s: String): PFunc;
function GetTriggeredFunc(s: String; t: TTriggerType): PFunc;
procedure RemoveFunc(s: String);
procedure RemoveTrigger(s: String);
constructor Create;
destructor Destroy; override;
end;
TTriggerCB = class(TComponent)
private
FTriggerType: TTriggerType;
FTriggerList: TTriggerList;
Fbuffer: String;
procedure SetTriggerType(const Value: TTriggerType);
procedure SetTriggerList(const Value: TTriggerList);
procedure Setbuffer(const Value: String);
{ Private declarations }
protected
{ Protected declarations }
public
constructor Create(AOwner:TComponent); override;
destructor Destroy; override;
published
property TriggerType:TTriggerType read FTriggerType write SetTriggerType default ttPrefix;
property TriggerList:TTriggerList read FTriggerList write SetTriggerList;
property buffer:String read Fbuffer write Setbuffer;
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TTriggerCB]);
end;
{ TTriggerCB }
constructor TTriggerCB.Create(AOwner:TComponent);
begin
inherited;
FTriggerList := TTriggerList.Create;
FTriggerType := ttPrefix;
end;
destructor TTriggerCB.Destroy;
begin
inherited;
FTriggerList.free;
end;
procedure TTriggerCB.Setbuffer(const Value: String);
var
p:PFunc;
begin
Fbuffer := Value;
p:=FTriggerList.GetTriggeredFunc(Fbuffer, FTriggerType);
if (@p<>Nil) then p(Fbuffer);
end;
procedure TTriggerCB.SetTriggerList(const Value: TTriggerList);
begin
FTriggerList := Value;
end;
procedure TTriggerCB.SetTriggerType(const Value: TTriggerType);
begin
FTriggerType := Value;
end;
{ TTriggerList }
procedure TTriggerList.AddFunc(s: String; p: PFunc);
var
i:Integer;
stack:TStack;
begin
i := list.IndexOf(s);
if (i<>-1) then begin
stack := TStack(list.Objects[i]);
if (stack<>Nil) then begin
stack.Push(@p);
end;
end;
end;
procedure TTriggerList.AddTrigger(s: String; p: PFunc);
var
stack:TStack;
begin
stack := TStack.Create;
list.AddObject(s, stack);
stack.Push(@p);
end;
constructor TTriggerList.Create;
begin
list:=TStringList.Create;
end;
destructor TTriggerList.Destroy;
begin
inherited;
while list.Count > 0 do begin
list.Objects[0].free;
list.Delete(0);
end;
list.Free;
end;
function TTriggerList.GetFunc(s: String): PFunc;
var
i:Integer;
stack:TStack;
begin
Result:=Nil;
i := list.IndexOf(s);
if (i<>-1) then begin
stack := TStack(list.Objects[i]);
if (stack<>Nil) then begin
if (stack.Count>0) then
Result := Pointer(stack.Peek);
end;
end;
end;
function TTriggerList.GetTriggeredFunc(s: String; t: TTriggerType): PFunc;
var
i:Integer;
p:Integer;
begin
Result:=Nil;
for i:=0 to list.Count-1 do begin
p := Pos(list.Strings[i], s);
if (t = ttSubStr) and (p > 0) then break;
if (t = ttPrefix) and (p = 1) then break;
end;
if (i < list.Count) then begin
Result := GetFunc(list.Strings[i]);
end;
end;
procedure TTriggerList.RemoveFunc(s: String);
var
i:Integer;
stack:TStack;
begin
i := list.IndexOf(s);
if (i<>-1) then begin
stack := TStack(list.Objects[i]);
if (stack<>Nil) then begin
if stack.Count>0 then
stack.Pop;
end;
end;
end;
procedure TTriggerList.RemoveTrigger(s: String);
var
i:Integer;
begin
i := list.IndexOf(s);
if (i<>-1) then begin
list.Objects[i].free;
list.Delete(i);
end;
end;
end.
--- Unit1 --
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
TriggerCB, StdCtrls, shellapi;
type
TForm1 = class(TForm)
TriggerCB1: TTriggerCB;
Button1: TButton;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
function MyFunc(s:String):Integer;
begin
ShowMessage(s);
result:=0;
end;
function MyFunc2(s:String):Integer;
begin
ShowMessage('2');
result:=0;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
TriggerCB1.TriggerType := ttSubStr;
TriggerCB1.TriggerList.AddTrigger('wow', @MyFunc);
TriggerCB1.TriggerList.AddFunc('wow', @MyFunc2);
TriggerCB1.buffer := 'it is wownderful';
TriggerCB1.TriggerList.RemoveFunc('wow');
TriggerCB1.buffer := 'it is wownderful';
TriggerCB1.TriggerList.RemoveFunc('wow');
TriggerCB1.buffer := 'it is wownderful';
end;
end.
下面是该构件的源程序,它包含一个 stringlist。在此 stringlist 的对象数组中保存了一个堆栈的指针。
这些指针指向回调函数。开发者可以用它们来生成基于字串的触发器。触发器在缓冲属性被设置时触发。
这些处于堆栈内的指针允许开发者对他们作临时性的改变,并且要回到通常的调用方式也很轻松。
--- TriggerCB ---
unit TriggerCB;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
contnrs;
type
PFunc = function (msg:String) : Integer;
TTriggerType = ( ttPrefix, ttSubStr );
TTriggerList = class(TStringList)
private
list:TStringList;
public
procedure AddFunc(s: String; p: PFunc);
procedure AddTrigger(s: String; p: PFunc);
function GetFunc(s: String): PFunc;
function GetTriggeredFunc(s: String; t: TTriggerType): PFunc;
procedure RemoveFunc(s: String);
procedure RemoveTrigger(s: String);
constructor Create;
destructor Destroy; override;
end;
TTriggerCB = class(TComponent)
private
FTriggerType: TTriggerType;
FTriggerList: TTriggerList;
Fbuffer: String;
procedure SetTriggerType(const Value: TTriggerType);
procedure SetTriggerList(const Value: TTriggerList);
procedure Setbuffer(const Value: String);
{ Private declarations }
protected
{ Protected declarations }
public
constructor Create(AOwner:TComponent); override;
destructor Destroy; override;
published
property TriggerType:TTriggerType read FTriggerType write SetTriggerType default ttPrefix;
property TriggerList:TTriggerList read FTriggerList write SetTriggerList;
property buffer:String read Fbuffer write Setbuffer;
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TTriggerCB]);
end;
{ TTriggerCB }
constructor TTriggerCB.Create(AOwner:TComponent);
begin
inherited;
FTriggerList := TTriggerList.Create;
FTriggerType := ttPrefix;
end;
destructor TTriggerCB.Destroy;
begin
inherited;
FTriggerList.free;
end;
procedure TTriggerCB.Setbuffer(const Value: String);
var
p:PFunc;
begin
Fbuffer := Value;
p:=FTriggerList.GetTriggeredFunc(Fbuffer, FTriggerType);
if (@p<>Nil) then p(Fbuffer);
end;
procedure TTriggerCB.SetTriggerList(const Value: TTriggerList);
begin
FTriggerList := Value;
end;
procedure TTriggerCB.SetTriggerType(const Value: TTriggerType);
begin
FTriggerType := Value;
end;
{ TTriggerList }
procedure TTriggerList.AddFunc(s: String; p: PFunc);
var
i:Integer;
stack:TStack;
begin
i := list.IndexOf(s);
if (i<>-1) then begin
stack := TStack(list.Objects[i]);
if (stack<>Nil) then begin
stack.Push(@p);
end;
end;
end;
procedure TTriggerList.AddTrigger(s: String; p: PFunc);
var
stack:TStack;
begin
stack := TStack.Create;
list.AddObject(s, stack);
stack.Push(@p);
end;
constructor TTriggerList.Create;
begin
list:=TStringList.Create;
end;
destructor TTriggerList.Destroy;
begin
inherited;
while list.Count > 0 do begin
list.Objects[0].free;
list.Delete(0);
end;
list.Free;
end;
function TTriggerList.GetFunc(s: String): PFunc;
var
i:Integer;
stack:TStack;
begin
Result:=Nil;
i := list.IndexOf(s);
if (i<>-1) then begin
stack := TStack(list.Objects[i]);
if (stack<>Nil) then begin
if (stack.Count>0) then
Result := Pointer(stack.Peek);
end;
end;
end;
function TTriggerList.GetTriggeredFunc(s: String; t: TTriggerType): PFunc;
var
i:Integer;
p:Integer;
begin
Result:=Nil;
for i:=0 to list.Count-1 do begin
p := Pos(list.Strings[i], s);
if (t = ttSubStr) and (p > 0) then break;
if (t = ttPrefix) and (p = 1) then break;
end;
if (i < list.Count) then begin
Result := GetFunc(list.Strings[i]);
end;
end;
procedure TTriggerList.RemoveFunc(s: String);
var
i:Integer;
stack:TStack;
begin
i := list.IndexOf(s);
if (i<>-1) then begin
stack := TStack(list.Objects[i]);
if (stack<>Nil) then begin
if stack.Count>0 then
stack.Pop;
end;
end;
end;
procedure TTriggerList.RemoveTrigger(s: String);
var
i:Integer;
begin
i := list.IndexOf(s);
if (i<>-1) then begin
list.Objects[i].free;
list.Delete(i);
end;
end;
end.
--- Unit1 --
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
TriggerCB, StdCtrls, shellapi;
type
TForm1 = class(TForm)
TriggerCB1: TTriggerCB;
Button1: TButton;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
function MyFunc(s:String):Integer;
begin
ShowMessage(s);
result:=0;
end;
function MyFunc2(s:String):Integer;
begin
ShowMessage('2');
result:=0;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
TriggerCB1.TriggerType := ttSubStr;
TriggerCB1.TriggerList.AddTrigger('wow', @MyFunc);
TriggerCB1.TriggerList.AddFunc('wow', @MyFunc2);
TriggerCB1.buffer := 'it is wownderful';
TriggerCB1.TriggerList.RemoveFunc('wow');
TriggerCB1.buffer := 'it is wownderful';
TriggerCB1.TriggerList.RemoveFunc('wow');
TriggerCB1.buffer := 'it is wownderful';
end;
end.
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货