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

📄 dbtree.pas

📁 delphi编程控件
💻 PAS
📖 第 1 页 / 共 5 页
字号:
  begin
    Exclude(FState, dtvsNeedReBuildAfterPost);
    if (not (dtRebuildFocusedOnly in Options)) or Focused then
      BuildTree
    else
      Include(FState, dtvsNeedReBuild);
  end;
end;

procedure TCustomDBTreeView.DataSetAfterCancel;
var
  Node: TTreeNode;
begin
  Exclude(FState, dtvsNeedReBuildAfterPost);
  if (dtvsLostFocusWhileDatasetInEditModes in FState) then
  begin
    if (Selected <> nil) and not IsEditing then
    begin
    { Maybe we changed the Text of the node, but that was cancelled now: }
      Selected.Text := DataSet.FieldByName(FTableTextField).AsString;
    end;
    Exclude(FState, dtvsLostFocusWhileDatasetInEditModes);
  end;
  if (dtvsDatasetInEditMode in FState) then
  begin
  { DataSet.State has changed from dsEdit to dsBrowse, but that was not
    done by TCustomDBTreeView: }
    Exclude(FState, dtvsDatasetInEditMode);
    if (FDisableCount = 0) and IsEditing then
    { TCustomDBTreeView is still in edit-mode but someone canceled e.g.
      by pressing cancel on a DBNavigator. Stop edit: }
      Selected.EndEdit(true);
  end
  else
  begin
    if (dtvsDatasetInInsertMode in FState) then
    begin
    { DataSet.State has changed from dsInsert to dsBrowse, but that was
      not done by TCustomDBTreeView: }
      Exclude(FState, dtvsDatasetInInsertMode);
      if (FDisableCount = 0) then
      begin
      { Someone canceled inserting, e.g. by pressing cancel on a DBNavigator,
        or a TDBGrid with dgCancelOnExit in Options lost focus: }
        if IsEditing then
        begin
        { still in insert-mode. Stop insert: }
          Node := Selected;
          if (Node <> nil) then
          begin
            Node.EndEdit(true);
            if (Node.GetNextSibling <> nil) then
              Selected := Node.GetNextSibling
            else
              if (Node.GetPrevSibling <> nil) then
                Selected := Node.GetPrevSibling
              else
                if (Node.Parent <> nil) then
                  Selected := Node.Parent;
            Items.Delete(Node);
          end;
        end
        else
        begin
        { Maybe TDBGrid with dgCancelOnExit in Options lost focus and the
          empty record was deleted. }
        { if (DataSet.FieldByName(FTableIDField).AsString <> SelectedID) ...
          does not work because RecordNumberChanged happend already. So: }
          if Assigned(FTVRecordList) then
          begin
          { sorry, but we have to do a complete rebuild: }
            FTVRecordList.Free;
            FTVRecordList := nil;
          end;
          BuildTree;
        end;
      end;
    end;
  end;
end;

procedure TCustomDBTreeView.DataSetBeforeDelete;
var
  Node: TTreeNode;
begin
  if (FDisableCount = 0) and (not Readonly) then
  begin
    Node := GetDataSetIDNode;
    if (Node <> nil) then
    begin
      if (dtRootItemReadOnly in Options) and IsRootNode(Node) then
      { Do not let the user delete a RootNode if dtRootItemReadOnly in Options.
        The EAbort exception is Delphi's "silent" exception.
        When it is raised, no message box appears to inform the user: }
        raise EAbort.Create('RootItem is ReadOnly');
      if (dtConfirmDelete in Options) or Node.HasChildren then
      begin
        DeleteNode(Node); { ask user }
      { Raise the EAbort exception, Delphi's "silent" exception, to stop
        deletion of a record that does not exist anymore: }
        raise EAbort.Create(''); { exit dataset.delete }
      { Sorry, EAbort is not "silent" in the IDE, press F9 to continue... }
      end;
    end
    else
    { record is not in tree: }
      if (dtConfirmDelete in Options) then
      { No confirmation possible: }
        raise EAbort.Create(''); { exit dataset.delete }
  end;
{ No reason to abort deletion or do it ous way: }
  if (FDisableCount = 0) then
    try
      FIDOfDeleted := Dataset.FieldByName(FTableIDField).AsString;
    except
      FIDOfDeleted := '';
    end;
end;

procedure TCustomDBTreeView.DataSetAfterDelete;
var
  Node: TTreeNode;
