git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@38 05c56307-c608-d34a-929d-697000501d7a
840 lines
27 KiB
ObjectPascal
840 lines
27 KiB
ObjectPascal
unit dxtree;
|
|
{*******************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ Express tree view control }
|
|
{ }
|
|
{ Copyright (c) 1998-2009 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSGRID AND ALL ACCOMPANYING VCL }
|
|
{ CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{*******************************************************************}
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
|
ComCtrls, CommCtrl, ExtCtrls ;
|
|
|
|
type
|
|
TdxTreeViewOption = (trCanDelete, trConfirmDelete);
|
|
TdxTreeViewOptions = set of TdxTreeViewOption;
|
|
|
|
TDragDropTreeNode = procedure(Destination, Source: TTreeNode;
|
|
var Accept: Boolean) of object;
|
|
TEndDragTreeNode = procedure(Destination, Source: TTreeNode;
|
|
var AttachMode: TNodeAttachMode) of object;
|
|
TDragDropIsCopy = procedure(Destination, Source: TTreeNode;
|
|
var IsCopy: Boolean) of object;
|
|
TTreeViewCustomDraw = procedure(Sender: TObject; TreeNode: TTreeNode;
|
|
AFont: TFont; var AColor, ABkColor: TColor) of object;
|
|
|
|
// Avoid MoveTo bug in D4.
|
|
TdxTreeNode = class(TTreeNode)
|
|
{$IFDEF DELPHI4}
|
|
procedure MoveTo(Destination: TTreeNode; Mode: TNodeAttachMode); override;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
TCustomdxTreeView = class(TCustomTreeView)
|
|
private
|
|
FOptions: TdxTreeViewOptions;
|
|
FSelectedIndex: Integer;
|
|
FDragDropProcessingFlag: Boolean;
|
|
FDragObject: TDragObject;
|
|
FDeletingConfirmationMessage: string;
|
|
FIsConfirmationAssigned: Boolean;
|
|
FScrollTimerID: Integer;
|
|
fntcd: TFont;
|
|
FCanvas: TControlCanvas;
|
|
FOnDragDropTreeNode: TDragDropTreeNode;
|
|
FOnEndDragTreeNode: TEndDragTreeNode;
|
|
FOnDragDropIsCopy: TDragDropIsCopy;
|
|
FOnCustomDraw: TTreeViewCustomDraw;
|
|
FOnSetEditText: TTVEditedEvent;
|
|
FShowNodeHint: Boolean;
|
|
FInternalDragObject: TDragObject;
|
|
|
|
function GetDragSourceTreeNode: TTreeNode;
|
|
function GetDeletingConfirmationMessage: string;
|
|
procedure SetSelectedIndex(Value: Integer);
|
|
procedure SetDeletingConfirmationMessage(const AValue: string);
|
|
procedure CMDrag(var Message: TCMDrag); message CM_DRAG;
|
|
function DoCNNotify(var Message: TWMNotify): Boolean;
|
|
function DoWMNotify(var Message: TWMNotify): Boolean;
|
|
procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
|
|
procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
|
|
procedure ReadIsAssigned(AReader: TReader);
|
|
procedure WriteIsAssigned(AWriter: TWriter);
|
|
protected
|
|
CopyTreeNodeStructFlag: Boolean;
|
|
|
|
procedure DefineProperties(AFiler: TFiler); override;
|
|
|
|
procedure DoCustomDraw(TreeNode: TTreeNode; AFont: TFont;
|
|
var AColor, ABkColor: TColor); virtual;
|
|
procedure DoStartDrag(var DragObject: TDragObject); override;
|
|
procedure DoEndDrag(Target: TObject; X, Y: Integer); override;
|
|
function GetNodeFromItem(const Item: TTVItem): TTreeNode;
|
|
function GetListItemText(TreeNode: TTreeNode): String; virtual;
|
|
procedure InsertTreeNodeStructure(ListS, ListD: TList; Flag: Boolean); virtual;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure DoDragDropTreeNode(Destination, Source: TTreeNode; var Accept: Boolean); virtual;
|
|
procedure DoDragDropIsCopy(Destination, Source: TTreeNode; var IsCopy: Boolean); virtual;
|
|
|
|
property Options: TdxTreeViewOptions read FOptions write FOptions
|
|
default [trCanDelete, trConfirmDelete];
|
|
property SelectedIndex: Integer read FSelectedIndex write SetSelectedIndex;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
|
|
function CreateNode: TTreeNode; override;
|
|
procedure SetFocus; override;
|
|
|
|
procedure GetNodeStructure(TreeNode: TTreeNode; List: TList); virtual;
|
|
function IsCustomDraw: Boolean; virtual;
|
|
function MoveTreeNodeStructure(Source, Destination: TTreeNode; IsCopy: Boolean): TTreeNode;
|
|
|
|
property DragSourceTreeNode: TTreeNode read GetDragSourceTreeNode;
|
|
property IsConfirmationAssigned: Boolean read FIsConfirmationAssigned write FIsConfirmationAssigned;
|
|
property OnSetEditText: TTVEditedEvent read FOnSetEditText write FOnSetEditText;
|
|
|
|
property Color;
|
|
property DragCursor;
|
|
property Font;
|
|
property Images;
|
|
property Items;
|
|
property Indent;
|
|
property PopupMenu;
|
|
property ReadOnly;
|
|
property ShowButtons;
|
|
property ShowLines;
|
|
property ShowRoot;
|
|
property SortType;
|
|
property StateImages;
|
|
|
|
property OnClick;
|
|
property OnChanging;
|
|
property OnDblClick;
|
|
property OnGetImageIndex;
|
|
property OnGetSelectedIndex;
|
|
published
|
|
{$IFDEF DELPHI3}
|
|
property ImeMode;
|
|
property ImeName;
|
|
property RightClickSelect;
|
|
{$ENDIF}
|
|
property ShowNodeHint: Boolean read FShowNodeHint write FShowNodeHint;
|
|
property OnCustomDraw: TTreeViewCustomDraw read FOnCustomDraw write FOnCustomDraw;
|
|
property OnDragDropIsCopy: TDragDropIsCopy read FOnDragDropIsCopy write FOnDragDropIsCopy;
|
|
property OnDragDropTreeNode: TDragDropTreeNode read FOnDragDropTreeNode
|
|
write FOnDragDropTreeNode;
|
|
property OnEndDragTreeNode: TEndDragTreeNode read FOnEndDragTreeNode
|
|
write FOnEndDragTreeNode;
|
|
|
|
{$IFDEF DELPHI4}
|
|
property Anchors;
|
|
property AutoExpand;
|
|
property BiDiMode;
|
|
property Constraints;
|
|
property DeletingConfirmationMessage: string read GetDeletingConfirmationMessage write SetDeletingConfirmationMessage stored FIsConfirmationAssigned;
|
|
property DragKind;
|
|
property HotTrack;
|
|
property ParentBiDiMode;
|
|
property RowSelect;
|
|
property ToolTips;
|
|
property OnCustomDrawItem;
|
|
property OnEndDock;
|
|
property OnStartDock;
|
|
{$ENDIF}
|
|
{$IFDEF DELPHI5}
|
|
property OnAdvancedCustomDraw;
|
|
{$ENDIF}
|
|
end;
|
|
|
|
TdxTreeView = class(TCustomdxTreeView)
|
|
published
|
|
property ShowButtons;
|
|
property BorderStyle;
|
|
property DragCursor;
|
|
property ShowLines;
|
|
property ShowRoot;
|
|
property ReadOnly;
|
|
property DragMode;
|
|
property HideSelection;
|
|
property Indent;
|
|
property Items;
|
|
property OnEditing;
|
|
property OnEdited;
|
|
property OnExpanding;
|
|
property OnExpanded;
|
|
property OnCollapsing;
|
|
property OnCompare;
|
|
property OnCollapsed;
|
|
property OnChanging;
|
|
property OnChange;
|
|
property OnDeletion;
|
|
property OnGetImageIndex;
|
|
property OnGetSelectedIndex;
|
|
property Align;
|
|
property Enabled;
|
|
property Font;
|
|
property Color;
|
|
property ParentColor;
|
|
property ParentCtl3D;
|
|
property Ctl3D;
|
|
property Options;
|
|
property SelectedIndex;
|
|
property SortType;
|
|
property TabOrder;
|
|
property TabStop default True;
|
|
property Visible;
|
|
property OnClick;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnDragDrop;
|
|
property OnDragOver;
|
|
property OnStartDrag;
|
|
property OnEndDrag;
|
|
property OnMouseDown;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnDblClick;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property PopupMenu;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property ShowHint;
|
|
property Images;
|
|
property StateImages;
|
|
end;
|
|
|
|
resourcestring
|
|
dxTreeViewDelConfirm = 'Do you want to delete the item "%s"';
|
|
dxDBTreeViewSmartLoadS = 'Set trSmartRecordLoad in the Options property to decrease the loading time. Do you want to do it now?';
|
|
|
|
implementation
|
|
|
|
uses ImgList ;
|
|
|
|
{$I dxcmctl.inc}
|
|
{$R dxtree.res}
|
|
|
|
const
|
|
crdxTreeDrag = -1011;
|
|
|
|
var
|
|
{$IFDEF DELPHI4}
|
|
dxTreeViewDragImages: TDragImageList;
|
|
{$ELSE}
|
|
dxTreeViewDragImages: TCustomImageList;
|
|
{$ENDIF}
|
|
DropSourceTreeNode: TTreeNode;
|
|
OldDragOverTreeNode: TTreeNode;
|
|
|
|
type
|
|
TDummyControl = class(TWinControl)
|
|
public
|
|
function GetDragImages: {$IFDEF DELPHI4}TDragImageList{$ELSE}TCustomImageList{$ENDIF}; override;
|
|
end;
|
|
|
|
function TDummyControl.GetDragImages: {$IFDEF DELPHI4}TDragImageList{$ELSE}TCustomImageList{$ENDIF};
|
|
begin
|
|
Result := inherited GetDragImages;
|
|
end;
|
|
|
|
{TdxTreeNode}
|
|
{$IFDEF DELPHI4}
|
|
//Avoid MoveTo bug in D4.
|
|
procedure TdxTreeNode.MoveTo(Destination: TTreeNode; Mode: TNodeAttachMode);
|
|
var
|
|
Dummy: TTreeNode;
|
|
begin
|
|
if Mode in [naAddChild, naAddChildFirst] then
|
|
begin
|
|
TCustomdxTreeView(TreeView).CopyTreeNodeStructFlag := True;
|
|
if Mode = naAddChildFirst then
|
|
Dummy := TTreeView(Destination.TreeView).Items.AddChildFirst(Destination, '')
|
|
else
|
|
Dummy := TTreeView(Destination.TreeView).Items.AddChild(Destination, '');
|
|
TCustomdxTreeView(TreeView).CopyTreeNodeStructFlag := False;
|
|
inherited MoveTo(Dummy, naInsert);
|
|
TCustomdxTreeView(TreeView).CopyTreeNodeStructFlag := True;
|
|
Dummy.Free;
|
|
TCustomdxTreeView(TreeView).CopyTreeNodeStructFlag := False;
|
|
end
|
|
else
|
|
inherited MoveTo(Destination, Mode);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
{TCustomdxTreeView}
|
|
constructor TCustomdxTreeView.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FScrollTimerID := -1;
|
|
FSelectedIndex := -1;
|
|
FOptions := [trCanDelete, trConfirmDelete];
|
|
FDragDropProcessingFlag := False;
|
|
fntcd := TFont.Create;
|
|
FCanvas := TControlCanvas.Create;
|
|
FShowNodeHint := True;
|
|
end;
|
|
|
|
destructor TCustomdxTreeView.Destroy;
|
|
begin
|
|
fntcd.Free;
|
|
FCanvas.Free;
|
|
inherited;
|
|
end;
|
|
|
|
type
|
|
TtmpDragObject = class(TDragControlObject)
|
|
protected
|
|
function GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor; override;
|
|
end;
|
|
|
|
function TtmpDragObject.GetDragCursor(Accepted: Boolean; X, Y: Integer): TCursor;
|
|
begin
|
|
if not Accepted then
|
|
Result := crNoDrop
|
|
else
|
|
if not (GetKeyState(VK_CONTROL) < 0) then
|
|
Result := TCustomdxTreeView(Control).DragCursor
|
|
else
|
|
Result := crdxTreeDrag;
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.DoStartDrag(var DragObject: TDragObject);
|
|
begin
|
|
DragObject := TtmpDragObject.Create(Self);
|
|
FInternalDragObject := DragObject;
|
|
inherited;
|
|
dxTreeViewDragImages := GetDragImages;
|
|
if Self.Focused then
|
|
DropSourceTreeNode := Selected
|
|
else
|
|
DropSourceTreeNode := nil;
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.DoEndDrag(Target: TObject; X, Y: Integer);
|
|
begin
|
|
inherited DoEndDrag(Target, X, Y);
|
|
FInternalDragObject.Free;
|
|
DropSourceTreeNode := nil;
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.DoDragDropTreeNode(Destination, Source: TTreeNode;
|
|
var Accept: Boolean);
|
|
begin
|
|
if Assigned(FOnDragDropTreeNode) then
|
|
FOnDragDropTreeNode(Destination, Source, Accept);
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.DoDragDropIsCopy(Destination, Source: TTreeNode; var IsCopy: Boolean);
|
|
begin
|
|
if Assigned(FOnDragDropIsCopy) then
|
|
FOnDragDropIsCopy(Destination, Source, IsCopy);
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.GetNodeStructure(TreeNode: TTreeNode; List: TList);
|
|
|
|
procedure GetNodeStructure_(TreeNode: TTreeNode; List: TList);
|
|
var
|
|
tn: TTreeNode;
|
|
begin
|
|
if (TreeNode <> nil) and TreeNode.HasChildren then
|
|
begin
|
|
tn := TreeNode.GetFirstChild;
|
|
while tn <> nil do
|
|
begin
|
|
List.Add(tn);
|
|
if tn.HasChildren then
|
|
GetNodeStructure_(tn, List);
|
|
tn := TreeNode.GetNextChild (tn);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
List.Add(TreeNode);
|
|
GetNodeStructure_(TreeNode, List);
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.InsertTreeNodeStructure(ListS, ListD: TList; Flag: Boolean);
|
|
begin
|
|
end;
|
|
|
|
function TCustomdxTreeView.GetDragSourceTreeNode: TTreeNode;
|
|
begin
|
|
if (DropSourceTreeNode <> nil) and (DropSourceTreeNode.TreeView = Self) then
|
|
Result := DropSourceTreeNode
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TCustomdxTreeView.GetDeletingConfirmationMessage: string;
|
|
begin
|
|
Result := FDeletingConfirmationMessage;
|
|
if not FIsConfirmationAssigned then
|
|
Result := dxTreeViewDelConfirm;
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.SetSelectedIndex(Value: Integer);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Value <> FSelectedIndex then
|
|
begin
|
|
FSelectedIndex := Value;
|
|
for i := 0 to Items.Count - 1 do
|
|
Items[i].SelectedIndex := FSelectedIndex;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.SetDeletingConfirmationMessage(const AValue: string);
|
|
begin
|
|
FDeletingConfirmationMessage := AValue;
|
|
IsConfirmationAssigned := True;
|
|
end;
|
|
|
|
function TCustomdxTreeView.CreateNode: TTreeNode;
|
|
begin
|
|
Result := TdxTreeNode.Create(Items);
|
|
if (Result <> nil) and (FSelectedIndex <> -1) then
|
|
Result.SelectedIndex := FSelectedIndex
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.ReadIsAssigned(AReader: TReader);
|
|
begin
|
|
FIsConfirmationAssigned := AReader.ReadBoolean;
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.WriteIsAssigned(AWriter: TWriter);
|
|
begin
|
|
AWriter.WriteBoolean(FIsConfirmationAssigned);
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.SetFocus;
|
|
begin
|
|
if (GetParentForm(Self) <> nil) or (ParentWindow <> 0) then
|
|
inherited SetFocus;
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.KeyDown(var Key: Word; Shift: TShiftState);
|
|
var
|
|
St: string;
|
|
begin
|
|
if (Key = VK_DELETE) and (trCanDelete in Options)
|
|
and not ReadOnly and (Selected <> nil) and not IsEditing then
|
|
begin
|
|
if IsConfirmationAssigned then
|
|
St := Format(DeletingConfirmationMessage, [Selected.Text])
|
|
else
|
|
St := Format(dxTreeViewDelConfirm, [Selected.Text]);
|
|
if not (trConfirmDelete in Options) or
|
|
(MessageDlg(St, mtConfirmation, mbOKCancel, 0) <> idCancel) then
|
|
Items.Delete(Selected);
|
|
end;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.CMDrag(var Message: TCMDrag);
|
|
var
|
|
lpht: TTVHitTestInfo;
|
|
TreeNode: TTreeNode;
|
|
|
|
procedure HideDragImage;
|
|
begin
|
|
if dxTreeViewDragImages <> nil then
|
|
dxTreeViewDragImages.HideDragImage
|
|
else
|
|
if FDragObject <> nil then
|
|
FDragObject.HideDragImage;
|
|
end;
|
|
|
|
procedure ShowDragImage;
|
|
begin
|
|
if dxTreeViewDragImages <> nil then
|
|
dxTreeViewDragImages.ShowDragImage
|
|
else
|
|
if FDragObject <> nil then
|
|
FDragObject.ShowDragImage;
|
|
end;
|
|
|
|
function IsNodeVisible(TreeNode: TTreeNode): Boolean;
|
|
var
|
|
Rect: TRect;
|
|
begin
|
|
Result := TreeView_GetItemRect(Handle, TreeNode.ItemId, Rect, False);
|
|
Result := Result and (Rect.Top < ClientHeight);
|
|
end;
|
|
|
|
var
|
|
CorrectDragFlag, IsCopyFlag: Boolean;
|
|
begin
|
|
CorrectDragFlag := False;
|
|
with Message, DragRec^ do
|
|
begin
|
|
case DragMessage of
|
|
dmDragEnter:
|
|
begin
|
|
FDragDropProcessingFlag := True;
|
|
OldDragOverTreeNode := nil;
|
|
FDragObject := Source;
|
|
end;
|
|
dmDragMove:
|
|
begin
|
|
lpht.pt := ScreenToClient(Point(Pos.X, Pos.Y));
|
|
lpht.flags := TVHT_ONITEM;
|
|
TreeNode := Items.GetNode(TreeView_HitTest(Handle, lpht));
|
|
|
|
if TreeNode <> nil then
|
|
begin
|
|
if (OldDragOverTreeNode <> nil) and (OldDragOverTreeNode = TreeNode) then
|
|
begin
|
|
if (TreeNode = TopItem) or
|
|
((TreeNode.GetPrevVisible <> nil) and (TreeNode.GetPrevVisible = TopItem))
|
|
and (TopItem.GetPrevVisible <> nil) then
|
|
TopItem := TopItem.GetPrevVisible
|
|
else
|
|
if ((TreeNode.GetNextVisible <> nil) and not IsNodeVisible(TreeNode.GetNextVisible)
|
|
or ((TreeNode.GetNextVisible <> nil) and (TreeNode.GetNextVisible.GetNextVisible <> nil)
|
|
and not IsNodeVisible(TreeNode.GetNextVisible.GetNextVisible))) then
|
|
TopItem := TopItem.GetNextVisible;
|
|
end;
|
|
if OldDragOverTreeNode <> TreeNode then
|
|
begin
|
|
OldDragOverTreeNode := TreeNode;
|
|
HideDragImage;
|
|
TreeView_SelectDropTarget(Handle, OldDragOverTreeNode.ItemId);
|
|
ShowDragImage;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
OldDragOverTreeNode := nil;
|
|
HideDragImage;
|
|
TreeView_SelectDropTarget(Handle, nil);
|
|
ShowDragImage;
|
|
end;
|
|
end;
|
|
dmDragLeave:
|
|
begin
|
|
if DropSourceTreeNode <> nil then
|
|
begin
|
|
HideDragImage;
|
|
TreeView_SelectDropTarget(Handle, nil);
|
|
DropSourceTreeNode.Selected := True;
|
|
ShowDragImage;
|
|
end;
|
|
FDragObject := nil;
|
|
end;
|
|
dmDragCancel:
|
|
begin
|
|
FDragObject := nil;
|
|
FDragDropProcessingFlag := False;
|
|
OldDragOverTreeNode := nil;
|
|
Invalidate;
|
|
end;
|
|
dmDragDrop:
|
|
begin
|
|
FDragObject := nil;
|
|
IsCopyFlag := GetKeyState(VK_CONTROL) < 0;
|
|
if OldDragOverTreeNode <> nil then
|
|
begin
|
|
TreeView_SelectDropTarget(Handle, nil);
|
|
OldDragOverTreeNode.Selected := True;
|
|
Invalidate;
|
|
if (DropSourceTreeNode <> nil) and not OldDragOverTreeNode.HasAsParent(DropSourceTreeNode)
|
|
and (OldDragOverTreeNode <> DropSourceTreeNode) then
|
|
begin
|
|
DoDragDropIsCopy(DropSourceTreeNode, OldDragOverTreeNode, IsCopyFlag);
|
|
if ((OldDragOverTreeNode <> DropSourceTreeNode.Parent)
|
|
or IsCopyFlag or Assigned(FOnEndDragTreeNode)) then
|
|
begin
|
|
CorrectDragFlag := True;
|
|
DoDragDropTreeNode(OldDragOverTreeNode, DropSourceTreeNode, CorrectDragFlag);
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
if DropSourceTreeNode <> nil then
|
|
begin
|
|
DoDragDropIsCopy(DropSourceTreeNode, OldDragOverTreeNode, IsCopyFlag);
|
|
DoDragDropTreeNode(OldDragOverTreeNode, DropSourceTreeNode, CorrectDragFlag);
|
|
end;
|
|
if CorrectDragFlag then
|
|
begin
|
|
TreeNode := MoveTreeNodeStructure(DropSourceTreeNode, OldDragOverTreeNode, IsCopyFlag);
|
|
if TreeNode <> nil then
|
|
begin
|
|
TreeNode.MakeVisible;
|
|
Selected := TreeNode;
|
|
end;
|
|
Message.DragMessage := dmDragDrop;
|
|
DropTarget := OldDragOverTreeNode;
|
|
end;
|
|
FDragDropProcessingFlag := False;
|
|
OldDragOverTreeNode := nil;
|
|
Invalidate;
|
|
end; // dmDragDrop:
|
|
end; // case
|
|
end; // with
|
|
|
|
if (DropSourceTreeNode <> nil) and (Message.DragMessage <> dmDragDrop)
|
|
and (Message.DragMessage <> dmDragCancel)
|
|
and (OldDragOverTreeNode <> DropSourceTreeNode) then
|
|
begin
|
|
if OldDragOverTreeNode <> nil then
|
|
begin
|
|
CorrectDragFlag := (not DropSourceTreeNode.HasChildren
|
|
or not OldDragOverTreeNode.HasAsParent(DropSourceTreeNode))
|
|
and not Assigned(OnDragOver);
|
|
if CorrectDragFlag then
|
|
DoDragDropTreeNode(OldDragOverTreeNode, DropSourceTreeNode, CorrectDragFlag);
|
|
end
|
|
else
|
|
DoDragDropTreeNode(OldDragOverTreeNode, DropSourceTreeNode, CorrectDragFlag);
|
|
end;
|
|
|
|
inherited;
|
|
|
|
if (Message.DragMessage = dmDragDrop) or (Message.DragMessage = dmDragCancel) then
|
|
begin
|
|
DropSourceTreeNode := nil;
|
|
dxTreeViewDragImages := nil;
|
|
DropTarget := nil;
|
|
end;
|
|
|
|
if ((Message.DragMessage = dmDragMove) or (Message.DragMessage = dmDragLeave))
|
|
and CorrectDragFlag and (Message.Result = 0) then
|
|
Message.Result := 1;
|
|
end;
|
|
|
|
function TCustomdxTreeView.MoveTreeNodeStructure(Source, Destination: TTreeNode; IsCopy: Boolean): TTreeNode;
|
|
var
|
|
i, ind: Integer;
|
|
ListS, ListD: TList;
|
|
tr: TTreeNode;
|
|
AStyle: TNodeAttachMode;
|
|
begin
|
|
Result := nil;
|
|
ListS := TList.Create;
|
|
ListD := TList.Create;
|
|
CopyTreeNodeStructFlag := IsCopy or (Self <> Source.TreeView);
|
|
GetNodeStructure(Source, ListS);
|
|
CopyTreeNodeStructFlag := False;
|
|
if Destination <> nil then
|
|
AStyle := naAddChild
|
|
else
|
|
AStyle := naAdd;
|
|
|
|
if Assigned(FOnEndDragTreeNode) then
|
|
FOnEndDragTreeNode(Destination, Source, AStyle);
|
|
|
|
if (AStyle = naAddChild) or (AStyle = naAddChildFirst) then
|
|
Destination.HasChildren := True;
|
|
if (Self <> Source.TreeView) or IsCopy then
|
|
begin
|
|
CopyTreeNodeStructFlag := True;
|
|
tr := nil;
|
|
for i := 0 to ListS.Count - 1 do
|
|
begin
|
|
if i = 0 then
|
|
case AStyle of
|
|
naAdd: tr := Items.Add(Destination, GetListItemText(TTreeNode(ListS.List[i])));
|
|
naAddFirst: tr := Items.AddFirst(Destination, GetListItemText(TTreeNode(ListS.List[i])));
|
|
naAddChild: tr := Items.AddChild(Destination, GetListItemText(TTreeNode(ListS.List[i])));
|
|
naAddChildFirst: tr := Items.AddChildFirst(Destination, GetListItemText(TTreeNode(ListS.List[i])));
|
|
naInsert: tr := Items.Insert(Destination, GetListItemText(TTreeNode(ListS.List[i])));
|
|
end
|
|
else
|
|
begin
|
|
ind := ListS.IndexOf(TTreeNode(ListS.List[i]).Parent);
|
|
tr := Items.AddChild(TTreeNode(ListD.List[ind]), GetListItemText(TTreeNode(ListS.List[i])))
|
|
end;
|
|
if tr <> nil then
|
|
ListD.Add(tr);
|
|
end;
|
|
InsertTreeNodeStructure(ListS, ListD, True);
|
|
CopyTreeNodeStructFlag := False;
|
|
if ListD.Count > 0 then
|
|
begin
|
|
Result := TTreeNode(ListD[0]);
|
|
Destination.HasChildren := True;
|
|
end;
|
|
end;
|
|
if (Self = Source.TreeView) and not IsCopy then
|
|
begin
|
|
CopyTreeNodeStructFlag := True;
|
|
Source.MoveTo(Destination, AStyle);
|
|
CopyTreeNodeStructFlag := False;
|
|
Result := Source;
|
|
end;
|
|
ListS.Free;
|
|
ListD.Free;
|
|
if (Source <> nil) and not TdxTreeView(Source.TreeView).ReadOnly
|
|
and (Self <> Source.TreeView) and not IsCopy then
|
|
Source.Free;
|
|
end;
|
|
|
|
function TCustomdxTreeView.GetNodeFromItem(const Item: TTVItem): TTreeNode;
|
|
begin
|
|
with Item do
|
|
if (state and TVIF_PARAM) <> 0 then
|
|
begin
|
|
Result := TTreeNode(lParam);
|
|
end else Result := Items.GetNode(hItem);
|
|
end;
|
|
|
|
function TCustomdxTreeView.GetListItemText(TreeNode: TTreeNode): String;
|
|
begin
|
|
if TreeNode <> nil then
|
|
Result := TreeNode.Text;
|
|
end;
|
|
|
|
function TCustomdxTreeView.IsCustomDraw: Boolean;
|
|
begin
|
|
Result := Assigned(FOnCustomDraw);
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.DefineProperties(AFiler: TFiler);
|
|
begin
|
|
inherited DefineProperties(AFiler);
|
|
AFiler.DefineProperty('IsConfirmationAssigned', ReadIsAssigned,
|
|
WriteIsAssigned, IsConfirmationAssigned);
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.DoCustomDraw(TreeNode: TTreeNode; AFont: TFont;
|
|
var AColor, ABkColor: TColor);
|
|
begin
|
|
if Assigned(FOnCustomDraw) then
|
|
FOnCustomDraw(Self, TreeNode, AFont, AColor, ABkColor);
|
|
end;
|
|
|
|
function TCustomdxTreeView.DoCNNotify(var Message: TWMNotify): Boolean;
|
|
var
|
|
pnmlv: PNMTVCustomDraw;
|
|
tr: TTreeNode;
|
|
htr: HTReeItem;
|
|
Color, BkColor: TColor;
|
|
St: String;
|
|
begin
|
|
if (Message.nmhdr^.code = NM_CUSTOMDRAW) {$IFDEF DELPHI5}and not (Assigned(OnAdvancedCustomDraw)
|
|
or Assigned(OnAdvancedCustomDrawItem)){$ENDIF} then
|
|
begin
|
|
Result := False;
|
|
pnmlv := PNMTVCustomDraw(TMessage(Message).lParam);
|
|
if pnmlv^.nmcd.dwDrawStage = CDDS_PREPAINT then
|
|
begin
|
|
if IsCustomDraw then
|
|
Message.Result := CDRF_NOTIFYITEMDRAW
|
|
else
|
|
Message.Result := CDRF_DODEFAULT;
|
|
end;
|
|
if pnmlv^.nmcd.dwDrawStage = CDDS_ITEMPREPAINT then
|
|
begin
|
|
htr := Pointer(pnmlv^.nmcd.dwItemSpec);
|
|
tr := Items.GetNode(htr);
|
|
fntcd.Assign(Font);
|
|
Color := Font.Color;
|
|
BkColor := clWindow;
|
|
DoCustomDraw( tr, fntcd, Color, BkColor);
|
|
if ((pnmlv^.nmcd.uItemState and TVGN_CARET = 0)
|
|
and (pnmlv^.nmcd.uItemState and TVGN_DROPHILITE = 0)
|
|
and (OldDragOverTreeNode <> tr)) or not Focused then
|
|
begin
|
|
pnmlv^.clrText := ColorToRGB(Color);
|
|
pnmlv^.clrTextBk := ColorToRGB(bkColor);
|
|
end;
|
|
|
|
SelectObject(pnmlv^.nmcd.hdc, fntcd.Handle);
|
|
Message.Result := CDRF_NEWFONT;
|
|
end;
|
|
end
|
|
else Result := True;
|
|
|
|
with Message.NMHdr^ do
|
|
if code = TVN_BEGINLABELEDIT then
|
|
begin
|
|
SetImeMode(TreeView_GetEditControl(handle), ImeMode);
|
|
if Assigned(FOnSetEditText) then
|
|
with PTVDispInfo(Pointer(Message.NMHdr))^ do
|
|
begin
|
|
tr := GetNodeFromItem(item);
|
|
St := tr.Text;
|
|
FOnSetEditText(Self, tr, St);
|
|
SendMessage(TreeView_GetEditControl(handle), WM_SETTEXT, 0, Integer(PChar(St)));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.CNNotify(var Message: TWMNotify);
|
|
begin
|
|
if DoCNNotify(Message) then
|
|
inherited;
|
|
end;
|
|
|
|
type
|
|
PAToolTipText = ^TAToolTipText;
|
|
TAToolTipText = packed record
|
|
hdr: TNMHDR;
|
|
lpszText: PAnsiChar;
|
|
szText: array[0..79] of {$IFNDEF DELPHI12}Char {$ELSE} AnsiChar{$ENDIF};
|
|
hinst: THandle;
|
|
uFlags: UINT;
|
|
end;
|
|
|
|
function TCustomdxTreeView.DoWMNotify(var Message: TWMNotify): Boolean;
|
|
begin
|
|
if ((Message.nmhdr^.code = TTN_NEEDTEXTA) or (Message.nmhdr^.code = TTN_NEEDTEXTW))
|
|
and not FShowNodeHint then
|
|
begin
|
|
PAToolTipText(TMessage(Message).lparam).lpszText := {$IFDEF DELPHI12}PAnsiChar{$ELSE}PChar{$ENDIF}('');
|
|
TMessage(Message).Result := 0;
|
|
Result := False;
|
|
end else Result := True;
|
|
end;
|
|
|
|
procedure TCustomdxTreeView.WMNotify(var Message: TWMNotify);
|
|
begin
|
|
if DoWMNotify(Message) then
|
|
inherited;
|
|
end;
|
|
|
|
initialization
|
|
OldDragOverTreeNode := nil;
|
|
dxTreeViewDragImages := nil;
|
|
Screen.Cursors[crdxTreeDrag] := LoadCursor(HInstance, 'DXTREEDRAGCOPY');
|
|
|
|
end.
|
|
|