现在的位置: 首页 > 综合 > 正文

VCL类学习之(七) TComponent

2017年12月01日 ⁄ 综合 ⁄ 共 22643字 ⁄ 字号 评论关闭
TComponent is the common ancestor of all component classes.
Unit
Classes
Description
TComponent is the base class for all components. TComponent implements the following features:
Components are persistent objects that have the following capabilities:
IDE integration. The ability to appear on an IDE palette and be manipulated in a form designer.
 Ownership. The ability to manage other components. If component A owns component B, then A is responsible for destroying B when A is destroyed.
 Streaming and filing. Enhancements of the persistence features inherited from TPersistent.
 COM support. Components can be converted into ActiveX controls or other COM objects using wizards provided with Windows products. Components can serve as wrappers for COM objects.
COM features are present in all implementations of TComponent, including those provided with Linux development tools. However, these features are only useful in Windows applications, and are marked in this documentation as "Windows only". Do not use these features in cross-platform applications.
TComponent does not provide any user interface or display features. These features are provided by two classes that directly descend from TComponent.
TControl, in the QControls unit, is the base class for "visual" components in cross-platform applications.
TControl, in the Controls unit, is the base class for "visual" components in Windows-only applications.
The Controls unit and other Windows-specific units are not provided with Linux development tools.
Components that can be visible at runtime are sometimes called "visual components". Other components, which are never visible at runtime, are sometimes called "non-visual components". However it is more common to refer to "visual components" as "controls" and "non-visual components" simply as "components."
Do not create instances of TComponent. Use TComponent as a base class when declaring non-visual components that can appear on the component palette and be used in the form designer. Properties and methods of TComponent provide basic behavior that descendant classes inherit as well as behavior that components can override to customize their behavior.
  1. TComponent = class(TPersistent, IInterface, IInterfaceComponentReference)
  2.   private
  3.     FOwner: TComponent;            //所属
  4.     FName: TComponentName; 
  5.     FTag: Longint;
  6.     FComponents: TList;
  7.     FFreeNotifies: TList;
  8.     FDesignInfo: Longint;
  9.     FComponentState: TComponentState;
  10.     FVCLComObject: Pointer;
  11.     function GetComObject: IUnknown;
  12.     function GetComponent(AIndex: Integer): TComponent;
  13.     function GetComponentCount: Integer;
  14.     function GetComponentIndex: Integer;
  15.     procedure Insert(AComponent: TComponent);
  16.     procedure ReadLeft(Reader: TReader);
  17.     procedure ReadTop(Reader: TReader);
  18.     procedure Remove(AComponent: TComponent);
  19.     procedure RemoveNotification(AComponent: TComponent);
  20.     procedure SetComponentIndex(Value: Integer);
  21.     procedure SetReference(Enable: Boolean);
  22.     procedure WriteLeft(Writer: TWriter);
  23.     procedure WriteTop(Writer: TWriter);
  24.     { IInterfaceComponentReference }
  25.     function IInterfaceComponentReference.GetComponent = IntfGetComponent;
  26.     function IntfGetComponent: TComponent;
  27.   protected
  28.     FComponentStyle: TComponentStyle;
  29.     procedure ChangeName(const NewName: TComponentName);
  30.     procedure DefineProperties(Filer: TFiler); override;
  31.     procedure GetChildren(Proc: TGetChildProc; Root: TComponent); dynamic;
  32.     function GetChildOwner: TComponent; dynamic;
  33.     function GetChildParent: TComponent; dynamic;
  34.     function GetOwner: TPersistent; override;
  35.     procedure Loaded; virtual;
  36.     procedure Notification(AComponent: TComponent;
  37.       Operation: TOperation); virtual;                  //发送消息
  38.     procedure PaletteCreated; dynamic;
  39.     procedure ReadState(Reader: TReader); virtual;
  40.     procedure SetAncestor(Value: Boolean);
  41.     procedure SetDesigning(Value: Boolean; SetChildren: Boolean = True);
  42.     procedure SetInline(Value: Boolean);
  43.     procedure SetDesignInstance(Value: Boolean);
  44.     procedure SetName(const NewName: TComponentName); virtual;
  45.     procedure SetChildOrder(Child: TComponent; Order: Integer); dynamic;
  46.     procedure SetParentComponent(Value: TComponent); dynamic;
  47.     procedure Updating; dynamic;
  48.     procedure Updated; dynamic;
  49.     class procedure UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); virtual;
  50.     procedure ValidateRename(AComponent: TComponent;
  51.       const CurName, NewName: string); virtual;    //确定是否有重名组件存在
  52.     procedure ValidateContainer(AComponent: TComponent); dynamic;
  53.     procedure ValidateInsert(AComponent: TComponent); dynamic;
  54.     procedure WriteState(Writer: TWriter); virtual;
  55.     { IInterface }
  56.     function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
  57.     function _AddRef: Integer; stdcall;
  58.     function _Release: Integer; stdcall;
  59.     { IDispatch }
  60.     function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
  61.     function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
  62.     function GetIDsOfNames(const IID: TGUID; Names: Pointer;
  63.       NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
  64.     function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  65.       Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
  66.   public
  67.     constructor Create(AOwner: TComponent); virtual;
  68.     destructor Destroy; override;
  69.     procedure BeforeDestruction; override;
  70.     procedure DestroyComponents;
  71.     procedure Destroying;
  72.     function ExecuteAction(Action: TBasicAction): Boolean; dynamic;
  73.     function FindComponent(const AName: string): TComponent;
  74.     procedure FreeNotification(AComponent: TComponent);
  75.     procedure RemoveFreeNotification(AComponent: TComponent);
  76.     procedure FreeOnRelease;
  77.     function GetParentComponent: TComponent; dynamic;
  78.     function GetNamePath: string; override;
  79.     function HasParent: Boolean; dynamic;
  80.     procedure InsertComponent(AComponent: TComponent);
  81.     procedure RemoveComponent(AComponent: TComponent);
  82.     procedure SetSubComponent(IsSubComponent: Boolean);
  83.     function SafeCallException(ExceptObject: TObject;
  84.       ExceptAddr: Pointer): HResult; override;
  85.     function UpdateAction(Action: TBasicAction): Boolean; dynamic;
  86.     function IsImplementorOf(const I: IInterface): Boolean;
  87.     function ReferenceInterface(const I: IInterface; Operation: TOperation): Boolean;
  88.     property ComObject: IUnknown read GetComObject;
  89.     property Components[Index: Integer]: TComponent read GetComponent;
  90.     property ComponentCount: Integer read GetComponentCount;
  91.     property ComponentIndex: Integer read GetComponentIndex write SetComponentIndex;
  92.     property ComponentState: TComponentState read FComponentState;
  93.     property ComponentStyle: TComponentStyle read FComponentStyle;
  94.     property DesignInfo: Longint read FDesignInfo write FDesignInfo;
  95.     property Owner: TComponent read FOwner;
  96.     property VCLComObject: Pointer read FVCLComObject write FVCLComObject;
  97.   published
  98.     property Name: TComponentName read FName write SetName stored False;
  99.     property Tag: Longint read FTag write FTag default 0;
  100.   end;
  101. { TComponent }
  102. constructor TComponent.Create(AOwner: TComponent);
  103. begin
  104.   FComponentStyle := [csInheritable];
  105.   if AOwner <> nil then AOwner.InsertComponent(Self);    //新增
  106. end;
  107. destructor TComponent.Destroy;
  108. begin
  109.   Destroying;
  110.   if FFreeNotifies <> nil then
  111.   begin
  112.     while Assigned(FFreeNotifies) and (FFreeNotifies.Count > 0do
  113.       TComponent(FFreeNotifies[FFreeNotifies.Count - 1]).Notification(Self, opRemove);
  114.     FreeAndNil(FFreeNotifies);
  115.   end;
  116.   DestroyComponents;
  117.   if FOwner <> nil then FOwner.RemoveComponent(Self);
  118.   inherited Destroy;
  119. end;
  120. procedure TComponent.BeforeDestruction;
  121. begin
  122.   if not (csDestroying in ComponentState) then
  123.     Destroying;
  124. end;
  125. procedure TComponent.FreeNotification(AComponent: TComponent);
  126. begin
  127.   if (Owner = nilor (AComponent.Owner <> Owner) then
  128.   begin
  129.     // Never acquire a reference to a component that is being deleted.
  130.     assert(not (csDestroying in (ComponentState + AComponent.ComponentState)));
  131.     if not Assigned(FFreeNotifies) then FFreeNotifies := TList.Create;
  132.     if FFreeNotifies.IndexOf(AComponent) < 0 then
  133.     begin
  134.       FFreeNotifies.Add(AComponent);
  135.       AComponent.FreeNotification(Self);
  136.     end;
  137.   end;
  138.   Include(FComponentState, csFreeNotification);
  139. end;
  140. procedure TComponent.ReadLeft(Reader: TReader);
  141. begin
  142.   LongRec(FDesignInfo).Lo := Reader.ReadInteger;
  143. end;
  144. procedure TComponent.ReadTop(Reader: TReader);
  145. begin
  146.   LongRec(FDesignInfo).Hi := Reader.ReadInteger;
  147. end;
  148. procedure TComponent.WriteLeft(Writer: TWriter);
  149. begin
  150.   Writer.WriteInteger(LongRec(FDesignInfo).Lo);
  151. end;
  152. procedure TComponent.WriteTop(Writer: TWriter);
  153. begin
  154.   Writer.WriteInteger(LongRec(FDesignInfo).Hi);
  155. end;
  156. procedure TComponent.Insert(AComponent: TComponent);
  157. begin
  158.   if FComponents = nil then FComponents := TList.Create;
  159.   FComponents.Add(AComponent);
  160.   AComponent.FOwner := Self;
  161. end;
  162. procedure TComponent.Remove(AComponent: TComponent);
  163. begin
  164.   AComponent.FOwner := nil;
  165.   FComponents.Remove(AComponent);
  166.   if FComponents.Count = 0 then
  167.   begin
  168.     FComponents.Free;
  169.     FComponents := nil;
  170.   end;
  171. end;
  172. procedure TComponent.InsertComponent(AComponent: TComponent);
  173. begin
  174.   AComponent.ValidateContainer(Self);
  175.   ValidateRename(AComponent, '', AComponent.FName);
  176.   Insert(AComponent);
  177.   AComponent.SetReference(True);
  178.   if csDesigning in ComponentState then
  179.     AComponent.SetDesigning(True);
  180.   Notification(AComponent, opInsert);  //发送消息
  181. end;
  182. procedure TComponent.RemoveComponent(AComponent: TComponent);
  183. begin
  184.   ValidateRename(AComponent, AComponent.FName, '');
  185.   Notification(AComponent, opRemove);
  186.   AComponent.SetReference(False);
  187.   Remove(AComponent);
  188. end;
  189. procedure TComponent.DestroyComponents;
  190. var
  191.   Instance: TComponent;
  192. begin
  193.   while FComponents <> nil do
  194.   begin
  195.     Instance := FComponents.Last;
  196.     if (csFreeNotification in Instance.FComponentState)
  197.       or (FComponentState * [csDesigning, csInline] = [csDesigning, csInline]) then
  198.       RemoveComponent(Instance)
  199.     else
  200.       Remove(Instance);
  201.     Instance.Destroy;
  202.   end;
  203. end;
  204. procedure TComponent.Destroying;
  205. var
  206.   I: Integer;
  207. begin
  208.   if not (csDestroying in FComponentState) then
  209.   begin
  210.     Include(FComponentState, csDestroying);
  211.     if FComponents <> nil then
  212.       for I := 0 to FComponents.Count - 1 do
  213.         TComponent(FComponents[I]).Destroying;
  214.   end;
  215. end;
  216. procedure TComponent.RemoveNotification(AComponent: TComponent);
  217. begin
  218.   if FFreeNotifies <> nil then
  219.   begin
  220.     FFreeNotifies.Remove(AComponent);
  221.     if FFreeNotifies.Count = 0 then
  222.     begin
  223.       FFreeNotifies.Free;
  224.       FFreeNotifies := nil;
  225.     end;
  226.   end;
  227. end;
  228. procedure TComponent.RemoveFreeNotification(AComponent: TComponent);
  229. begin
  230.   RemoveNotification(AComponent);
  231.   AComponent.RemoveNotification(Self);
  232. end;
  233. procedure TComponent.Notification(AComponent: TComponent;
  234.   Operation: TOperation);
  235. var
  236.   I: Integer;
  237. begin
  238.   if (Operation = opRemove) and (AComponent <> nilthen
  239.     RemoveFreeNotification(AComponent);
  240.   if FComponents <> nil then
  241.   begin
  242.     I := FComponents.Count - 1;
  243.     while I >= 0 do
  244.     begin
  245.       TComponent(FComponents[I]).Notification(AComponent, Operation);
  246.       Dec(I);
  247.       if I >= FComponents.Count then
  248.         I := FComponents.Count - 1;
  249.     end;
  250.   end;
  251. end;
  252. procedure TComponent.DefineProperties(Filer: TFiler);
  253. var
  254.   Ancestor: TComponent;
  255.   Info: Longint;
  256. begin
  257.   Info := 0;
  258.   Ancestor := TComponent(Filer.Ancestor);
  259.   if Ancestor <> nil then Info := Ancestor.FDesignInfo;
  260.   Filer.DefineProperty('Left', ReadLeft, WriteLeft,
  261.     LongRec(FDesignInfo).Lo <> LongRec(Info).Lo);
  262.   Filer.DefineProperty('Top', ReadTop, WriteTop,
  263.     LongRec(FDesignInfo).Hi <> LongRec(Info).Hi);
  264. end;
  265. function TComponent.HasParent: Boolean;
  266. begin
  267.   Result := False;
  268. end;
  269. procedure TComponent.GetChildren(Proc: TGetChildProc; Root: TComponent);
  270. begin
  271. end;
  272. function TComponent.GetChildOwner: TComponent;
  273. begin
  274.   Result := nil;
  275. end;
  276. function TComponent.GetChildParent: TComponent;
  277. begin
  278.   Result := Self;
  279. end;
  280. function TComponent.GetNamePath: string;
  281. begin
  282.   Result := FName;
  283. end;
  284. function TComponent.GetOwner: TPersistent;
  285. begin
  286.   Result := FOwner;
  287. end;
  288. procedure TComponent.SetChildOrder(Child: TComponent; Order: Integer);
  289. begin
  290. end;
  291. function TComponent.GetParentComponent: TComponent;
  292. begin
  293.   Result := nil;
  294. end;
  295. procedure TComponent.SetParentComponent(Value: TComponent);
  296. begin
  297. end;
  298. procedure TComponent.Updating;
  299. begin
  300.   Include(FComponentState, csUpdating);
  301. end;
  302. procedure TComponent.Updated;
  303. begin
  304.   Exclude(FComponentState, csUpdating);
  305. end;
  306. procedure TComponent.Loaded;
  307. begin
  308.   Exclude(FComponentState, csLoading);
  309. end;
  310. procedure TComponent.PaletteCreated;
  311. begin
  312.   // Notification
  313. end;
  314. procedure TComponent.ReadState(Reader: TReader);
  315. begin
  316.   Reader.ReadData(Self);
  317. end;
  318. procedure TComponent.WriteState(Writer: TWriter);
  319. begin
  320.   Writer.WriteData(Self);
  321. end;
  322. procedure TComponent.ValidateRename(AComponent: TComponent;
  323.   const CurName, NewName: string);
  324. begin
  325.   if (AComponent <> niland not SameText(CurName, NewName) and
  326.     (AComponent.Owner = Self) and (FindComponent(NewName) <> nilthen
  327.     raise EComponentError.CreateResFmt(@SDuplicateName, [NewName]);
  328.   if (csDesigning in ComponentState) and (Owner <> nilthen
  329.     Owner.ValidateRename(AComponent, CurName, NewName);
  330. end;
  331. procedure TComponent.ValidateContainer(AComponent: TComponent);
  332. begin
  333.   AComponent.ValidateInsert(Self);
  334. end;
  335. procedure TComponent.ValidateInsert(AComponent: TComponent);
  336. begin
  337. end;
  338. function TComponent.FindComponent(const AName: string): TComponent;
  339. var
  340.   I: Integer;
  341. begin
  342.   if (AName <> ''and (FComponents <> nilthen
  343.     for I := 0 to FComponents.Count - 1 do
  344.     begin
  345.       Result := FComponents[I];
  346.       if SameText(Result.FName, AName) then Exit;
  347.     end;
  348.   Result := nil;
  349. end;
  350. procedure TComponent.SetName(const NewName: TComponentName);
  351. begin
  352.   if FName <> NewName then
  353.   begin
  354.     if (NewName <> ''and not IsValidIdent(NewName) then
  355.       raise EComponentError.CreateResFmt(@SInvalidName, [NewName]);
  356.     if FOwner <> nil then
  357.       FOwner.ValidateRename(Self, FName, NewName) else
  358.       ValidateRename(nil, FName, NewName);
  359.     SetReference(False);
  360.     ChangeName(NewName);
  361.     SetReference(True);
  362.   end;
  363. end;
  364. procedure TComponent.ChangeName(const NewName: TComponentName);
  365. begin
  366.   FName := NewName;
  367. end;
  368. function TComponent.GetComponentIndex: Integer;
  369. begin
  370.   if (FOwner <> niland (FOwner.FComponents <> nilthen
  371.     Result := FOwner.FComponents.IndexOf(Self) else
  372.     Result := -1;
  373. end;
  374. function TComponent.GetComponent(AIndex: Integer): TComponent;
  375. begin
  376.   if FComponents = nil then TList.Error(@SListIndexError, AIndex);
  377.   Result := FComponents[AIndex];
  378. end;
  379. function TComponent.GetComponentCount: Integer;
  380. begin
  381.   if FComponents <> nil then
  382.     Result := FComponents.Count else
  383.     Result := 0;
  384. end;
  385. procedure TComponent.SetComponentIndex(Value: Integer);
  386. var
  387.   I, Count: Integer;
  388. begin
  389.   if FOwner <> nil then
  390.   begin
  391.     I := FOwner.FComponents.IndexOf(Self);
  392.     if I >= 0 then
  393.     begin
  394.       Count := FOwner.FComponents.Count;
  395.       if Value < 0 then Value := 0;
  396.       if Value >= Count then Value := Count - 1;
  397.       if Value <> I then
  398.       begin
  399.         FOwner.FComponents.Delete(I);
  400.         FOwner.FComponents.Insert(Value, Self);
  401.       end;
  402.     end;
  403.   end;
  404. end;
  405. procedure TComponent.SetAncestor(Value: Boolean);
  406. var
  407.   I: Integer;
  408. begin
  409.   if Value then
  410.     Include(FComponentState, csAncestor) else
  411.     Exclude(FComponentState, csAncestor);
  412.   for I := 0 to ComponentCount - 1 do
  413.     Components[I].SetAncestor(Value);
  414. end;
  415. procedure TComponent.SetDesigning(Value, SetChildren: Boolean);
  416. var
  417.   I: Integer;
  418. begin
  419.   if Value then
  420.     Include(FComponentState, csDesigning) else
  421.     Exclude(FComponentState, csDesigning);
  422.   if SetChildren then
  423.     for I := 0 to ComponentCount - 1 do Components[I].SetDesigning(Value);
  424. end;
  425. procedure TComponent.SetInline(Value: Boolean);
  426. begin
  427.   if Value then
  428.     Include(FComponentState, csInline) else
  429.     Exclude(FComponentState, csInline);
  430. end;
  431. procedure TComponent.SetDesignInstance(Value: Boolean);
  432. begin
  433.   if Value then
  434.     Include(FComponentState, csDesignInstance) else
  435.     Exclude(FComponentState, csDesignInstance);
  436. end;
  437. procedure TComponent.SetReference(Enable: Boolean);
  438. var
  439.   Field: ^TComponent;
  440. begin
  441.   if FOwner <> nil then
  442.   begin
  443.     Field := FOwner.FieldAddress(FName);
  444.     if Field <> nil then
  445.       if Enable then Field^ := Self else Field^ := nil;
  446.   end;
  447. end;
  448. function TComponent.ExecuteAction(Action: TBasicAction): Boolean;
  449. begin
  450.   Result := Action.HandlesTarget(Self);
  451.   if Result then
  452.     Action.ExecuteTarget(Self);
  453. end;
  454. function TComponent.UpdateAction(Action: TBasicAction): Boolean;
  455. begin
  456.   Result := Action.HandlesTarget(Self);
  457.   if Result then
  458.     Action.UpdateTarget(Self);
  459. end;
  460. procedure TComponent.SetSubComponent(IsSubComponent: Boolean);
  461. begin
  462.   if IsSubComponent then
  463.     Include(FComponentStyle, csSubComponent)
  464.   else
  465.     Exclude(FComponentStyle, csSubComponent);
  466. end;
  467. function TComponent.GetComObject: IUnknown;
  468. begin
  469.   if FVCLComObject = nil then
  470.   begin
  471.     if Assigned(CreateVCLComObjectProc) then CreateVCLComObjectProc(Self);
  472.     if FVCLComObject = nil then
  473.       raise EComponentError.CreateResFmt(@SNoComSupport, [ClassName]);
  474.   end;
  475.   IVCLComObject(FVCLComObject).QueryInterface(IUnknown, Result);
  476. end;
  477. function TComponent.SafeCallException(ExceptObject: TObject;
  478.   ExceptAddr: Pointer): HResult;
  479. begin
  480.   if FVCLComObject <> nil then
  481.     Result := IVCLComObject(FVCLComObject).SafeCallException(
  482.       ExceptObject, ExceptAddr)
  483. {$IFDEF LINUX}
  484.   {$IFDEF _WIN32};{$ENDIF}
  485.   if ExceptObject is Exception then
  486.   begin
  487.     SetSafeCallExceptionMsg(Exception(ExceptObject).Message);
  488.     SetSafeCallExceptionAddr(ExceptAddr);
  489.     Result := HResult($8000FFFF);
  490.   end
  491. {$ENDIF}
  492.   else
  493.     Result := inherited SafeCallException(ExceptObject, ExceptAddr);
  494. end;
  495. procedure TComponent.FreeOnRelease;
  496. begin
  497.   if FVCLComObject <> nil then IVCLComObject(FVCLComObject).FreeOnRelease;
  498. end;
  499. class procedure TComponent.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string);
  500. begin
  501. end;
  502. { TComponent.IInterface }
  503. function TComponent.QueryInterface(const IID: TGUID; out Obj): HResult;
  504. begin
  505.   if FVCLComObject = nil then
  506.   begin
  507.     if GetInterface(IID, Obj) then Result := S_OK
  508.     else Result := E_NOINTERFACE
  509.   end
  510.   else
  511.     Result := IVCLComObject(FVCLComObject).QueryInterface(IID, Obj);
  512. end;
  513. function TComponent._AddRef: Integer;
  514. begin
  515.   if FVCLComObject = nil then
  516.     Result := -1   // -1 indicates no reference counting is taking place
  517.   else
  518.     Result := IVCLComObject(FVCLComObject)._AddRef;
  519. end;
  520. function TComponent._Release: Integer;
  521. begin
  522.   if FVCLComObject = nil then
  523.     Result := -1   // -1 indicates no reference counting is taking place
  524.   else
  525.     Result := IVCLComObject(FVCLComObject)._Release;
  526. end;
  527. { TComponent.IDispatch }
  528. function TComponent.GetTypeInfoCount(out Count: Integer): HResult;
  529. begin
  530.   if FVCLComObject = nil then
  531.     Result := E_NOTIMPL
  532.   else
  533.     Result := IVCLComObject(FVCLComObject).GetTypeInfoCount(Count);
  534. end;
  535. function TComponent.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult;
  536. begin
  537.   if FVCLComObject = nil then
  538.     Result := E_NOTIMPL
  539.   else
  540.     Result := IVCLComObject(FVCLComObject).GetTypeInfo(
  541.       Index, LocaleID, TypeInfo);
  542. end;
  543. function TComponent.GetIDsOfNames(const IID: TGUID; Names: Pointer;
  544.   NameCount, LocaleID: Integer; DispIDs: Pointer): HResult;
  545. begin
  546.   if FVCLComObject = nil then
  547.     Result := E_NOTIMPL
  548.   else
  549.     Result := IVCLComObject(FVCLComObject).GetIDsOfNames(IID, Names,
  550.       NameCount, LocaleID, DispIDs);
  551. end;
  552. function TComponent.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  553.   Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult;
  554. begin
  555.   if FVCLComObject = nil then
  556.     Result := E_NOTIMPL
  557.   else
  558.     Result := IVCLComObject(FVCLComObject).Invoke(DispID, IID, LocaleID,
  559.       Flags, Params, VarResult, ExcepInfo, ArgErr);
  560. end;
  561. { TComponent.IInterfaceComponentReference.GetComponent
  562.   Return a reference to the component that can be queried at load time to
  563.   obtain an interface.  The name of the reference component will be written to
  564.   the stream (same as a normal component reference) so that it can be located
  565.   again at load time.
  566.   In the case of aggregation, the reference component for an interface might
  567.   not be the same as the class that implements the interface itself.
  568.   Aggregate implementation classes should not implement
  569.   IInterfaceComponentReference, but should defer requests for that interface
  570.   to the controlling component.
  571. }
  572. function TComponent.IntfGetComponent: TComponent;
  573. begin
  574.   Result := Self;
  575. end;
  576. function TComponent.IsImplementorOf(const I: IInterface): Boolean;
  577. var
  578.   ICR: IInterfaceComponentReference;
  579. begin
  580.   Result := (I <> niland Supports(I, IInterfaceComponentReference, ICR)
  581.     and (ICR.GetComponent = Self);
  582. end;
  583. { TComponent.ReferenceInterface
  584.   Establishes (opInsert) or removes (opRemove) internal links that
  585.   notify us when the component that implements the given interface is
  586.   destroyed.  The function result indicates whether the function was able
  587.   to establish/remove a notification link or not.  A result of False
  588.   doesn't necessarily indicate an error, but it does mean that the
  589.   interface's implementor does not participate in the interfaced component
  590.   reference model.  This could mean that the given interface employs true
  591.   reference counting, independent of component lifetimes.  That doesn't
  592.   affect the use of interface properties at runtime, but non-component
  593.   interfaces cannot be stored by the property streaming system.
  594.   When implementing components with interface-type properties, implement
  595.   setter methods for the interface-type properties like this:
  596.   procedure TMyComponent.SetMyIntfProp(const Value: IMyInterface);
  597.   begin
  598.     ReferenceInterface(FIntfField, opRemove);
  599.     FIntfField := Value;
  600.     ReferenceInterface(FIntfField, opInsert);
  601.   end;
  602.   Also override Notification to do the following for each interface property
  603.   in your component:
  604.   procedure TMyComponent.Notification(AComponent: TComponent; Operation: TOperation);
  605.   begin
  606.     inherited;
  607.     if Assigned(MyIntfProp) and AComponent.IsImplementorOf(MyIntfProp) then
  608.       MyIntfProp := nil;
  609.     ... repeat for other interface properties ...
  610.   end;
  611.   Note that the Notification code assigns nil to the *property*, not to the
  612.   private field, so that the property setter will call
  613.   ReferenceInterface(FIntfField, opRemove to undo any links established by
  614.   a previous opInsert operation.  All assignments to the interface property
  615.   *must* be made through the property setter.
  616.   TComponent.ReferenceInterface hides the details of how links are
  617.   established between the implementor and the holder of an interface.
  618.   The implementation details may change in the future.  Code that relies
  619.   on those implementation details (instead of using ReferenceInterface)
  620.   will not be supported.  In particular, avoid the temptation to use
  621.   IInterfaceComponentReference in your own code, as this interface may
  622.   not be available in the future.
  623. }
  624. function TComponent.ReferenceInterface(const I: IInterface; Operation: TOperation): Boolean;
  625. var
  626.   ICR: IInterfaceComponentReference;
  627. begin
  628.   Result := (I <> niland Supports(I, IInterfaceComponentReference, ICR);
  629.   if Result then
  630.     if Operation = opInsert then
  631.       ICR.GetComponent.FreeNotification(Self)
  632.     else
  633.       ICR.GetComponent.RemoveFreeNotification(Self);
  634. end;

抱歉!评论已关闭.