begin
  if (FDisableCount = 0) then
    if (FIDOfDeleted <> '') then
    begin
      Node := Selected;
      if (Node.GetNextSibling <> nil) then
        Selected := Node.GetNextSibling
      else
        if (Node.GetPrevSibling <> nil) then
          Selected := Node.GetPrevSibling
        else
          if (Node.Parent <> nil) then
            Selected := Node.Parent;
      Items.Delete(Node);
      FIDOfDeleted := '';
    end
    else
      if (not (dtRebuildFocusedOnly in Options)) or Focused then
        BuildTree
      else
        Include(FState, dtvsNeedReBuild);
end;

function TCustomDBTreeView.DataSetLocate(const ID: string): Boolean;
begin
  with DataSet do
  begin
    if (ID = FieldByName(FTableIDField).AsString) then
    begin
      Result := true;
      exit; { nothing to do }
    end;
    if (ID = '') then
    begin
      Result := false;
      exit; { DataSet.Locate does not work with empty value }
    end;
    Include(FState, dtvsChangingDataset);
    Inc(FDisableCount);
    try
      Result := DataSet.Locate(FTableIDField, ID, []);
    finally
      Dec(FDisableCount);
    end;
  end;
end;

procedure TCustomDBTreeView.SynchronizeSelectedNodeToCurrentRecord;
var
  Node: TTreeNode;
begin
  Node := GetDataSetIDNode;
  if (Node <> nil) then
  begin
    Selected := Node;
    Node.MakeVisible;
    if (dtAutoExpand in Options) and Node.HasChildren then
    begin
      try
        Inc(FDisableCount);
        Node.Expand(dtAutoExpand in Options);
        Selected := Node;
      finally
        Dec(FDisableCount);
      end;
    end;
  end;
end;

procedure TCustomDBTreeView.SynchronizeCurrentRecordToSelectedNode;
begin
  if (Selected <> nil) and (DataSet <> nil) and (DataSet.Active) then
    DataSetLocate(SelectedID);
end;

procedure TCustomDBTreeView.IndexChanged;
begin
  if (not (dtvsBuilding in FState)) and (FDisableCount = 0) and
     (dtSynchronizeDataSet in Options) then
   SynchronizeCurrentRecordToSelectedNode;
end;

procedure TCustomDBTreeView.Expand(Node: TTreeNode);
begin
  inherited Expand(Node);
{
  if (not (dtvsBuilding in FState)) and (FDisableCount = 0) and
     (Selected <> nil) then
    Selected.MakeVisible;
}    
end;

procedure TCustomDBTreeView.SetRootID(ID: string);
begin
  if (FRootID <> ID) then
  begin
    FRootID := ID;
    if FTreeViewLink.Active then
      BuildTree;
  end;
end;

function TCustomDBTreeView.GetID(AIndex: Integer): string;
begin
  Result := '';
  if (AIndex >= 0) and (AIndex < Items.Count) then
    Result := IDOfNode(Items[AIndex]);
end;

function TCustomDBTreeView.GetSelectedID: string;
begin
  if Selected = nil then
    Result := FRootID
  else
    Result := IDOfNode(Selected);
end;

procedure TCustomDBTreeView.SelectID(const Value: string);
var
  Node: TTreeNode;
begin
  Node := GetIDNode(Value);
  if (Node <> nil) then
    Selected := Node;
end;

procedure TCustomDBTreeView.CNNotify(var Message: TWMNotify);
begin
  if (Message.NMHdr^.code = TVN_BEGINLABELEDIT) then
  begin
    inherited;
    if (DataSet = nil) then
      exit;
    if (Message.Result = 0) and (DataSet <> nil) then
    begin { node is in edit-mode now: }
      try
        if (DataSet.State = dsBrowse) then
        begin
          if not (dtSynchronizeDataSet in Options) then
            SynchronizeCurrentRecordToSelectedNode; { Synchronize now }
          if (dtvsNeedReBuild in FState) then
          begin
            Message.Result := 1;
            Include(FState, dtvsEditAfterReBuild);
            DatasetRefreshed;
          end
          else
          begin
            Inc(FDisableCount);
            try
              DataSet.Edit;
              if (dtvsNeedReBuild in FState) then
              begin
                DataSet.Cancel;
                Message.Result := 1;
                Include(FState, dtvsEditAfterReBuild);
                DatasetRefreshed;
              end;
            finally
              Dec(FDisableCount);
            end;
          end;
        end;
      except
        Message.Result := 1;
        raise;
      end;
    end;
  end
  else
    inherited;
end;

function TCustomDBTreeView.CanEdit(Node: TTreeNode): Boolean;
begin
  KillAllTimer;
  if DataSet.CanModify then
    Result := inherited CanEdit(Node)
  else
    Result := false;
end;

procedure TCustomDBTreeView.AfterEdit(Sender: TObject;
  Node: TTreeNode; var S: string);
