📄 classes.pas
字号:
raise EClassNotFound.Create(Format(SClassNotFound, [ClassName]));
end;
function GetClass(const AClassName: string): TPersistentClass;
var
I: Integer;
begin
with ClassList.LockList do
try // ClassAliasList protected by ClassList lock
for I := 0 to Count - 1 do
begin
Result := Items[I];
if Result.ClassNameIs(AClassName) then Exit;
end;
I := ClassAliasList.IndexOf(AClassName);
if I >= 0 then
begin
Result := TPersistentClass(ClassAliasList.Objects[I]);
Exit;
end;
Result := nil;
finally
ClassList.UnlockList;
end;
end;
function FindClass(const ClassName: string): TPersistentClass;
begin
Result := GetClass(ClassName);
if Result = nil then ClassNotFound(ClassName);
end;
function FindFieldClass(Instance: TObject;
const ClassName: string): TPersistentClass;
var
I: Integer;
ClassTable: PFieldClassTable;
ClassType: TClass;
begin
ClassType := Instance.ClassType;
while ClassType <> TPersistent do
begin
ClassTable := GetFieldClassTable(ClassType);
if ClassTable <> nil then
for I := 0 to ClassTable^.Count - 1 do
begin
Result := ClassTable^.Classes[I]^;
if CompareText(Result.ClassName, ClassName) = 0 then Exit;
end;
ClassType := ClassType.ClassParent;
end;
Result := FindClass(ClassName);
end;
procedure RegisterClass(AClass: TPersistentClass);
var
AClassName: string;
begin
with ClassList.LockList do
try
while IndexOf(AClass) = -1 do
begin
AClassName := AClass.ClassName;
if GetClass(AClassName) <> nil then
raise EFilerError.CreateFmt(SDuplicateClass, [AClassName]);
Add(AClass);
if AClass = TPersistent then Break;
AClass := TPersistentClass(AClass.ClassParent);
end;
finally
ClassList.UnlockList;
end;
end;
procedure RegisterClasses(AClasses: array of TPersistentClass);
var
I: Integer;
begin
for I := Low(AClasses) to High(AClasses) do RegisterClass(AClasses[I]);
end;
procedure RegisterClassAlias(AClass: TPersistentClass; const Alias: string);
begin
ClassList.LockList; // ClassAliasList protected by ClassList lock
try
RegisterClass(AClass);
ClassAliasList.AddObject(Alias, TObject(AClass));
finally
ClassList.UnlockList;
end;
end;
procedure UnRegisterClass(AClass: TPersistentClass);
begin
ClassList.Remove(AClass);
end;
procedure UnRegisterClasses(AClasses: array of TPersistentClass);
var
I: Integer;
begin
for I := Low(AClasses) to High(AClasses) do UnRegisterClass(AClasses[I]);
end;
procedure UnRegisterModuleClasses(Module: HMODULE);
var
I: Integer;
M: TMemoryBasicInformation;
begin
with ClassList.LockList do
try
for I := Count - 1 downto 0 do
begin
VirtualQuery(Items[I], M, SizeOf(M));
if (Module = 0) or (HMODULE(M.AllocationBase) = Module) then
Delete(I);
end;
// ClassAliasList protected by ClassList lock
for I := ClassAliasList.Count - 1 downto 0 do
begin
VirtualQuery(Pointer(ClassAliasList.Objects[I]), M, SizeOf(M));
if (Module = 0) or (HMODULE(M.AllocationBase) = Module) then
ClassAliasList.Delete(I);
end;
finally
ClassList.UnlockList;
end;
end;
{ Component registration routines }
procedure RegisterComponents(const Page: string;
ComponentClasses: array of TComponentClass);
begin
if Assigned(RegisterComponentsProc) then
RegisterComponentsProc(Page, ComponentClasses)
else
raise EComponentError.Create(SRegisterError);
end;
procedure RegisterNoIcon(ComponentClasses: array of TComponentClass);
begin
if Assigned(RegisterNoIconProc) then
RegisterNoIconProc(ComponentClasses)
else
raise EComponentError.Create(SRegisterError);
end;
procedure RegisterNonActiveX(ComponentClasses: array of TComponentClass;
AxRegType: TActiveXRegType);
begin
if not Assigned(RegisterNonActiveXProc) then
raise EComponentError.Create(SRegisterError);
RegisterNonActiveXProc(ComponentClasses, AxRegType)
end;
{ Component filing }
type
TIntConst = class
IntegerType: PTypeInfo;
IdentToInt: TIdentToInt;
IntToIdent: TIntToIdent;
constructor Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
AIntToIdent: TIntToIdent);
end;
constructor TIntConst.Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
AIntToIdent: TIntToIdent);
begin
IntegerType := AIntegerType;
IdentToInt := AIdentToInt;
IntToIdent := AIntToIdent;
end;
procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToInt: TIdentToInt;
IntToIdent: TIntToIdent);
begin
IntConstList.Add(TIntConst.Create(IntegerType, IdentToInt, IntToIdent));
end;
function IdentToInt(const Ident: string; var Int: Longint; const Map: array of TIdentMapEntry): Boolean;
var
I: Integer;
begin
for I := Low(Map) to High(Map) do
if CompareText(Map[I].Name, Ident) = 0 then
begin
Result := True;
Int := Map[I].Value;
Exit;
end;
Result := False;
end;
function IntToIdent(Int: Longint; var Ident: string; const Map: array of TIdentMapEntry): Boolean;
var
I: Integer;
begin
for I := Low(Map) to High(Map) do
if Map[I].Value = Int then
begin
Result := True;
Ident := Map[I].Name;
Exit;
end;
Result := False;
end;
function InternalReadComponentRes(const ResName: string; HInst: THandle; var Instance: TComponent): Boolean;
var
HRsrc: THandle;
begin { avoid possible EResNotFound exception }
if HInst = 0 then HInst := HInstance;
HRsrc := FindResource(HInst, PChar(ResName), RT_RCDATA);
Result := HRsrc <> 0;
if not Result then Exit;
with TResourceStream.Create(HInst, ResName, RT_RCDATA) do
try
Instance := ReadComponent(Instance);
finally
Free;
end;
Result := True;
end;
threadvar
GlobalLoaded: TList;
GlobalLists: TList;
procedure BeginGlobalLoading;
begin
if GlobalLists = nil then GlobalLists := TList.Create;
GlobalLists.Add(GlobalLoaded);
GlobalLoaded := TList.Create;
end;
procedure NotifyGlobalLoading;
var
I: Integer;
begin
for I := 0 to GlobalLoaded.Count - 1 do
TComponent(GlobalLoaded[I]).Loaded;
end;
procedure EndGlobalLoading;
begin
GlobalLoaded.Free;
GlobalLoaded := GlobalLists.Last;
GlobalLists.Delete(GlobalLists.Count - 1);
if GlobalLists.Count = 0 then
begin
GlobalLists.Free;
GlobalLists := nil;
end;
end;
function InitInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean;
function InitComponent(ClassType: TClass): Boolean;
begin
Result := False;
if (ClassType = TComponent) or (ClassType = RootAncestor) then Exit;
Result := InitComponent(ClassType.ClassParent);
Result := InternalReadComponentRes(ClassType.ClassName, FindResourceHInstance(
FindClassHInstance(ClassType)), Instance) or Result;
end;
begin
GlobalNameSpace.BeginWrite; // hold lock across all ancestor loads (performance)
try
BeginGlobalLoading;
try
Result := InitComponent(Instance.ClassType);
NotifyGlobalLoading;
finally
EndGlobalLoading;
end;
finally
GlobalNameSpace.EndWrite;
end;
end;
function InitComponentRes(const ResName: string; Instance: TComponent): Boolean;
begin
Result := InternalReadComponentRes(ResName, FindResourceHInstance(
FindClassHInstance(Instance.ClassType)), Instance);
end;
function ReadComponentRes(const ResName: string; Instance: TComponent): TComponent;
var
HInstance: THandle;
begin
if Instance <> nil then
HInstance := FindResourceHInstance(FindClassHInstance(Instance.ClassType))
else HInstance := 0;
if InternalReadComponentRes(ResName, HInstance, Instance) then
Result := Instance else
raise EResNotFound.CreateFmt(SResNotFound, [ResName]);
end;
function ReadComponentResEx(HInstance: THandle; const ResName: string): TComponent;
var
Instance: TComponent;
begin
Instance := nil;
if InternalReadComponentRes(ResName, HInstance, Instance) then
Result := Instance else
raise EResNotFound.CreateFmt(SResNotFound, [ResName]);
end;
function ReadComponentResFile(const FileName: string; Instance: TComponent): TComponent;
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
Result := Stream.ReadComponentRes(Instance);
finally
Stream.Free;
end;
end;
procedure WriteComponentResFile(const FileName: string; Instance: TComponent);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmCreate);
try
Stream.WriteComponentRes(Instance.ClassName, Instance);
finally
Stream.Free;
end;
end;
function CollectionsEqual(C1, C2: TCollection): Boolean;
var
S1, S2: TMemoryStream;
procedure WriteCollection(Stream: TStream; Collection: TCollection);
var
Writer: TWriter;
begin
Writer := TWriter.Create(Stream, 1024);
try
Writer.WriteCollection(Collection);
finally
Writer.Free;
end;
end;
begin
Result := False;
if C1.ClassType <> C2.ClassType then Exit;
if C1.Count <> C2.Count then Exit;
S1 := TMemoryStream.Create;
try
WriteCollection(S1, C1);
S2 := TMemoryStream.Create;
try
WriteCollection(S2, C2);
Result := (S1.Size = S2.Size) and CompareMem(S1.Memory, S2.Memory, S1.Size);
finally
S2.Free;
end;
finally
S1.Free;
end;
end;
{ Utility routines }
function LineStart(Buffer, BufPos: PChar): PChar; assembler;
asm
PUSH EDI
MOV EDI,EDX
MOV ECX,EDX
SUB ECX,EAX
SUB ECX,1
JBE @@1
MOV EDX,EAX
DEC EDI
MOV AL,0AH
STD
REPNE SCASB
CLD
MOV EAX,EDX
JNE @@1
LEA EAX,[EDI+2]
@@1: POP EDI
end;
function ExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: PChar;
Strings: TStrings): Integer;
var
Head, Tail: PChar;
EOS, InQuote: Boolean;
QuoteChar: Char;
Item: string;
begin
Result := 0;
if (Content = nil) or (Content^=#0) or (Strings = nil) then Exit;
Tail := Content;
InQuote := False;
QuoteChar := #0;
Strings.BeginUpdate;
try
repeat
while Tail^ in WhiteSpace + [#13, #10] do Inc(Tail);
Head := Tail;
while True do
begin
while (InQuote and not (Tail^ in ['''', '"', #0])) or
not (Tail^ in Separators + [#0, #13, #10, '''', '"']) do Inc(Tail);
if Tail^ in ['''', '"'] then
begin
if (QuoteChar <> #0) and (QuoteChar = Tail^) then
QuoteChar := #0
else QuoteChar := Tail^;
InQuote := QuoteChar <> #0;
Inc(Tail);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -