这是我在2000年写的程序,直到现在我还认为是比较精品的
以下全部代码实现了一个树类
TMyList是在delphi的TList基础上改造的,加入了批量删除
TNode是节点类
TNodes是对节点类的封装,实现了一棵树的增、删、改、查等操作
以下是TMyList的源代码unit List;
//改造自delphi的TList,增加了批量删除
interfaceuses
Classes, RTLConsts;type
TMyList = class(TObject)
private
FList: PPointerList;
FCount: Integer;
FCapacity: Integer;
protected
function Get(Index: Integer): Pointer;
procedure Grow;
procedure Put(Index: Integer; Item: Pointer);
procedure SetCapacity(NewCapacity: Integer);
public
destructor Destroy; override;
function Add(Item: Pointer): Integer;
procedure Clear;
procedure Delete(Index: Integer; ItemCount: Integer = 1);
class procedure Error(const Msg: string; Data: Integer); overload;
class procedure Error(Msg: PResStringRec; Data: Integer); overload;
procedure Exchange(Index1, Index2: Integer);
function First: Pointer;
function IndexOf(Item: Pointer): Integer;
procedure Insert(Index: Integer; Item: Pointer);
function Last: Pointer;
property Capacity: Integer read FCapacity write SetCapacity;
property Count: Integer read FCount;
property Items[Index: Integer]: Pointer read Get write Put; default;
end;implementationuses
Consts;{ TMyList }destructor TMyList.Destroy;
begin
Clear;
end;function TMyList.Add(Item: Pointer): Integer;
begin
Result := FCount;
if Result = FCapacity then
Grow;
FList^[Result] := Item;
Inc(FCount);
end;procedure TMyList.Clear;
begin
FCount := 0;
SetCapacity(0);
end;class procedure TMyList.Error(const Msg: string; Data: Integer); function ReturnAddr: Pointer;
asm
MOV EAX,[EBP+4]
end;begin
raise EListError.CreateFmt(Msg, [Data]) at ReturnAddr;
end;class procedure TMyList.Error(Msg: PResStringRec; Data: Integer);
begin
TMyList.Error(LoadResString(Msg), Data);
end;procedure TMyList.Exchange(Index1, Index2: Integer);
var
Item: Pointer;
begin
if (Index1 < 0) or (Index1 >= FCount) then
Error(@SListIndexError, Index1);
if (Index2 < 0) or (Index2 >= FCount) then
Error(@SListIndexError, Index2);
Item := FList^[Index1];
FList^[Index1] := FList^[Index2];
FList^[Index2] := Item;
end;function TMyList.First: Pointer;
begin
Result := Get(0);
end;function TMyList.Get(Index: Integer): Pointer;
begin
if (Index < 0) or (Index >= FCount) then
Error(@SListIndexError, Index);
Result := FList^[Index];
end;procedure TMyList.Grow;
var
Delta: Integer;
begin
if FCapacity > 64 then
Delta := FCapacity div 4
else
if FCapacity > 8 then
Delta := 16
else
Delta := 4;
SetCapacity(FCapacity + Delta);
end;function TMyList.IndexOf(Item: Pointer): Integer;
begin
Result := 0;
while (Result < FCount) and (FList^[Result] <> Item) do
Inc(Result);
if Result = FCount then
Result := -1;
end;procedure TMyList.Insert(Index: Integer; Item: Pointer);
begin
if (Index < 0) or (Index > FCount) then
Error(@SListIndexError, Index);
if FCount = FCapacity then
Grow;
if Index < FCount then
System.Move(FList^[Index], FList^[Index + 1],
(FCount - Index) * SizeOf(Pointer));
FList^[Index] := Item;
Inc(FCount);
end;function TMyList.Last: Pointer;
begin
Result := Get(FCount - 1);
end;procedure TMyList.Put(Index: Integer; Item: Pointer);
begin
if (Index < 0) or (Index >= FCount) then
Error(@SListIndexError, Index);
FList^[Index] := Item;
end;procedure TMyList.SetCapacity(NewCapacity: Integer);
begin
if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
Error(@SListCapacityError, NewCapacity);
if NewCapacity <> FCapacity then
begin
ReallocMem(FList, NewCapacity * SizeOf(Pointer));
FCapacity := NewCapacity;
end;
end;procedure TMyList.Delete(Index: Integer; ItemCount: Integer = 1);
begin
if (Index < 0) or (Index >= FCount) then
Error(@SListIndexError, Index);
if ItemCount > FCount - Index then
ItemCount := FCount - Index;
if Index < FCount then
Move(FList[Index + ItemCount], FList[Index],
(FCount - (Index + ItemCount)) * SizeOf(Pointer));
Dec(FCount, ItemCount);
end;end.
以下全部代码实现了一个树类
TMyList是在delphi的TList基础上改造的,加入了批量删除
TNode是节点类
TNodes是对节点类的封装,实现了一棵树的增、删、改、查等操作
以下是TMyList的源代码unit List;
//改造自delphi的TList,增加了批量删除
interfaceuses
Classes, RTLConsts;type
TMyList = class(TObject)
private
FList: PPointerList;
FCount: Integer;
FCapacity: Integer;
protected
function Get(Index: Integer): Pointer;
procedure Grow;
procedure Put(Index: Integer; Item: Pointer);
procedure SetCapacity(NewCapacity: Integer);
public
destructor Destroy; override;
function Add(Item: Pointer): Integer;
procedure Clear;
procedure Delete(Index: Integer; ItemCount: Integer = 1);
class procedure Error(const Msg: string; Data: Integer); overload;
class procedure Error(Msg: PResStringRec; Data: Integer); overload;
procedure Exchange(Index1, Index2: Integer);
function First: Pointer;
function IndexOf(Item: Pointer): Integer;
procedure Insert(Index: Integer; Item: Pointer);
function Last: Pointer;
property Capacity: Integer read FCapacity write SetCapacity;
property Count: Integer read FCount;
property Items[Index: Integer]: Pointer read Get write Put; default;
end;implementationuses
Consts;{ TMyList }destructor TMyList.Destroy;
begin
Clear;
end;function TMyList.Add(Item: Pointer): Integer;
begin
Result := FCount;
if Result = FCapacity then
Grow;
FList^[Result] := Item;
Inc(FCount);
end;procedure TMyList.Clear;
begin
FCount := 0;
SetCapacity(0);
end;class procedure TMyList.Error(const Msg: string; Data: Integer); function ReturnAddr: Pointer;
asm
MOV EAX,[EBP+4]
end;begin
raise EListError.CreateFmt(Msg, [Data]) at ReturnAddr;
end;class procedure TMyList.Error(Msg: PResStringRec; Data: Integer);
begin
TMyList.Error(LoadResString(Msg), Data);
end;procedure TMyList.Exchange(Index1, Index2: Integer);
var
Item: Pointer;
begin
if (Index1 < 0) or (Index1 >= FCount) then
Error(@SListIndexError, Index1);
if (Index2 < 0) or (Index2 >= FCount) then
Error(@SListIndexError, Index2);
Item := FList^[Index1];
FList^[Index1] := FList^[Index2];
FList^[Index2] := Item;
end;function TMyList.First: Pointer;
begin
Result := Get(0);
end;function TMyList.Get(Index: Integer): Pointer;
begin
if (Index < 0) or (Index >= FCount) then
Error(@SListIndexError, Index);
Result := FList^[Index];
end;procedure TMyList.Grow;
var
Delta: Integer;
begin
if FCapacity > 64 then
Delta := FCapacity div 4
else
if FCapacity > 8 then
Delta := 16
else
Delta := 4;
SetCapacity(FCapacity + Delta);
end;function TMyList.IndexOf(Item: Pointer): Integer;
begin
Result := 0;
while (Result < FCount) and (FList^[Result] <> Item) do
Inc(Result);
if Result = FCount then
Result := -1;
end;procedure TMyList.Insert(Index: Integer; Item: Pointer);
begin
if (Index < 0) or (Index > FCount) then
Error(@SListIndexError, Index);
if FCount = FCapacity then
Grow;
if Index < FCount then
System.Move(FList^[Index], FList^[Index + 1],
(FCount - Index) * SizeOf(Pointer));
FList^[Index] := Item;
Inc(FCount);
end;function TMyList.Last: Pointer;
begin
Result := Get(FCount - 1);
end;procedure TMyList.Put(Index: Integer; Item: Pointer);
begin
if (Index < 0) or (Index >= FCount) then
Error(@SListIndexError, Index);
FList^[Index] := Item;
end;procedure TMyList.SetCapacity(NewCapacity: Integer);
begin
if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
Error(@SListCapacityError, NewCapacity);
if NewCapacity <> FCapacity then
begin
ReallocMem(FList, NewCapacity * SizeOf(Pointer));
FCapacity := NewCapacity;
end;
end;procedure TMyList.Delete(Index: Integer; ItemCount: Integer = 1);
begin
if (Index < 0) or (Index >= FCount) then
Error(@SListIndexError, Index);
if ItemCount > FCount - Index then
ItemCount := FCount - Index;
if Index < FCount then
Move(FList[Index + ItemCount], FList[Index],
(FCount - (Index + ItemCount)) * SizeOf(Pointer));
Dec(FCount, ItemCount);
end;end.
解决方案 »
- Delphi2009使用VCSKIN的朋友进来下
- 关于使用sql2000数据库,运行速度的问题
- to : 小和
- 模拟鼠标怎么在后台运行?
- 关于checkbox控件的数据库应用问题
- 关于用ACCESS做后台数据库,出现DATABASE LOGIN对话框问题?
- 如何在FORM中用代码创建一个按钮?
- 谁有辞职申请书的例子 借来看一看 从来没写过
- 如果用D7开发基于Corba结构的分布式系统,连接数据库时用什么控件啊
- 使用Delphi读取Excel单元格批注时如何判断是否存在批注?
- 三层数据更新出现问题:update affected more than 1 record ?????
- 如何动态在ado中添加计算列?
List, SysUtils;type
TNodes = class;
TNode = class;
TAddMode = (amAddChildFirst, amAddChild); TNode = class(TObject)
private
FOwner: TNodes;
FData: Pointer;
FParent: TNode;
FFirstChild: TNode;
FNextSibling: TNode;
FPrevSibling: TNode;
FExpanded: Boolean;
function GetHasChildren: Boolean;
function GetLevel: Integer;
function GetParent: TNode;
function GetLastSibling: TNode;
function GetFirstSibling: TNode;
function GetLastChild: TNode;
function GetIsVisible: Boolean;
function GetCount: Integer;
public
constructor Create(AOwner: TNodes);
destructor Destroy; override;
procedure Collapse(Recurse: Boolean);
procedure Expand(Recurse: Boolean);
procedure Delete;
procedure DeleteChildren;
// procedure MoveTo(Destination: TNode; Mode: TMoveMode);
procedure LevelDown;
procedure LevelUp;
procedure MoveDown;
procedure MoveUp;
property FirstChild: TNode read FFirstChild;
property NextSibling: TNode read FNextSibling;
property PrevSibling: TNode read FPrevSibling;
property Data: Pointer read FData write FData;
property Expanded: Boolean read FExpanded write FExpanded;
property HasChildren: Boolean read GetHasChildren;
property Level: Integer read GetLevel;
property Owner: TNodes read FOwner;
property Parent: TNode read GetParent;
property LastSibling: TNode read GetLastSibling;
property FirstSibling: TNode read GetFirstSibling;
property LastChild: TNode read GetLastChild;
property IsVisible: Boolean read GetIsVisible;
property Count: Integer read GetCount;
end; TNodes = class(TObject)
private
FUpdateCount: Integer;
FRoot: TNode;
FCount: Integer;
FNodeList: TMyList;
FCapacity: Integer;
FTag: Integer;
procedure BuildNodeList;
function InternalAdd(Node: TNode; Ptr: Pointer; AddMode: TAddMode): TNode;
function GetItems(Index: Integer): TNode;
// procedure Move(Source, Destination: TNode; Mode: TMoveMode);
public
constructor Create;
destructor Destroy; override;
function AddChildFirst(Node: TNode; Ptr: Pointer): TNode;
function AddChild(Node: TNode; Ptr: Pointer): TNode;
function AddFirst(Node: TNode; Ptr: Pointer): TNode;
function Add(Node: TNode; Ptr: Pointer): TNode;
function InsertObject(Node: TNode; Ptr: Pointer): TNode;
function IndexOf(Node: TNode): Integer;
procedure BeginUpdate;
procedure EndUpdate;
procedure Clear;
procedure AdjustDelete(Node: TNode);
procedure Delete(Node: TNode); overload;
procedure Delete(Index: Integer); overload;
procedure DeleteChildren(Node: TNode); overload;
procedure DeleteChildren(Index: Integer); overload;
procedure LevelDown(Node: TNode);
procedure LevelUp(Node: TNode);
procedure MoveDown(Node: TNode);
procedure MoveUp(Node: TNode);
procedure FullExpand;
procedure FullCollapse;
property Root: TNode read FRoot;
property Count: Integer read FCount;
property Capacity: Integer read FCapacity write FCapacity;
property Tag: Integer read FTag write FTag;
property Items[Index: Integer]: TNode read GetItems; default;
end;//function IsAncestor(Ancestor, Child: TNode): Boolean;implementation{function IsAncestor(Ancestor, Child: TNode): Boolean;
begin
Result := False;
if Child = nil then
raise Exception.Create('参数Child不能为空');
if Ancestor = nil then
begin
Result := True;
exit;
end;
Child := Child.Parent;
while Child <> nil do
begin
if Child = Ancestor then
begin
Result := True;
exit;
end;
Child := Child.Parent;
end;
end;}{ TNode }constructor TNode.Create(AOwner: TNodes);
begin
inherited Create;
FOwner := AOwner;
Inc(FOwner.FCount);
FExpanded := False;
end;destructor TNode.Destroy;
begin
Dec(FOwner.FCount);
inherited;
end;procedure TNode.Collapse(Recurse: Boolean);
var
Node: TNode;
begin
FExpanded := False;
if Recurse then
begin
Node := FFirstChild;
while Node <> nil do
begin
Node.Collapse(Recurse);
Node := Node.FNextSibling;
end;
end;
end;procedure TNode.Expand(Recurse: Boolean);
var
Node: TNode;
begin
FExpanded := True;
if Recurse then
begin
Node := FFirstChild;
while Node <> nil do
begin
Node.Expand(Recurse);
Node := Node.FNextSibling;
end;
end;
end;procedure TNode.Delete;
begin
FOwner.Delete(Self);
end;procedure TNode.DeleteChildren;
begin
FOwner.DeleteChildren(Self);
end;function TNode.GetHasChildren: Boolean;
begin
Result := FFirstChild <> nil;
end;function TNode.GetLevel: Integer;
var
Node: TNode;
begin
Result := 0;
Node := FParent;
while Node <> nil do
begin
Inc(Result);
Node := Node.FParent;
end;
end;function TNode.GetParent: TNode;
begin
Result := FParent;
end;function TNode.GetLastSibling: TNode;
begin
Result := Self;
while Result.FNextSibling <> nil do
Result := Result.FNextSibling;
end;function TNode.GetFirstSibling: TNode;
begin
Result := Self;
while Result.FPrevSibling <> nil do
Result := Result.FPrevSibling;
end;function TNode.GetLastChild: TNode;
begin
Result := FFirstChild;
if Result = nil then exit;
while Result.FNextSibling <> nil do
Result := Result.FNextSibling;
end;{procedure TNode.MoveTo(Destination: TNode; Mode: TMoveMode);
begin
if Destination = Self then exit;
if (Destination <> nil) and IsAncestor(Self, Destination) then exit;
// not realilzed
FOwner.Move(Self, Destination, Mode);
end;}procedure TNode.LevelDown;
begin
FOwner.LevelDown(Self);
end;procedure TNode.LevelUp;
begin
FOwner.LevelUp(Self);
end;procedure TNode.MoveDown;
begin
FOwner.MoveDown(Self);
end;procedure TNode.MoveUp;
begin
FOwner.MoveUp(Self);
end;function TNode.GetIsVisible: Boolean;
begin
Result := (FParent = nil) or FParent.IsVisible and FParent.FExpanded;
end;function TNode.GetCount: Integer;
var
Node: TNode;
begin
Result := 0;
Node := FFirstChild;
while Node <> nil do
begin
Inc(Result, Node.Count + 1);
Node := Node.FNextSibling;
end;
end;{ TNodes }constructor TNodes.Create;
begin
FUpdateCount := 0;
FCount := 0;
FCapacity := 0;
FRoot := nil;
FTag := 0;
FNodeList := TMyList.Create;
end;destructor TNodes.Destroy;
begin
Clear;
FNodeList.Free;
inherited;
end;function TNodes.AddChild(Node: TNode; Ptr: Pointer): TNode;
begin
Result := InternalAdd(Node, Ptr, amAddChild);
end;function TNodes.AddChildFirst(Node: TNode; Ptr: Pointer): TNode;
begin
Result := InternalAdd(Node, Ptr, amAddChildFirst);
end;procedure TNodes.BeginUpdate;
begin
Inc(FUpdateCount);
end;procedure TNodes.Clear;
var
Node, L_NextSibling: TNode;
begin
if FRoot = nil then exit;
BeginUpdate;
Node := FRoot;
while Node <> nil do
begin
L_NextSibling := Node.NextSibling;
Delete(Node);
Node := L_NextSibling;
end;
FRoot := nil;
EndUpdate;
end;function DoDelete(Node: TNode): Integer;
var
L_Node, L_NextSibling: TNode;
begin
Result := 0;
if Node = nil then exit;
L_Node := Node.FirstChild;
while L_Node <> nil do
begin
L_NextSibling := L_Node.NextSibling;
Inc(Result, DoDelete(L_Node));
L_Node := L_NextSibling;
end;
Node.Free;
Inc(Result);
end;
var
L_Parent, L_PrevSibling, L_NextSibling: TNode;
begin
if Node = nil then exit;
L_Parent := Node.Parent;
L_PrevSibling := Node.PrevSibling;
L_NextSibling := Node.NextSibling;
if L_PrevSibling = nil then // 无兄
begin
if L_Parent = nil then // 无兄无父
begin
if L_NextSibling = nil then // 无兄无父无弟
FRoot := nil
else // 无兄无父有弟
begin
FRoot := L_NextSibling;
FRoot.FPrevSibling := nil;
end;
end
else // 无兄有父
begin
if L_NextSibling = nil then // 无兄有父无弟
L_Parent.FFirstChild := nil
else // 无兄有父有弟
begin
L_Parent.FFirstChild := L_NextSibling;
L_NextSibling.FPrevSibling := nil;
end;
end;
end
else // 有兄
begin
if L_NextSibling = nil then // 有兄无弟
L_PrevSibling.FNextSibling := nil
else // 有兄有弟
begin
L_PrevSibling.FNextSibling := L_NextSibling;
L_NextSibling.FPrevSibling := L_PrevSibling;
end;
end;
end;
procedure TNodes.Delete(Node: TNode);
begin
if Node = nil then exit;
AdjustDelete(Node);
DoDelete(Node);
if FUpdateCount = 0 then BuildNodeList;
end;
procedure TNodes.Delete(Index: Integer);
var
Node: TNode;
begin
if FUpdateCount > 0 then
raise Exception.Create('此时无法进行该操作');
Node := FNodeList[Index];
if Node = nil then exit;
AdjustDelete(Node);
FNodeList.Delete(Index, DoDelete(Node));
end;
procedure TNodes.DeleteChildren(Node: TNode);
var
L_Node, L_NextSibling: TNode;
begin
if Node = nil then exit;
L_Node := Node.FirstChild;
while L_Node <> nil do
begin
L_NextSibling := L_Node.NextSibling;
DoDelete(L_Node);
L_Node := L_NextSibling;
end;
Node.FFirstChild := nil;
if FUpdateCount = 0 then BuildNodeList;
end;
procedure TNodes.DeleteChildren(Index: Integer);
var
Node, L_Node, L_NextSibling: TNode;
DeleteCount: Integer;
begin
if FUpdateCount > 0 then
raise Exception.Create('此时无法进行该操作');
Node := FNodeList[Index];
if Node = nil then exit;
if not Node.HasChildren then exit;
DeleteCount := 0;
L_Node := Node.FirstChild;
while L_Node <> nil do
begin
L_NextSibling := L_Node.NextSibling;
Inc(DeleteCount, DoDelete(L_Node));
L_Node := L_NextSibling;
end;
Node.FFirstChild := nil;
FNodeList.Delete(Index+1, DeleteCount);
end;
procedure TNodes.EndUpdate;
begin
if FUpdateCount > 0 then Dec(FUpdateCount);
if FUpdateCount = 0 then BuildNodeList;
end;
procedure TNodes.BuildNodeList;
procedure AddOneNode(Node: TNode);
begin
while Node <> nil do
begin
FNodeList.Add(Node);
if Node.FirstChild <> nil then
AddOneNode(Node.FirstChild);
Node := Node.NextSibling;
end;
end;
begin
FNodeList.Clear;
FNodeList.Capacity := FCapacity;
AddOneNode(FRoot);
end;
function TNodes.InsertObject(Node: TNode; Ptr: Pointer): TNode;
var
L_Node: TNode;
begin
if Node = nil then
Result := InternalAdd(Node, Ptr, amAddChild)
else
begin
if Node.PrevSibling = nil then
Result := InternalAdd(Node.Parent, Ptr, amAddChildFirst)
else
begin
Result := TNode.Create(Self);
Result.Data := Ptr;
Result.FParent := Node.Parent;
L_Node := Node.PrevSibling;
L_Node.FNextSibling := Result;
Result.FPrevSibling := L_Node;
Result.FNextSibling := Node;
Node.FPrevSibling := Result;
if FUpdateCount = 0 then
FNodeList.Insert(FNodeList.IndexOf(Node), Result);
end;
end;
end;
function TNodes.InternalAdd(Node: TNode; Ptr: Pointer;
AddMode: TAddMode): TNode;
var
L_Node: TNode;
begin
Result := TNode.Create(Self);
Result.Data := Ptr;
if Node = nil then
begin
if FRoot = nil then
begin
FRoot := Result;
if FUpdateCount = 0 then
FNodeList.Insert(0, Result);
end
else
case AddMode of
amAddChildFirst:
begin
Result.FNextSibling := FRoot;
FRoot.FPrevSibling := Result;
FRoot := Result;
if FUpdateCount = 0 then
FNodeList.Insert(0, Result);
end;
amAddChild:
begin
L_Node := FRoot.GetLastSibling;
L_Node.FNextSibling := Result;
Result.FPrevSibling := L_Node;
if FUpdateCount = 0 then
FNodeList.Add(Result);
end;
end;
end
else
begin
Result.FParent := Node;
if Node.HasChildren then
begin
if AddMode = amAddChildFirst then
begin
L_Node := Node.FirstChild;
Node.FFirstChild := Result;
Result.FNextSibling := L_Node;
L_Node.FPrevSibling := Result;
if FUpdateCount = 0 then
FNodeList.Insert(FNodeList.IndexOf(L_Node), Result);
end
else
begin
L_Node := Node.LastChild;
L_Node.FNextSibling := Result;
Result.FPrevSibling := L_Node;
if FUpdateCount = 0 then
begin
while L_Node.HasChildren do
L_Node := L_Node.LastChild;
FNodeList.Insert(FNodeList.IndexOf(L_Node)+1, Result);
end;
end;
end
else
begin
Node.FFirstChild := Result;
if FUpdateCount = 0 then
FNodeList.Insert(FNodeList.IndexOf(Node)+1, Result);
end;
end;
end;
function TNodes.Add(Node: TNode; Ptr: Pointer): TNode;
begin
if Node <> nil then Node := Node.Parent;
Result := InternalAdd(Node, Ptr, amAddChild);
end;
function TNodes.AddFirst(Node: TNode; Ptr: Pointer): TNode;
begin
if Node <> nil then Node := Node.Parent;
Result := InternalAdd(Node, Ptr, amAddChildFirst);
end;
function TNodes.GetItems(Index: Integer): TNode;
begin
if FUpdateCount > 0 then
raise Exception.Create('此时无法进行该操作');
Result := FNodeList[Index];
end;
function TNodes.IndexOf(Node: TNode): Integer;
begin
if FUpdateCount > 0 then
raise Exception.Create('此时无法进行该操作');
Result := FNodeList.IndexOf(Node);
end;
begin
case Mode of
mmAdd:
mmAddFirst:
mmAddChild:
mmAddChildFirst:
mmInsert:
end;
end;}
procedure TNodes.LevelDown(Node: TNode);
var
Dest: TNode;
begin
Dest := Node.PrevSibling;
if Dest = nil then
Dest := Node.NextSibling;
if Dest = nil then exit;
AdjustDelete(Node);
Node.FParent := Dest;
Node.FNextSibling := nil;
if Dest.HasChildren then
begin
Dest := Dest.LastChild;
Dest.FNextSibling := Node;
Node.FPrevSibling := Dest;
end
else
begin
Dest.FFirstChild := Node;
Node.FPrevSibling := nil;
end;
if FUpdateCount = 0 then BuildNodeList;
end;
procedure TNodes.LevelUp(Node: TNode);
var
L_PrevSibling, L_NextSibling: TNode;
begin
if Node.Level = 0 then exit;
L_PrevSibling := Node.Parent;
L_NextSibling := Node.Parent.NextSibling;
AdjustDelete(Node);
Node.FParent := L_PrevSibling.Parent;
L_PrevSibling.FNextSibling := Node;
Node.FPrevSibling := L_PrevSibling;
Node.FNextSibling := L_NextSibling;
if L_NextSibling <> nil then
L_NextSibling.FPrevSibling := Node;
if FUpdateCount = 0 then BuildNodeList;
end;
procedure TNodes.MoveDown(Node: TNode);
var
L_PrevSibling, L_NextSibling: TNode;
begin
L_NextSibling := Node.NextSibling;
if L_NextSibling = nil then exit;
AdjustDelete(Node);
L_PrevSibling := L_NextSibling;
L_NextSibling := L_NextSibling.NextSibling;
L_PrevSibling.FNextSibling := Node;
Node.FPrevSibling := L_PrevSibling;
Node.FNextSibling := L_NextSibling;
if L_NextSibling <> nil then
L_NextSibling.FPrevSibling := Node;
if FUpdateCount = 0 then BuildNodeList;
end;
procedure TNodes.MoveUp(Node: TNode);
var
L_PrevSibling: TNode;
begin
L_PrevSibling := Node.PrevSibling;
if L_PrevSibling = nil then exit;
MoveDown(L_PrevSibling);
end;
procedure TNodes.FullCollapse;
var
Node: TNode;
begin
Node := FRoot;
while Node <> nil do
begin
Node.Collapse(True);
Node := Node.NextSibling;
end;
end;
procedure TNodes.FullExpand;
var
Node: TNode;
begin
Node := FRoot;
while Node <> nil do
begin
Node.Expand(True);
Node := Node.NextSibling;
end;
end;
end.
3年前的程序了,现在看到还是感觉很亲切。
说明:如果程序中不需要按index访问,可以不用TMyList,并将程序中涉及到该list的地方重新改造一下。因为这个list对访问进行了限制,不是随时都可以的。
可写出来的程序还是有很大差别这段程序用在了国内某建筑软件公司的概预算软件中。
然后我把StringGrid又改造了一下(说是改造,跟自己写一个差不多,而且代码多了3、4千行),大大增强了原有的功能。
最后我写了个控件,封装了TNodes、改造后的StringGrid(本身也是个控件)、数据集,做成了个树形网格编辑控件。
我离开了这家公司后,该公司将我写的控件做成了activex控件,用在了很多产品中。
涉及到知识产权问题,改造后的StringGrid与树形网格编辑控件我不能共享了,很抱歉!
[email protected]