⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbtree.pas

📁 delphi编程控件
💻 PAS
📖 第 1 页 / 共 5 页
字号:
  ValCode: Integer;
  WasFiltered: Boolean;
begin
  if Assigned(FOnGetNextID) then
  begin
    Result := FOnGetNextID(self, DataSet);
    exit;
  end;
  Result := '0';
  with DataSet do
  begin
    Inc(FDisableCount);
    try
      DisableControls;
      WasFiltered := Filtered;
      try { search for the highest ID-Value first: }
        Filtered := false;
        if (DataSet is TTable) then
          with TTable(DataSet) do
          begin
            FIndexFields := IndexFieldNames;
            FIndexName := IndexName;
            IndexFieldNames := FTableIDField;
          end;
        if (FieldByName(FTableIDField).DataType = ftString) or
           not (DataSet is TTable) or
           (CompareText(Copy(TTable(DataSet).IndexFieldNames, 1,
                             Length(FTableIDField)),
                        FTableIDField) <> 0) then
        begin
        { Check EVERY record for the highest ID-Value: }
          IntValue := 0;
          First;
          while not EOF do
          begin
            try
              sID := FieldByName(FTableIDField).AsString;
              Val(sID, IntValue, ValCode);
              if (ValCode = 0) then
                Inc(IntValue);
            except
            end;
            if (IntValue > StrToInt(Result)) then
              Result := IntToStr(IntValue);
            Next;
          end;
        end
        else
        begin
          Last;
          if not BOF then
          try
            Result := IntToStr(FieldByName(FTableIDField).AsInteger + 1);
          except
          end;
        end;
      finally
        if DataSet is TTable then
          with TTable(DataSet) do
          begin
            if FIndexName <> '' then
              IndexName := FIndexName
            else
              IndexFieldNames := FIndexFields;
          end;
        Filtered := WasFiltered;
      end;
    finally
      EnableControls;
      Dec(FDisableCount);
    end;
  end;
end;

{$HINTS OFF}
procedure TCustomDBTreeView.Insert(AsChild: Boolean);
var
  NewID: string;
  FSelectedID: string;
  NewNode: TTreeNode;
  ParentNode: TTreeNode;
begin
  if (DataSet = nil) then
  begin
    inherited;
    exit;
  end;
  if (FDisableCount = 0) then
  begin
    FTreeViewLink.CheckRefresh;
    if (dtvsNeedReBuild in FState) then
      BuildTree;
  end;
  if not DataSet.CanModify then
    exit;
  Inc(FDisableCount);
  try
    FSelectedID := SelectedID;
    NewID := GetNewID;
    NewNode := nil;
    with DataSet do
    begin
      try
//      DisableControls;
        Append;
        FieldByName(FTableIDField).Value := NewID;
        if AsChild and (Selected <> nil) then
        begin
          if (FSelectedID <> '') and (NewID <> FSelectedID) then
            FieldByName(FTableParentField).Value := FSelectedID;
          NewNode := AddNewNodeFromDataset(Selected, true);
        end
        else
        begin
          if (Selected <> nil) then
          begin
            ParentNode := Selected.Parent;
            if (ParentNode <> nil) and (ParentNode is TTreeIDNode) and
               (TTreeIDNode(ParentNode).ID <> '') and
               (TTreeIDNode(ParentNode).ID <> NewID) then
              FieldByName(FTableParentField).Value := TTreeIDNode(ParentNode).ID;
          end;
          NewNode := AddNewNodeFromDataset(Selected, false);
        end;
        if (NewNode <> nil) then
        begin
          Selected := NewNode;
          if (dtAutoShowRoot in Options) and (Items.Count = 2) and
             IsRootNode(Selected) then
            ShowRoot := true;
        end;
      finally
//        EnableControls;
      end;
    end;
    if (NewNode <> nil) then
    begin
      if (dtFocusOnEdit in Options) then
        SetFocus;
      if Focused then
        NewNode.EditText;
    end;
  finally
    Dec(FDisableCount);
  end;
end;
{$HINTS ON}

function TCustomDBTreeView.GetDeleteQuestion(Node: TTreeNode): string;
begin
  if (Node <> nil) and (Pos('%s', sdbtvDefaultDeleteQuestion) > 0) then
    result := Format(sdbtvDefaultDeleteQuestion, [Node.Text])
  else
    result := sdbtvDefaultDeleteQuestion;
end;

function TCustomDBTreeView.DoDelete(Node: TTreeNode): Boolean;
begin
  if (DataSet = nil) then
  begin
    result := inherited DoDelete(Node);
    exit;
  end;
  if DataSetLocate(IDOfNode(Node)) then
  begin
    if not (DataSet.FieldByName(FTableIDField).Value = IDOfNode(Node)) then
    begin
    { should NEVER happen, but I want to make sure
      not to delete another record }
      result := false;
      exit;
    end;
    Inc(FDisableCount); { no BuildTree please ! }
    try
      if (DataSet.State = dsInsert) then
        DataSet.Cancel { cancel of insert works like deleting it }
      else
        DataSet.Delete;
    finally
      Dec(FDisableCount);
    end;
    result := inherited DoDelete(Node);
    if result and (dtAutoShowRoot in Options) then
      if (Items.Count = 0) then
        ShowRoot := false
      else
        ShowRoot := not IsSingleRootNode(Items[0]);
  end
  else
    result := false;
end;

procedure TCustomDBTreeView.Delete;
begin
  if (DataSet = nil) then
  begin
    inherited;
    exit;
  end;
  if (FDisableCount = 0) then
  begin
    FTreeViewLink.CheckRefresh;
    if (dtvsNeedReBuild in FState) then
      BuildTree;
  end;
  if DataSet.CanModify then
    inherited;
end;

procedure TCustomDBTreeView.KeyDown(var Key: Word; Shift: TShiftState);
begin
  KillAllTimer;
  if (FDisableCount = 0) then
  begin
    FTreeViewLink.CheckRefresh;
    if (dtvsNeedReBuild in FState) and
       (not (dtvsBuilding in FState)) and
       (not IsEditing) and (FIDOfDeleted = '') then
      BuildTree;
  end;
  inherited KeyDown(Key, Shift);
end;

procedure TCustomDBTreeView.WMTimer(var Msg: TWMTimer);
begin
  if (Msg.TimerID = TimerIDRebuild) then
  begin
        if (FDisableCount = 0) and (not (dtvsBuilding in FState)) and
           (not IsEditing) and (FIDOfDeleted = '') and
           (dtvsNeedReBuild in FState) then
        begin
          KillTimer(Handle, TimerIDRebuild);
          FReBuildTimer := 0;
          BuildTree;
        end
        else
          if not (dtvsNeedReBuild in FState) then
          begin
            KillTimer(Handle, TimerIDRebuild);
            FReBuildTimer := 0;
          end;
  end
  else
    inherited;
end;

function TCustomDBTreeView.MoveNode(Source, Destination: TTreeNode;
  Mode: TNodeAttachMode): Boolean;
var
  DestinationID: string;
begin
  if (DataSet = nil) or not DataSet.Active then
  begin
    Result := inherited MoveNode(Source, Destination, Mode);
    exit;
  end;
  Result := false;
  if (Source = nil) then
    exit;
  with DataSet do
  begin
    Inc(FDisableCount);
    try
//    DisableControls;
      if DataSetLocate(IDOfNode(Source)) then
      begin
        Edit;
        try
          Result := inherited MoveNode(Source, Destination, Mode);
          if Result then
          begin
            if (SortType = stNone) then
            begin
              if (Destination <> nil) then
                Destination.AlphaSort
              else
                AlphaSort;
              Source.MakeVisible;
            end;
            if (Source.Parent = nil) then
              DestinationID := FRootID
            else
              DestinationID := IDOfNode(Source.Parent);
            if (DestinationID <> '') then
              DataSet.FieldByName(FTableParentField).Value := DestinationID
            else
              DataSet.FieldByName(FTableParentField).Clear;
            Post;
            if Assigned(FTVRecordList) then
              FTVRecordList.ChangeParent(IDOfNode(Source), DestinationID);
            if (dtAutoShowRoot in Options) then
              if (Items.Count = 0) then
                ShowRoot := false
              else
                ShowRoot := not IsSingleRootNode(Items[0]);
          end
          else
            Cancel;
        except
          if (State = dsEdit) then
            Cancel;
          raise;
        end;
      end;
    finally
