📄 methprop.pas
字号:
unit MethProp;
(*
The Components Events Information module of the DFM2PAS utility by Alexei Hmelnov.
----------------------------------------------------------------------------
E-Mail: alex@monster.icc.ru
http://monster.icc.ru/~alex/
----------------------------------------------------------------------------
See the file "readme.txt" for more details.
------------------------------------------------------------------------
IMPORTANT NOTE:
This software is provided 'as-is', without any expressed or implied warranty.
In no event will the author be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented, you must not
claim that you wrote the original software.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*)
interface
uses
SysUtils,Classes;
type
TComponentInfo = class
Parent: TComponentInfo;
UnitName: String;
Methods: TStringList;
constructor Create;
destructor Destroy; override;
function GetPropertyMethod(PropName,MethodName: String): String;
private
function IsNew: boolean;
end ;
procedure LoadComponentDescrs;
procedure FreeComponentDescrs;
function GetComponentInfo(ClassName: String): TComponentInfo;
implementation
type
PMethodInfo = ^TMethodInfo;
TMethodInfo = record
Descr: String;
{This information could be extended, so I decided to use record here
instead of direct string to pointer conversion like
Methods.Objects[i] := Pointer(Descr)}
end ;
const
CompTbl: TStringList = Nil;
EvtTbl: TStringList = Nil;
NotifyEvt: String = 'procedure(Sender: TObject);{?}';
FormInfo: TComponentInfo = Nil;
procedure LoadComponentDescrs;
function GetComponentInfo(Name: String): TComponentInfo;
var
i: integer;
begin
if CompTbl.Find(Name,i) then
Result := TComponentInfo(CompTbl.Objects[i])
else begin
Result := TComponentInfo.Create;
CompTbl.AddObject(Name,Result);
end ;
end ;
function GetEvtInfo(Name: String): PMethodInfo;
var
i: integer;
begin
if EvtTbl.Find(Name,i) then
Result := PMethodInfo(EvtTbl.Objects[i])
else begin
New(Result);
Pointer(Result.Descr) := Nil;
EvtTbl.AddObject(Name,Pointer(Result));
end ;
end ;
var
l: integer;
S: String;
procedure ScanError(Msg: String);
begin
raise Exception.CreateFmt('%s at %d:'#13#10'%s',[Msg,l,S]);
end ;
var
F: Text;
FBuf: array[0..$FFF] of Byte;
UnitS: String;
PropS,EvtS: String;
OnTypes: boolean;
CI,Parent: TComponentInfo;
CP: PChar;
MI: PMethodInfo;
i: integer;
begin
if CompTbl=nil then CompTbl := TStringList.Create;
// CompTbl := TStringList.Create;
// CompTbl.Create;
CompTbl.Sorted := true;
CompTbl.Duplicates := dupError;
if EvtTbl=nil then EvtTbl := TStringList.Create;
// EvtTbl := TStringList.Create;;
// EvtTbl.Create;
EvtTbl.Sorted := true;
EvtTbl.Duplicates := dupError;
AssignFile(F,ExtractFilePath(ParamStr(0))+'classes.lst');
SetTextBuf(F,FBuf);
{$I-}
Reset(F);
{$I+}
if IOResult<>0 then
Exit;
try
UnitS := '?';
OnTypes := false;
CI := Nil;
l := 0;
while not EOF(F) do begin
Readln(F,S);
Inc(l);
S := Trim(S);
if S='' then begin
if not OnTypes then
CI := Nil;
Continue;
end ;
if OnTypes then begin
CP := StrScan(PChar(S),'=');
if CP=Nil then
ScanError('"=" expected');
EvtS := TrimRight(Copy(S,1,CP-PChar(S)));
MI := GetEvtInfo(EvtS);
if MI^.Descr<>'' then
ScanError('Event redefined');
MI.Descr := TrimLeft(Copy(S,CP-PChar(S)+2,1000));
end
else begin
if CompareText(S,'type')=0 then begin
OnTypes := true;
Continue;
end ;
if S[Length(S)]=':' then begin
SetLength(S,Length(S)-1);
UnitS := TrimRight(S);
Continue;
end ;
if CI=Nil then begin
CP := StrScan(PChar(S),'(');
if CP=Nil then
Parent := Nil
else begin
if S[Length(S)]<>')' then
ScanError('")" expected');
Parent := GetComponentInfo(Trim(Copy(S,CP-PChar(S)+2,Length(S)-(CP-PChar(S))-2)));
SetLength(S,CP-PChar(S));
S := TrimRight(S);
end ;
CI := GetComponentInfo(S);
if not CI.IsNew then
ScanError('Component redefined');
CI.UnitName := UnitS;
CI.Parent := Parent;
Continue;
end ;
CP := StrScan(PChar(S),':');
if CP=Nil then
ScanError('":" expected');
PropS := TrimRight(Copy(S,1,CP-PChar(S)));
EvtS := TrimLeft(Copy(S,CP-PChar(S)+2,255));
MI := GetEvtInfo(EvtS);
CI.Methods.AddObject(PropS,Pointer(MI));
end ;
end ;
if CompTbl.Find('TForm',i) then
FormInfo := TComponentInfo(CompTbl.Objects[i])
finally
Close(F);
end ;
end ;
procedure FreeComponentDescrs;
var
i: integer;
MI: PMethodInfo;
CI: TComponentInfo;
begin
if EvtTbl<>Nil then begin
for i:=0 to EvtTbl.Count-1 do begin
MI := PMethodInfo(EvtTbl.Objects[i]);
if MI=Nil then
Continue;
Dispose(MI);
end ;
EvtTbl.Free;
// EvtTbl := Nil;
end ;
if CompTbl<>Nil then begin
for i:=0 to CompTbl.Count-1 do begin
CI := TComponentInfo(CompTbl.Objects[i]);
if CI=Nil then
Continue;
CI.Free;
end ;
CompTbl.Free;
CompTbl := Nil;
end ;
end ;
{ TComponentInfo. }
constructor TComponentInfo.Create;
begin
inherited Create;
Methods := TStringList.Create;
Methods.Sorted := true;
Methods.Duplicates := dupError;
end ;
destructor TComponentInfo.Destroy;
begin
Methods.Free;
inherited Destroy;
end ;
function TComponentInfo.GetPropertyMethod(PropName,MethodName: String): String;
{The DFM files contain only <PropName>=<MethodName> information about
event handlers. This procedure searches for the PropName method of the
Component and if found uses its Description to generate the result named
MethodName, else it returns the method header of the TNotifyEvent
type if the PropName starts with 'On'}
var
i: integer;
MI: PMethodInfo;
CP: PChar;
begin
Result := '';
if Methods.Find(PropName,i) then begin
MI := PMethodInfo(Methods.Objects[i]);
Result := MI^.Descr;
end ;
if Result='' then begin
if StrLIComp(PChar(PropName),'On',2)<>0 then
Exit
{This heuristics is used to skip component references,
e.g. TDataSource.DataSet};
Result := NotifyEvt;
end ;
CP := StrScan(PChar(Result),'(');
if CP=Nil then
CP := StrScan(PChar(Result),';');
if CP=Nil then
CP := PChar(Result)+Length(Result);
Insert(' '+MethodName,Result,CP-PChar(Result)+1);
end ;
function TComponentInfo.IsNew: boolean;
{This function is used on the LoadComponentDescrs stage to detect
redefinition of components}
begin
Result := UnitName='';
end ;
function GetComponentInfo(ClassName: String): TComponentInfo;
var
i: integer;
begin
if CompTbl.Find(ClassName,i) then
Result := TComponentInfo(CompTbl.Objects[i])
else
Result := FormInfo {Unknown class is processed using the TForm information};
end ;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -