在delphi 7 自带的控件中有一个ExtCtrls.pas单元!
该单元中有两个控件,分别为TBoundLabel和TCustomLabeledEdit,
我们来分析第二个控件:TCustomLabeledEdit
两个控件在ExtCtrls.pas中定义如下:  { TBoundLabel }
  TBoundLabel = class(TCustomLabel)
  private
    function GetTop: Integer;
    function GetLeft: Integer;
    function GetWidth: Integer;
    function GetHeight: Integer;
    procedure SetHeight(const Value: Integer);
    procedure SetWidth(const Value: Integer);
  protected
    procedure AdjustBounds; override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property BiDiMode;
    property Caption;
    property Color;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Font;
    property Height: Integer read GetHeight write SetHeight;
    property Left: Integer read GetLeft;
    property ParentBiDiMode;
    property ParentColor;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ShowAccelChar;
    property ShowHint;
    property Top: Integer read GetTop;
    property Transparent;
    property Layout;
    property WordWrap;
    property Width: Integer read GetWidth write SetWidth;
    property OnClick;
    property OnContextPopup;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDock;
    property OnEndDrag;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDock;
    property OnStartDrag;
  end;  TLabelPosition = (lpAbove, lpBelow, lpLeft, lpRight);  { TCustomLabeledEdit }  TCustomLabeledEdit = class(TCustomEdit)
  private
    FEditLabel: TBoundLabel;                         //注意此处为私有成员;
    FLabelPosition: TLabelPosition;
    FLabelSpacing: Integer;
    procedure SetLabelPosition(const Value: TLabelPosition);
    procedure SetLabelSpacing(const Value: Integer);
  protected
    procedure SetParent(AParent: TWinControl); override;
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    procedure SetName(const Value: TComponentName); override;
    procedure CMVisiblechanged(var Message: TMessage);
      message CM_VISIBLECHANGED;
    procedure CMEnabledchanged(var Message: TMessage);
      message CM_ENABLEDCHANGED;
    procedure CMBidimodechanged(var Message: TMessage);
      message CM_BIDIMODECHANGED;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer; AHeight: Integer); override;
    procedure SetupInternalLabel;
    property EditLabel: TBoundLabel read FEditLabel;
    property LabelPosition: TLabelPosition read FLabelPosition write SetLabelPosition;
    property LabelSpacing: Integer read FLabelSpacing write SetLabelSpacing;
  end;其它的代码我们暂且不看!
我们来看看public中SetupInternalLabel的源码为:procedure TCustomLabeledEdit.SetupInternalLabel;
begin
  if Assigned(FEditLabel) then exit;
  FEditLabel := TBoundLabel.Create(Self);
  FEditLabel.FreeNotification(Self);
  FEditLabel.FocusControl := Self;    //大家注意这句话;我感觉有问题!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
end;
FocusControl属性在TBoundLabel中并未进行定义
而是在其父类中进行定义的
并且在其父类中为保护区域!TBoundLabel其父类为TCustomLabel,在StdCtrls.pas单元!
定义如下:  TTextLayout = (tlTop, tlCenter, tlBottom);  TCustomLabel = class(TGraphicControl)
  private
    FFocusControl: TWinControl;
    FAlignment: TAlignment;
    FAutoSize: Boolean;
    FLayout: TTextLayout;
    FWordWrap: Boolean;
    FShowAccelChar: Boolean;
    FOnMouseLeave: TNotifyEvent;
    FOnMouseEnter: TNotifyEvent;
    FTransparentSet: Boolean;    
    function GetTransparent: Boolean;
    procedure SetAlignment(Value: TAlignment);
    procedure SetFocusControl(Value: TWinControl);
    procedure SetShowAccelChar(Value: Boolean);
    procedure SetTransparent(Value: Boolean);
    procedure SetLayout(Value: TTextLayout);
    procedure SetWordWrap(Value: Boolean);
    procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
    procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
    procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  protected
    procedure AdjustBounds; dynamic;
    procedure DoDrawText(var Rect: TRect; Flags: Longint); dynamic;
    function GetLabelText: string; virtual;
    procedure Loaded; override;
    procedure Notification(AComponent: TComponent;
      Operation: TOperation); override;
    procedure Paint; override;
    procedure SetAutoSize(Value: Boolean); override;
    property Alignment: TAlignment read FAlignment write SetAlignment
      default taLeftJustify;
    property AutoSize: Boolean read FAutoSize write SetAutoSize default True;
    property ShowAccelChar: Boolean read FShowAccelChar write SetShowAccelChar default True;
    property Transparent: Boolean read GetTransparent write SetTransparent stored FTransparentSet;
    property FocusControl: TWinControl read FFocusControl write SetFocusControl;    //FocusControl中是定义在protected区域中;
    property Layout: TTextLayout read FLayout write SetLayout default tlTop;
    property WordWrap: Boolean read FWordWrap write SetWordWrap default False;
  public
    constructor Create(AOwner: TComponent); override;
    property Caption;
    property Canvas;
    property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
    property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
  end;============================================================================================================================
现在的问题是:在TCustomLabeledEdit类中,
为什么能访问到FEditLabel.FocusControl属性?
TCustomLabeledEdit类在ExtCtrls.pas单元中定义;
TCustomLabel类在StdCtrls.pas单元中定义;
它们不能够成友元类!在不是友元类的情况下,为什么TCustomLabeledEdit类中却可以访问其成员FEditLabel
(该成员国为TBoundLabel类的实例,TBoundLabel类从TCustomLabel类派生)
下的FocusControl属性(该属性在TCustomLabel类中定义在保护区域)????

解决方案 »

  1.   

    可能是我没说清楚!
    这儿不存在子类与父类的关系!TCustomLabeledEdit = class(TCustomEdit)  //TCustomLabeledEdit 类是从 TCustomEdit派生的!FEditLabel: TBoundLabel;   //FEditLabel只是TCustomLabeledEdit 类中定义的一个成员,FocusControl属性在TBoundLabel类中是属于保护区域的!而在
    procedure TCustomLabeledEdit.SetupInternalLabel;
    begin
      if Assigned(FEditLabel) then exit;
      FEditLabel := TBoundLabel.Create(Self);
      FEditLabel.FreeNotification(Self);
      FEditLabel.FocusControl := Self; //注意:在TCustomLabeledEdit类中可以访问其成员的保护属性!而不是其父类的保护属性!
    end;
    现在确出现了在TCustomLabeledEdit中可以访问其成员的保护属性的情况?
      

  2.   

    玩控件或面向对象的高手们是怎么理解这个问题的?
    现在我自己定了一个控件,和TCustomLabeledEdit完全一样,
    只是从TDBEditEh类派生!
    其它代码都一模一样!
    就在FEditLabel.FocusControl := Self;这句话上出了问题,说没有定义FocusControl属性!
    然后我在StdCtrls.pas单元中,将 property FocusControl: TWinControl read FFocusControl write SetFocusControl;这行代码放到public中,也出现一样的问题!
    我想是因为没有将StdCtrls.pas单元重新编译的原故!我在改了DELPHI自带的控件单元后,怎么重新编译呢?听同事说把原来的StdCtrls.dcu文件删除,然后重新编译就行,但我试了也不行!怎么办?
      

  3.   

    这儿不存在子类与父类的关系!TCustomLabeledEdit = class(TCustomEdit)  //TCustomLabeledEdit 类是从 TCustomEdit派生的!FEditLabel: TBoundLabel;   //FEditLabel只是TCustomLabeledEdit 类中定义的一个成员,FocusControl属性在TBoundLabel类中是属于保护区域的!而在
    procedure TCustomLabeledEdit.SetupInternalLabel;
    begin
      if Assigned(FEditLabel) then exit;
      FEditLabel := TBoundLabel.Create(Self);
      FEditLabel.FreeNotification(Self);
      FEditLabel.FocusControl := Self; //注意:在TCustomLabeledEdit类中可以访问其成员的保护属性!而不是其父类的保护属性!
    end;
    现在确出现了在TCustomLabeledEdit中可以访问其成员的保护属性的情况?
      

  4.   

    TBoundLabel和TCustomLabeledEdit在同一个单元中声明,
    他们是友元类,
    不仅可以访问对方的保护成员,
    还可以访问私有成员。
      

  5.   

    TBoundLabel和TCustomLabeledEdit是在同一个单元中声明,
    但TBoundLabel的父类TCustomLabel确是在另一个单元,而FocusControl是属于TCustomLabel下的一个属性!
    这样TCustomLabeledEdit类也能和TCustomLabel类构成友元吗?
    好像不对吧!
    如果真是友元类的话,如果这也成了友元的话,友元的概念不就成了:不但可以访问本单元内其它类的属性,还可以访问本单元内其它类的父类的成员,
    这样一来,整个DELPHI中的类全都成了友元类了!====================================================================================
    现在的问题是:在TCustomLabeledEdit类中,
    为什么能访问到FEditLabel.FocusControl属性?
    TCustomLabeledEdit类在ExtCtrls.pas单元中定义;
    TCustomLabel类在StdCtrls.pas单元中定义;
    它们不能够成友元类!在不是友元类的情况下,为什么TCustomLabeledEdit类中却可以访问其成员FEditLabel
    (该成员国为TBoundLabel类的实例,TBoundLabel类从TCustomLabel类派生)
    下的FocusControl属性(该属性在TCustomLabel类中定义在保护区域)????