//    EnableControls;
      Dec(FDisableCount);
    end;
  end;
end;

function TCustomDBTreeView.GetExpanded(Separator: Char): string;
var
  i: Integer;
  FirstItem: Boolean;
begin
  result := '';
  FirstItem := true;
  for i := 0 to Items.Count - 1 do
  begin
    with Items[i] do
      if Expanded and (Count > 0) then
        if FirstItem then
        begin
          FirstItem := false;
          result := IDOfNode(Items[i]);
        end
        else
          result := result + Separator + IDOfNode(Items[i]);
  end;
end;

procedure TCustomDBTreeView.SetExpanded(const List: string; Separator: Char);
var
  i: Integer;
  xList: string;
  Node: TTreeNode;
begin
  Items.BeginUpdate; { changes are not visible until EndUpdate }
  Node := TopItem;
  xList := Separator + List + Separator;
  for i := 0 to Items.Count - 1 do
    Items[i].Expanded :=
      (Pos(Separator + IDs[i] + Separator, xList) > 0);
  if (Node <> nil) then
    TopItem := Node;
  Node := Selected;
  if (Node <> nil) then
    Node.MakeVisible;
  Items.EndUpdate;
end;

procedure TCustomDBTreeView.WMSetFocus(var Message: TMessage);
begin
{ We just received the focus. If the dateaset is in edit- or insert-mode
  and dtFocusOnEdit is in Options, we have to set the selected node into
  the edit-mode. }
  inherited;
  if (FDisableCount = 0) then
  begin
    FTreeViewLink.CheckRefresh;
    if (dtvsNeedReBuild in FState) then
      BuildTree;
    if ((dtFocusOnEdit in Options) or
        (dtvsLostFocusWhileDatasetInEditModes in FState)) and
       not IsEditing then
    begin
      Exclude(FState, dtvsLostFocusWhileDatasetInEditModes);
      if (DataSet <> nil) then
        with DataSet do
          if (State = dsEdit) or (State = dsInsert) then
          begin
            if not (dtSynchronizeDataSet in Options) then
              SynchronizeSelectedNodeToCurrentRecord;
            if (Selected <> nil) then
              Selected.EditText;
          end;
    end;
  end;
end;

procedure TCustomDBTreeView.RebuildTree;
begin
  Include(FState, dtvsNeedReBuild);
  BuildTree;
end;

function TCustomDBTreeView.FindTextID(const S: string; var ID: string;
  TVFindTextOptions: TTVFindTextOptions): Boolean;
begin
  if Assigned(FTVRecordList) then
    result := FTVRecordList.FindTextID(
      S, ID, TInternalTVFindTextOptions(TVFindTextOptions))
  else
    result := false;
end;

function TCustomDBTreeView.TextIDList(const S: string;
  TVFindTextOptions: TTVFindTextOptions): TStringList;
begin
  if Assigned(FTVRecordList) then
    result := FTVRecordList.TextIDList(
      S, TInternalTVFindTextOptions(TVFindTextOptions))
  else
    result := nil;
end;

function TCustomDBTreeView.IDOfNode(Node: TTreeNode): string;
begin
  if (Node = nil) then
    result := ''
  else
    if Node is TTreeIDNode then
      result := TTreeIDNode(Node).ID
    else
      result := '';
end;

function TCustomDBTreeView.CreateNode: TTreeNode;
begin
  Result := TTreeIDNode.Create(Items);
end;

procedure TCustomDBTreeView.DestroyWnd;
var
  i: Integer;
begin
  if Items.Count > 0 then
  begin
    FSaveIDList := TStringList.Create;
    for i := 0 to Items.Count - 1 do
      FSaveIDList.Add(IDOfNode(Items[i]));
  end;
  inherited DestroyWnd;
end;

procedure TCustomDBTreeView.CreateWnd;
var
  i: Integer;
begin
  inherited CreateWnd;
  if (FSaveIDList <> nil) then
  begin
    if (FSaveIDLis

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -