在做一种类似一些软件的“选项”对话框所采用的形式,目的是不管是用TreeView,还是用Tab,都可作出软件的“选项”对话框,现在正在实现一个TreeNodes和Frame结合的形式。
可能说不清楚。可以看一个图:
具体的问题,请先把这些声明看下去,自然就知道问题是什么了
Type
  TBaseFrameClass = Class Of TBaseFrame; //对TBaseFrame的类引用
  {* 关于TBaseFrame,在这里可以就当它是一个TFrame。}
  TBaseFrameEvent = Procedure(Sender: TObject; Frame: TBaseFrame) Of Object;
  TBasePreference = Class(TObject) //抽象基类
  Protected
    Procedure DoApply; Virtual; Abstract; //具体“应用”或者“确定”交给子类
    Procedure DoReset; Virtual; Abstract; //具体“恢复默认值”交给子类
    Procedure DoResetAll; Virtual; Abstract; //具体“全部恢复默认值”交给子类
  Public
    Procedure Apply; //响应“应用”或者“确定”命令
    Procedure Reset; //响应“恢复默认值”命令
    Procedure ResetAll; //响应“全部恢复默认值”命令
  End;
  TTreePreference = Class(TBasePreference) //使用TreeNodes来管理的子类
  Protected
    FItems: TTreeNodes;
    FCurrItem: TTreeNode;
    FRelatedTreeView: TCustomTreeView;
    Procedure SetRelatedTreeView(TreeView: TCustomTreeView); Virtual; Abstract;
  Public
    Property RelatedTreeView: TCustomTreeView Read FRelatedTreeView Write
      SetRelatedTreeView;
  End;
  TFrameTreePreference = Class(TTreePreference) //Frame和TreeNodes的结合
  Private
    FFrameOwner: Boolean;
    FCurrFrame: TBaseFrame;
    FNullFrame: TBaseFrame;
    FOnApply: TBaseFrameEvent;
    FOnReset: TBaseFrameEvent;
    Procedure SetRelatedTreeView(TreeView: TCustomTreeView); Override;
    Procedure DoApply; Override;
    Procedure DoReset; Override;
    Procedure DoResetAll; Override;
    // 实际上,有点像在包装TTreeNodes
    Procedure GetNodeFromIndex(Index: Integer);
  Public
    Constructor Create(NullFrame: TBaseFrame; FrameOwner: Boolean;
      TreeNodesOwner: TCustomTreeView);
    Destructor Destroy; Override;
    // 实际上,有点像在包装TTreeNodes
    Function AddChildObjectFirst(Parent: TTreeNode; Const S: String; FrameType:
      TBaseFrameClass): TTreeNode;
    Function AddChildObject(Parent: TTreeNode; Const S: String; FrameType:
      TBaseFrameClass): TTreeNode;
    Function AddObjectFirst(Sibling: TTreeNode; Const S: String; FrameType:
      TBaseFrameClass): TTreeNode;
    Function AddObject(Sibling: TTreeNode; Const S: String; FrameType:
      TBaseFrameClass): TTreeNode;
    Function AddNode(Node, Relative: TTreeNode; Const S: String; FrameType:
      TBaseFrameClass; Method: TNodeAttachMode): TTreeNode;
    Function AlphaSort(ARecurse: Boolean = False): Boolean;
    Procedure Assign(Source: TPersistent); Override;
    Procedure BeginUpdate;
    Procedure Clear;
    Function CustomSort(SortProc: TTVCompare; Data: Longint; ARecurse: Boolean =
      False): Boolean;
    Procedure Delete(Node: TTreeNode);
    Procedure EndUpdate;
    Function GetFirstNode: TTreeNode;
    Function GetNode(ItemId: HTreeItem): TTreeNode;
    Function InsertObject(Sibling: TTreeNode; Const S: String; FrameType:
      TBaseFrameClass): TTreeNode;
    Function InsertNode(Node, Sibling: TTreeNode; Const S: String; FrameType:
      TBaseFrameClass): TTreeNode;
    Property Count: Integer Read GetCount;
    Property Item[Index: Integer]: TTreeNode Read GetNodeFromIndex;
    {* 我的困惑就在Item属性的类型:TTreeNode上}
    {因为现在这样注定是可以通过Item来随便篡改Data的指向的指针,就
     是说,BaseFrame和TreeNode的关系就会乱掉!
     现在我的解决办法是把这个属性定义修改成:
     Property Item[Index: Integer]: TPreferenceNode,
     当然,上面很多的TTreeNode都要改为TPreferenceNode,然后再定义
     一个TPreferenceNode,也是在包装TTreeNode,只不过把Data属性给
     修改了,变成Data是TBaseFrame类型的对象。这样就不会乱。
     不过这样又要借助一个TObjectList,主要是用它的FindInstanceOf,
     来查找TBaseFrame。这样会很复杂。有什么比这个更好的方法呢?
    }
  End;
[
 Last edited by SuperYoyoNC on 2006-2-10 at 17:18 ]