begin
  if Assigned(FUserOnEdited) then
    FUserOnEdited(Sender, Node, S);
  if (FDisableCount = 0) and (Node <> nil) then
  begin
    with DataSet do
    begin
      if (State <> dsInsert) and (State <> dsEdit) then
        exit;
      if (FieldByName(FTableIDField).AsString <> IDOfNode(Node)) then
        exit; { maybe an error: this is not the record we started to edit! }
      Inc(FDisableCount);
      try
        if (FieldByName(FTableTextField).AsString <> S) then
          FieldByName(FTableTextField).AsString := S;
        if Focused then { if we just lost focus, don't touch DataSet }
        begin
          Post;
        end;
      finally
        Dec(FDisableCount);
      end;
    end;
  end;
end;

procedure TCustomDBTreeView.Edit(const Item: TTVItem);
var
  DeleteAll: Boolean;
  Canceled: Boolean;
begin
  if Assigned(FUserOnEdited) then
    exit; { rekursive call }
  FUserOnEdited := OnEdited;
  OnEdited := AfterEdit;
  try
    inherited Edit(Item); { calls proc AfterEdit if something was changed }
  finally
    OnEdited := FUserOnEdited;
    FUserOnEdited := nil;
  end;
  if (FDisableCount > 0) then
    exit;
  if (DataSet = nil) then
    exit;
  if not Focused then
  begin
  { we just lost the focus: }
    if (dtCancelOnExit in Options) and (DataSet.State = dsInsert) then
    begin
      if not DataSet.Modified then
      begin
        Exclude(FState, dtvsDatasetInEditMode);
        Exclude(FState, dtvsDatasetInInsertMode);
        DeleteAll := true;
        Canceled := false;
        InternalDeleteNode(Selected, false, DeleteAll, Canceled);
        exit;
      end;
    end;
    Include(FState, dtvsLostFocusWhileDatasetInEditModes);
    exit;
  end;
  Exclude(FState, dtvsDatasetInEditMode);
  Exclude(FState, dtvsDatasetInInsertMode);
  if (DataSet.State = dsInsert) then
  begin
  { proc AfterEdit was not called: user cancelled inserting }
    DeleteAll := true;
    Canceled := false;
    InternalDeleteNode(Selected, false, DeleteAll, Canceled);
  end
  else
    if (DataSet.State = dsEdit) then
    begin
    { proc AfterEdit was not called: user cancelled editing }
      Inc(FDisableCount);
      try
        DataSet.Cancel;
      finally
        Dec(FDisableCount);
      end;
    end;
end;

procedure TCustomDBTreeView.Change(Node: TTreeNode);
begin
  if (FDisableCount = 0) then
  begin
    FTreeViewLink.CheckRefresh;
    if (dtvsNeedReBuild in FState) then
      BuildTree;
  end;
  IndexChanged;
  inherited Change(Node);
end;

procedure TCustomDBTreeView.SetOptions(Value: TDBTreeOptions);
var
  TreeViewExOptions: TTreeViewExOptions;
begin
  if (dtSynchronizeDataSet in Value) and
     not (dtSynchronizeDataSet in Options) then
    SynchronizeCurrentRecordToSelectedNode; { Synchronize now }
  TreeViewExOptions := [];
  if (dtAllowDelete in Value) then
    Include(TreeViewExOptions, tveAllowDelete);
  if (dtAllowInsert in Value) then
    Include(TreeViewExOptions, tveAllowInsert);
  if (dtAutoDragMove in Value) then
    Include(TreeViewExOptions, tveAutoDragMove);
  if (dtRootItemReadOnly in Value) then
    Include(TreeViewExOptions, tveRootItemReadOnly);
  if (dtConfirmDelete in Value) then
    Include(TreeViewExOptions, tveConfirmDelete);
  if (dtMouseMoveSelect in Value) then
    Include(TreeViewExOptions, tveMouseMoveSelect);
  if (dtInsertAsChild in Value) then
    Include(TreeViewExOptions, tveInsertAsChild);
  if (FRootID = '') then
    Include(TreeViewExOptions, tveMultipleRootsAllowed);
  inherited Options := TreeViewExOptions;
  FOptions := Value;
end;

function TCustomDBTreeView.DragAllowed(Node: TTreeNode): Boolean;
begin
  if (DataSet <> nil) and not DataSet.CanModify then
    result := false
  else
    result := inherited DragAllowed(Node);
end;

function TCustomDBTreeView.GetNewID: string;
var
  FIndexName: string;
  FIndexFields: string;
  sID: string;
  IntValue: Integer;

⌨️ 快捷键说明

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