Componentes.Terceros.DevExp.../internal/x.42/2/ExpressPrinting System/Sources/dxPSXplorerTreeView.pas

1349 lines
41 KiB
ObjectPascal

{*******************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressPrinting System(tm) COMPONENT SUITE }
{ }
{ 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 EXPRESSPRINTINGSYSTEM 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. }
{ }
{*******************************************************************}
unit dxPSXplorerTreeView;
interface
{$I cxVer.inc}
uses
Windows, Classes, Messages, CommCtrl, Graphics, Controls, ExtCtrls, ComCtrls,
Forms, dxPSCore;
type
TCustomTreeViewClass = class of TCustomTreeView;
TCustomdxPSExplorerTreeViewContainer = class(TCustomdxPSExplorerTreeContainer)
private
FFocusedNode: TTreeNode;
FStorageStream: TMemoryStream;
function GetRootNode: TTreeNode;
function GetTreeView: TCustomTreeView;
procedure TreeCancelEdit(Sender: TObject; ANode: TTreeNode);
procedure TreeChanged(Sender: TObject; ANode: TTreeNode);
procedure TreeCollapsing(Sender: TObject; Node: TTreeNode; var AllowCollapse: Boolean);
procedure TreeCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
State: TCustomDrawState; var DefaultDraw: Boolean);
procedure TreeDblClick(Sender: TObject);
procedure TreeDragDrop(Sender, Source: TObject; X, Y: Integer);
procedure TreeDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
procedure TreeEdited(Sender: TObject; Node: TTreeNode; var S: string);
procedure TreeEditing(Sender: TObject; Node: TTreeNode; var AllowEdit: Boolean);
procedure TreeExpanding(Sender: TObject; Node: TTreeNode; var AllowExpansion: Boolean);
procedure TreeKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure TreeKeyPress(Sender: TObject; var Key: Char);
procedure TreeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure ReadTreeViewState;
procedure WriteTreeViewState;
protected
procedure AddItem(AParent: TdxPSExplorerFolder; AnItem: TCustomdxPSExplorerItem); override;
procedure Clear; override;
procedure DeleteItem(AnItem: TCustomdxPSExplorerItem); override;
procedure InvalidateItem(AnItem: TCustomdxPSExplorerItem); override;
procedure MoveItem(AnItem: TCustomdxPSExplorerItem); override;
procedure RenameItem(AnItem: TCustomdxPSExplorerItem); override;
function GetCreationParent: TdxPSExplorerFolder; override;
function GetFocusedItem: TCustomdxPSExplorerItem; override;
function GetIsEditing: Boolean; override;
function GetIsFolderSelected: Boolean; override;
function GetIsItemSelected: Boolean; override;
function GetIsRootSelected: Boolean; override;
function GetSelectedFolder: TdxPSExplorerFolder; override;
function GetSelectedItem: TCustomdxPSExplorerItem; override;
function GetSelectedItemText: string; override;
procedure SetFocusedItem(Value: TCustomdxPSExplorerItem); override;
procedure SetSelectedItem(Value: TCustomdxPSExplorerItem); override;
procedure SetSelectedItemText(const Value: string); override;
procedure RestoreState; override;
procedure SaveState; override;
procedure InitializeTreeContainer; override;
function AddNode(AParent: TTreeNode; AnItem: TCustomdxPSExplorerItem): TTreeNode; virtual;
function CanDragNode(ANode: TTreeNode): Boolean; virtual;
function GetHitTestInfoAt(X, Y: Integer): THitTests;
function GetItemByNode(ANode: TTreeNode): TCustomdxPSExplorerItem;
function GetNodeByItem(AnItem: TCustomdxPSExplorerItem): TTreeNode;
property FocusedNode: TTreeNode read FFocusedNode;
property RootNode: TTreeNode read GetRootNode;
property TreeView: TCustomTreeView read GetTreeView;
public
function BeginEdit(AnImmediate: Boolean = True): Boolean; override;
procedure EndEdit(ACancel: Boolean); override;
class function ControlClass: TWinControlClass; override;
class function TreeViewClass: TCustomTreeViewClass; virtual;
procedure CollapseItem(AnItem: TCustomdxPSExplorerItem; ARecursive: Boolean = False); override;
procedure ExpandItem(AnItem: TCustomdxPSExplorerItem; ARecursive: Boolean = False); override;
procedure MakeItemVisible(AnItem: TCustomdxPSExplorerItem); override;
procedure BeginUpdate; override;
procedure EndUpdate; override;
procedure RefreshSorting(ANode: TObject); override;
procedure RefreshSorting(AFolder: TdxPSExplorerFolder); override;
function GetDropTarget(X, Y: Integer): TdxPSExplorerFolder; override;
function GetItemAt(X, Y: Integer): TCustomdxPSExplorerItem; override;
function GetItemAtMousePos: TCustomdxPSExplorerItem;
end;
{$IFDEF DELPHI5}
{$IFNDEF DELPHI6}
{$DEFINE WMCONTEXTMENU}
{$ENDIF}
{$ENDIF}
TdxPSExplorerTreeViewScrollArea = (etsaLeft, etsaTop, etsaRight, etsaBottom);
TdxPSExplorerTreeViewScrollAreas = set of TdxPSExplorerTreeViewScrollArea;
TdxPSExplorerTreeView = class(TTreeView)
private
FContainer: TCustomdxPSExplorerTreeViewContainer;
FDragImage: TDragImageList;
FExpandTimer: TTimer;
FFlat: Boolean;
FSavedDropTarget: TTreeNode;
FSavedScrollActiveAreas: TdxPSExplorerTreeViewScrollAreas;
FScrollTimer: TTimer;
{$IFNDEF DELPHI6}
FOnCancelEdit: TTVChangedEvent;
{$ENDIF}
function GetIsMouseInScrollArea: Boolean;
function GetIsMouseInScrollAreaBound(ScrollArea: TdxPSExplorerTreeViewScrollArea): Boolean;
function GetScrollActiveAreas: TdxPSExplorerTreeViewScrollAreas;
function GetScrollAreaBounds(ScrollArea: TdxPSExplorerTreeViewScrollArea): TRect;
procedure SetFlat(Value: Boolean);
procedure OnExpandTimer(Sender: TObject);
procedure OnScrollTimer(Sender: TObject);
{$IFDEF WMCONTEXTMENU}
procedure WMContextMenu(var Message: TWMContextMenu); message WM_CONTEXTMENU;
{$ENDIF}
procedure WMNCPaint(var Message: TWMNCPaint); message WM_NCPAINT;
procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW;
protected
function CanCollapse(Node: TTreeNode): Boolean; override;
function CanEdit(Node: TTreeNode): Boolean; override;
function CanExpand(Node: TTreeNode): Boolean; override;
procedure Change(Node: TTreeNode); override;
procedure CreateParams(var Params: TCreateParams); override;
procedure DblClick; override;
procedure DoEndDrag(Target: TObject; X, Y: Integer); override;
procedure DoStartDrag(var DragObject: TDragObject); override;
procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); override;
{$IFNDEF DELPHI6}
procedure Edit(const Item: TTVItem); override;
{$ENDIF}
{$IFNDEF DELPHI12}
function GetDragImages: TDragImageList; override;
{$ENDIF}
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure KeyPress(var Key: Char); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure WndProc(var Message: TMessage); override;
function CanDragNode(ANode: TTreeNode): Boolean; virtual;
procedure DrawFlatEdge; virtual;
function GetInfoTip(AnItem: HTREEITEM): string;
function MakeDragBitmap(ANode: TTreeNode): Graphics.TBitmap; virtual;
procedure UpdateDragMode(ANode: TTreeNode);
property Container: TCustomdxPSExplorerTreeViewContainer read FContainer write FContainer;
property IsMouseInScrollArea: Boolean read GetIsMouseInScrollArea;
property IsMouseInScrollAreaBounds[ScrollArea: TdxPSExplorerTreeViewScrollArea]: Boolean read GetIsMouseInScrollAreaBound;
property ScrollActiveAreas: TdxPSExplorerTreeViewScrollAreas read GetScrollActiveAreas;
property ScrollAreaBounds[ScrollArea: TdxPSExplorerTreeViewScrollArea]: TRect read GetScrollAreaBounds;
public
constructor Create(AOwner: TComponent); override;
constructor CreateEx(AOwner: TComponent; AContainer: TCustomdxPSExplorerTreeViewContainer); virtual;
procedure DragDrop(Source: TObject; X, Y: Integer); override;
{$IFDEF DELPHI12}
function GetDragImages: TDragImageList; override;
{$ENDIF}
property Flat: Boolean read FFlat write SetFlat;
property OnCancelEdit{$IFNDEF DELPHI6} : TTVChangedEvent read FOnCancelEdit write FOnCancelEdit{$ENDIF};
end;
TdxPSExplorerTreeViewContainer = class(TCustomdxPSExplorerTreeViewContainer)
private
function GetTreeView: TdxPSExplorerTreeView;
protected
procedure InitializeTreeContainer; override;
public
class function TreeViewClass: TCustomTreeViewClass; override;
property TreeView: TdxPSExplorerTreeView read GetTreeView;
end;
implementation
uses
SysUtils, cxClasses, dxPSUtl, dxPSGlbl, dxCore;
const
ScrollAreaHeight = 30;
ScrollAreaWidth = 30;
type
TCustomTreeViewAccess = class(TCustomTreeView);
{ TreeView Helpers }
function TreeView_GetItems(AControl: TCustomTreeView): TTreeNodes;
begin
Result := TCustomTreeViewAccess(AControl).Items;
end;
{ TCustomdxPSExplorerTreeViewContainer }
function TCustomdxPSExplorerTreeViewContainer.BeginEdit(AnImmediate: Boolean = True): Boolean;
var
SelectedNode: TTreeNode;
begin
Result := CanRenameSelectedItem;
if Result then
begin
SelectedNode := TreeView.Selected;
if AnImmediate then
Result := SelectedNode.EditText
else
Result := PostMessage(TreeView.Handle, TVM_EDITLABEL, 0, lParam(SelectedNode.ItemId));
Host.UpdateState;
end;
end;
procedure TCustomdxPSExplorerTreeViewContainer.EndEdit(ACancel: Boolean);
var
Node: TTreeNode;
begin
if TreeView.IsEditing then
begin
Node := TreeView.Selected;
if Node <> nil then Node.EndEdit(ACancel);
end;
end;
procedure TCustomdxPSExplorerTreeViewContainer.CollapseItem(AnItem: TCustomdxPSExplorerItem;
ARecursive: Boolean = False);
var
Node: TTreeNode;
begin
Node := GetNodeByItem(AnItem);
if Node <> nil then Node.Collapse(ARecursive);
end;
procedure TCustomdxPSExplorerTreeViewContainer.ExpandItem(AnItem: TCustomdxPSExplorerItem;
ARecursive: Boolean = False);
var
Node: TTreeNode;
begin
Node := GetNodeByItem(AnItem);
if Node <> nil then
begin
dxPSCore.dxPSStartWait;
try
Node.Expand(ARecursive);
finally
dxPSCore.dxPSStopWait;
end;
end;
end;
procedure TCustomdxPSExplorerTreeViewContainer.MakeItemVisible(AnItem: TCustomdxPSExplorerItem);
var
Node: TTreeNode;
begin
Node := GetNodeByItem(AnItem);
if Node <> nil then
begin
Node.MakeVisible;
Node.Focused := True;
Node.Selected := True;
end;
end;
procedure TCustomdxPSExplorerTreeViewContainer.BeginUpdate;
begin
inherited;
TreeView_GetItems(TreeView).BeginUpdate;
end;
procedure TCustomdxPSExplorerTreeViewContainer.EndUpdate;
begin
TreeView_GetItems(TreeView).EndUpdate;
inherited;
end;
function TreeSortFunc(lParam1, lParam2, lParamSort: Longint): Integer; stdcall;
begin
if lParam2 <> 0 then
Result := TCustomdxPSExplorerItemComparator.CompareItems(TTreeNode(lParam1).Data, TTreeNode(lParam2).Data)
else
Result := 0;
end;
procedure TCustomdxPSExplorerTreeViewContainer.RefreshSorting(ANode: TObject);
begin
if Explorer.State * [esLoading{, esRefreshing}] = [] then
if ANode <> nil then
TTreeNode(ANode).CustomSort(TreeSortFunc, (0) {$IFDEF DELPHI6}, False{$ENDIF})
else
TreeView.CustomSort(TreeSortFunc, (0) {$IFDEF DELPHI6}, True{$ENDIF})
end;
procedure TCustomdxPSExplorerTreeViewContainer.RefreshSorting(AFolder: TdxPSExplorerFolder);
var
Node: TObject;
begin
if (AFolder = nil) or AFolder.IsRoot then
Node := nil
else
Node := GetNodeByItem(AFolder);
RefreshSorting(Node);
end;
class function TCustomdxPSExplorerTreeViewContainer.ControlClass: TWinControlClass;
begin
Result := TreeViewClass;
end;
class function TCustomdxPSExplorerTreeViewContainer.TreeViewClass: TCustomTreeViewClass;
begin
Result := TCustomTreeView;
end;
function TCustomdxPSExplorerTreeViewContainer.GetItemAt(X, Y: Integer): TCustomdxPSExplorerItem;
begin
Result := GetItemByNode(TreeView.GetNodeAt(X, Y))
end;
function TCustomdxPSExplorerTreeViewContainer.GetItemAtMousePos: TCustomdxPSExplorerItem;
begin
with Control.ScreenToClient(Mouse.CursorPos) do
Result := GetItemAt(X, Y);
end;
function TCustomdxPSExplorerTreeViewContainer.GetDropTarget(X, Y: Integer): TdxPSExplorerFolder;
var
Item: TCustomdxPSExplorerItem;
begin
if TreeView.DropTarget <> nil then
if [ComCtrls.htBelow, ComCtrls.htNowhere] * GetHitTestInfoAt(X, Y) = [] then
begin
Item := GetItemByNode(TreeView.DropTarget);
if Item is TdxPSExplorerFolder then
Result := TdxPSExplorerFolder(Item)
else
Result := nil;
end
else
Result := Explorer.Root
else
Result := Explorer.Root;
end;
procedure TCustomdxPSExplorerTreeViewContainer.AddItem(AParent: TdxPSExplorerFolder;
AnItem: TCustomdxPSExplorerItem);
var
Node: TTreeNode;
begin
Node := AddNode(GetNodeByItem(AParent), AnItem);
if AnItem is TdxPSExplorerFolder then
Node.HasChildren := TdxPSExplorerFolderHelper.GetHasChildren(TdxPSExplorerFolder(AnItem));
end;
procedure TCustomdxPSExplorerTreeViewContainer.Clear;
begin
TreeView_GetItems(TreeView).Clear;
end;
procedure TCustomdxPSExplorerTreeViewContainer.DeleteItem(AnItem: TCustomdxPSExplorerItem);
begin
inherited;
GetNodeByItem(AnItem).Delete;
end;
procedure TCustomdxPSExplorerTreeViewContainer.InvalidateItem(AnItem: TCustomdxPSExplorerItem);
var
Node: TTreeNode;
R: TRect;
begin
Node := GetNodeByItem(AnItem);
if Node <> nil then
begin
R := Node.DisplayRect(False);
InvalidateRect(TreeView.Handle, @R, True);
end;
end;
procedure TCustomdxPSExplorerTreeViewContainer.MoveItem(AnItem: TCustomdxPSExplorerItem);
var
Node: TTreeNode;
begin
Node := GetNodeByItem(AnItem);
if Node <> nil then { We are not in creation phase of parent assigning }
if AnItem is TdxPSExplorerFolder then
Node.MoveTo(GetNodeByItem(AnItem.Parent), naAddChildFirst)
else
Node.MoveTo(GetNodeByItem(AnItem.Parent), naAddChild);
end;
procedure TCustomdxPSExplorerTreeViewContainer.RenameItem(AnItem: TCustomdxPSExplorerItem);
begin
GetNodeByItem(AnItem).Text := AnItem.DisplayName;
end;
function TCustomdxPSExplorerTreeViewContainer.GetCreationParent: TdxPSExplorerFolder;
var
Item: TCustomdxPSExplorerItem;
begin
Item := SelectedItem;
if Item = nil then
Result := Explorer.Root
else
if not (Item is TdxPSExplorerFolder) then
Result := Item.Parent
else
Result := TdxPSExplorerFolder(Item);
end;
function TCustomdxPSExplorerTreeViewContainer.GetFocusedItem: TCustomdxPSExplorerItem;
begin
Result := GetItemByNode(FocusedNode);
end;
function TCustomdxPSExplorerTreeViewContainer.GetIsEditing: Boolean;
begin
Result := TreeView.IsEditing;
end;
function TCustomdxPSExplorerTreeViewContainer.GetIsFolderSelected: Boolean;
begin
Result := SelectedItem is TdxPSExplorerFolder;
end;
function TCustomdxPSExplorerTreeViewContainer.GetIsItemSelected: Boolean;
begin
Result := SelectedItem is TdxPSExplorerItem;
end;
function TCustomdxPSExplorerTreeViewContainer.GetIsRootSelected: Boolean;
begin
Result := SelectedItem = Explorer.Root;
end;
function TCustomdxPSExplorerTreeViewContainer.GetSelectedFolder: TdxPSExplorerFolder;
var
Item: TCustomdxPSExplorerItem;
begin
Item := SelectedItem;
if Item is TdxPSExplorerFolder then
Result := TdxPSExplorerFolder(Item)
else
Result := nil;
end;
function TCustomdxPSExplorerTreeViewContainer.GetSelectedItem: TCustomdxPSExplorerItem;
begin
Result := GetItemByNode(TreeView.Selected);
end;
function TCustomdxPSExplorerTreeViewContainer.GetSelectedItemText: string;
var
Node: TTreeNode;
begin
Node := GetNodeByItem(SelectedItem);
if Node <> nil then
Result := Node.Text
else
Result := '';
end;
procedure TCustomdxPSExplorerTreeViewContainer.SetFocusedItem(Value: TCustomdxPSExplorerItem);
var
Node: TTreeNode;
begin
Node := GetNodeByItem(Value);
if Node <> nil then
Node.Focused := True;
FFocusedNode := Node;
end;
procedure TCustomdxPSExplorerTreeViewContainer.SetSelectedItem(Value: TCustomdxPSExplorerItem);
var
Node: TTreeNode;
begin
Node := GetNodeByItem(Value);
if Node <> nil then
Node.Selected := True;
end;
procedure TCustomdxPSExplorerTreeViewContainer.SetSelectedItemText(const Value: string);
var
Node: TTreeNode;
begin
Node := GetNodeByItem(SelectedItem);
if Node <> nil then
begin
Node.Text := Value;
//RefreshSorting(Node.Parent); {.1}
end;
end;
procedure TCustomdxPSExplorerTreeViewContainer.RestoreState;
begin
FStorageStream.Position := 0;
ReadTreeViewState;
FreeAndNil(FStorageStream);
end;
procedure TCustomdxPSExplorerTreeViewContainer.SaveState;
begin
FStorageStream := TMemoryStream.Create;
WriteTreeViewState;
end;
procedure TCustomdxPSExplorerTreeViewContainer.InitializeTreeContainer;
begin
inherited;
TCustomTreeViewAccess(TreeView).OnCustomDrawItem := TreeCustomDrawItem;
TCustomTreeViewAccess(TreeView).OnEdited := TreeEdited;
end;
function TCustomdxPSExplorerTreeViewContainer.AddNode(AParent: TTreeNode;
AnItem: TCustomdxPSExplorerItem): TTreeNode;
begin
Result := TreeView_GetItems(TreeView).AddChildObject(AParent, AnItem.DisplayName, AnItem);
Result.ImageIndex := TCustomdxPSExplorerItemHelper.GetImageIndex(AnItem);
Result.SelectedIndex := TCustomdxPSExplorerItemHelper.GetSelectedIndex(AnItem);
// RefreshSorting(AParent); //3.1
end;
function TCustomdxPSExplorerTreeViewContainer.CanDragNode(ANode: TTreeNode): Boolean;
var
Item: TCustomdxPSExplorerItem;
begin
Item := GetItemByNode(ANode);
Result := (Item <> nil) and Item.CanMove;
end;
function TCustomdxPSExplorerTreeViewContainer.GetHitTestInfoAt(X, Y: Integer): THitTests;
begin
Result := TreeView.GetHitTestInfoAt(X, Y);
end;
function TCustomdxPSExplorerTreeViewContainer.GetItemByNode(ANode: TTreeNode): TCustomdxPSExplorerItem;
begin
if ANode <> nil then
Result := TCustomdxPSExplorerItem(ANode.Data)
else
Result := nil;
end;
function TCustomdxPSExplorerTreeViewContainer.GetNodeByItem(AnItem: TCustomdxPSExplorerItem): TTreeNode;
function FindInChildren(ANode: TTreeNode): TTreeNode;
var
I: Integer;
begin
for I := 0 to ANode.Count - 1 do
begin
Result := ANode[I];
if GetItemByNode(Result) = AnItem then
Exit;
if Result.HasChildren then
begin
Result := FindInChildren(Result);
if Result <> nil then Exit;
end;
end;
Result := nil;
end;
begin
Result := RootNode;
if (Result <> nil) and (GetItemByNode(Result) <> AnItem) then
Result := FindInChildren(Result);
end;
function TCustomdxPSExplorerTreeViewContainer.GetRootNode: TTreeNode;
begin
Result := TreeView_GetItems(TreeView).GetFirstNode;
end;
function TCustomdxPSExplorerTreeViewContainer.GetTreeView: TCustomTreeView;
begin
Result := TCustomTreeView(Control);
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeCollapsing(Sender: TObject;
Node: TTreeNode; var AllowCollapse: Boolean);
begin
AllowCollapse := GetItemByNode(Node) <> Explorer.Root;
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
var
Item: TCustomdxPSExplorerItem;
begin
Item := GetItemByNode(Node);
if Item is TdxPSExplorerItem then
with Sender.Canvas do
begin
if TdxPSExplorerItem(Item).IsCurrentlyLoaded then
Font.Style := Font.Style + [fsBold];
if TdxPSExplorerItem(Item).HasInvalidData then
Font.Color := clGrayText;
end;
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeDblClick(Sender: TObject);
begin
if (SelectedItem <> nil) and (GetItemAtMousePos = SelectedItem) and CanLoadSelectedItemData then
LoadSelectedItemData;
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeDragDrop(Sender, Source: TObject;
X, Y: Integer);
begin
SelectedItem.Parent := GetDropTarget(X, Y);
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeDragOver(Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
Accept := (Source = Sender) and SelectedItem.CanMoveTo(GetDropTarget(X, Y));
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeCancelEdit(Sender: TObject; ANode: TTreeNode);
begin
Host.UpdateState;
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeChanged(Sender: TObject; ANode: TTreeNode);
begin
FFocusedNode := ANode;
Host.UpdateState;
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeEdited(Sender: TObject; Node: TTreeNode;
var S: string);
var
Item: TCustomdxPSExplorerItem;
ErrorText: string;
begin
if Node.Selected then Node.Focused := True;
Item := GetItemByNode(Node);
if not dxSameStr(Item.DisplayName, S) then
if not Item.CanRenameTo(S) then
begin
ErrorText := Item.CannotRenameMessageText(Item.DisplayName, S);
dxPSUtl.MessageError(ErrorText);
BeginEdit(False);
end
else
Item.Name := S;
Host.UpdateState;
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeEditing(Sender: TObject; Node: TTreeNode;
var AllowEdit: Boolean);
var
Item: TCustomdxPSExplorerItem;
Editor: HWND;
begin
Item := GetItemByNode(Node);
AllowEdit := (Item <> nil) and Item.CanRename;
if AllowEdit then
begin
TreeView.Selected.Text := Item.DisplayName;
Editor := TreeView_GetEditControl(TreeView.Handle);
if IsWindow(Editor) then
SendMessage(Editor, WM_SETTEXT, 0, Integer(PChar(Item.DisplayName)));
end;
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeExpanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
var
Item: TCustomdxPSExplorerItem;
begin
Item := GetItemByNode(Node);
if Item is TdxPSExplorerFolder then
begin
TdxPSExplorerFolder(Item).Populate;
//RefreshSorting(Item);
end;
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeKeyDown(Sender: TObject;
var Key: Word; Shift: TShiftState);
begin
ProcessKeyDown(Key, Shift);
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeKeyPress(Sender: TObject;
var Key: Char);
begin
ProcessKeyPress(Key);
end;
procedure TCustomdxPSExplorerTreeViewContainer.TreeMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
Host.UpdateState;
end;
type
TdxNodeInfo = record
Expanded: Integer;
Count: Integer;
UniqueIDSize: Integer;
//UniqueID: TBytes with UniqueIDSize length
end;
function GetNodeInfoSize: Integer;
begin
Result := SizeOf(TdxNodeInfo);
end;
procedure TCustomdxPSExplorerTreeViewContainer.ReadTreeViewState;
function ReadNode(ARecursive: Boolean): TTreeNode;
var
NodeInfo: TdxNodeInfo;
Bytes: TBytes;
Item: TCustomdxPSExplorerItem;
I: Integer;
begin
Result := nil;
FStorageStream.ReadBuffer(NodeInfo, GetNodeInfoSize);
if NodeInfo.UniqueIDSize <> 0 then
begin
SetLength(Bytes, NodeInfo.UniqueIDSize);
FStorageStream.ReadBuffer(Pointer(Bytes)^, NodeInfo.UniqueIDSize);
Item := Explorer.FindCustomItemByUniqueID(Bytes);
if Item <> nil then
begin
Result := GetNodeByItem(Item);
if Result <> nil then
Result.Expanded := NodeInfo.Expanded = 1;
end;
end;
if ARecursive then
for I := 0 to NodeInfo.Count - 1 do
ReadNode(ARecursive);
end;
procedure ReadSelection;
var
Buffer: Integer;
begin
FStorageStream.ReadBuffer(Buffer, SizeOf(Buffer));
if Buffer <> 0 then
TreeView.Selected := ReadNode(False);
end;
begin
BeginUpdate;
try
ReadNode(True);
ReadSelection;
finally
EndUpdate;
end;
end;
procedure TCustomdxPSExplorerTreeViewContainer.WriteTreeViewState;
procedure WriteNode(ANode: TTreeNode; ARecursive: Boolean);
var
Item: TCustomdxPSExplorerItem;
NodeInfo: TdxNodeInfo;
Bytes: TBytes;
I: Integer;
begin
Item := GetItemByNode(ANode);
with NodeInfo do
begin
Expanded := Ord(ANode.Expanded);
if Expanded = 1 then
Count := ANode.Count
else
Count := 0;
UniqueIDSize := Item.GetUniqueID(Bytes);
end;
FStorageStream.WriteBuffer(NodeInfo, GetNodeInfoSize);
if NodeInfo.UniqueIDSize <> 0 then
FStorageStream.WriteBuffer(Pointer(Bytes)^, NodeInfo.UniqueIDSize);
for I := 0 to ANode.Count - 1 do
WriteNode(ANode[I], ARecursive);
end;
procedure WriteSelection;
var
Flag: Integer;
begin
Flag := Ord(TreeView.Selected <> nil);
FStorageStream.WriteBuffer(Flag , SizeOf(Flag));
if TreeView.Selected <> nil then
WriteNode(TreeView.Selected, False);
end;
begin
WriteNode(RootNode, True);
WriteSelection;
end;
{ TdxPSExplorerTreeView }
constructor TdxPSExplorerTreeView.Create(AOwner: TComponent);
function CreateTimer(AnInterval: Integer; AnOnTimer: TNotifyEvent): TTimer;
begin
Result := TTimer.Create(Self);
Result.Enabled := False;
Result.Interval := AnInterval;
Result.OnTimer := AnOnTimer;
end;
begin
inherited;
Align := alClient;
DragMode := dmAutomatic;
HideSelection := False;
Images := dxPSExplorerImages;
ShowHint := True;
ShowRoot := False;
if IsWin32Version(5, 1) then
begin
ShowLines := False;
//HotTrack := True;
end;
FDragImage := TDragImageList.Create(Self);
FExpandTimer := CreateTimer(500, OnExpandTimer);
FScrollTimer := CreateTimer(80, OnScrollTimer);
end;
constructor TdxPSExplorerTreeView.CreateEx(AOwner: TComponent;
AContainer: TCustomdxPSExplorerTreeViewContainer);
begin
Create(AOwner);
FContainer := AContainer;
end;
procedure TdxPSExplorerTreeView.DragDrop(Source: TObject; X, Y: Integer);
begin
inherited;
Container.TreeDragDrop(Self, Source, X, Y);
end;
function TdxPSExplorerTreeView.CanCollapse(Node: TTreeNode): Boolean;
begin
Result := inherited CanCollapse(Node);
Container.TreeCollapsing(Self, Node, Result);
end;
function TdxPSExplorerTreeView.CanEdit(Node: TTreeNode): Boolean;
begin
Result := inherited CanEdit(Node);
Container.TreeEditing(Self, Node, Result);
end;
function TdxPSExplorerTreeView.CanExpand(Node: TTreeNode): Boolean;
begin
Result := inherited CanExpand(Node);
Container.TreeExpanding(Self, Node, Result);
end;
procedure TdxPSExplorerTreeView.Change(Node: TTreeNode);
begin
inherited;
Container.TreeChanged(Self, Node);
end;
procedure TdxPSExplorerTreeView.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.Style := Params.Style or TVS_INFOTIP;
end;
procedure TdxPSExplorerTreeView.DblClick;
begin
inherited;
Container.TreeDblClick(Self);
end;
procedure TdxPSExplorerTreeView.DoEndDrag(Target: TObject; X, Y: Integer);
begin
FDragImage.Clear;
FSavedScrollActiveAreas := [];
FSavedDropTarget := nil;
FExpandTimer.Enabled := False;
FScrollTimer.Enabled := False;
inherited;
end;
procedure TdxPSExplorerTreeView.DoStartDrag(var DragObject: TDragObject);
var
Pt: TPoint;
DragNode: TTreeNode;
Bitmap: Graphics.TBitmap;
begin
inherited;
Pt := ScreenToClient(Mouse.CursorPos);
DragNode := GetNodeAt(Pt.X, Pt.Y);
if DragNode <> nil then
begin
FDragImage.Handle := TreeView_CreateDragImage(Handle, DragNode.ItemId);
if FDragImage.Handle <> 0 then
begin
//Item := GetItemFromNode(DragNode);
//Item.Unload;
Bitmap := MakeDragBitmap(DragNode);
try
with FDragImage do
begin
Clear;
Width := Bitmap.Width;
Height := Bitmap.Height;
AddMasked(Bitmap, clDefault);
SetDragImage(0, 2, 2);
end;
finally
Bitmap.Free;
end;
end;
end;
end;
procedure TdxPSExplorerTreeView.DragOver(Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean);
begin
inherited;
Container.TreeDragOver(Self, Source, X, Y, State, Accept);
if Accept and (DropTarget <> nil) and not DropTarget.Expanded then
begin
FSavedDropTarget := DropTarget;
FExpandTimer.Enabled := False;
FExpandTimer.Enabled := True;
end;
if IsMouseInScrollArea then
begin
FSavedScrollActiveAreas := ScrollActiveAreas;
FScrollTimer.Enabled := False;
FScrollTimer.Enabled := True;
end;
end;
{$IFNDEF DELPHI6}
procedure TdxPSExplorerTreeView.Edit(const Item: TTVItem);
var
Node: TTreeNode;
begin
inherited;
if Item.pszText = nil then
begin
if (Item.State and TVIF_PARAM) <> 0 then
Node := Pointer(Item.lParam)
else
Node := Items.GetNode(Item.hItem);
if Assigned(FOnCancelEdit) then FOnCancelEdit(Self, Node);
end;
end;
{$ENDIF}
function TdxPSExplorerTreeView.GetDragImages: TDragImageList;
begin
if FDragImage.Count <> 0 then
Result := FDragImage
else
Result := nil;
end;
procedure TdxPSExplorerTreeView.KeyDown(var Key: Word; Shift: TShiftState);
begin
inherited;
Container.TreeKeyDown(Self, Key, Shift);
end;
procedure TdxPSExplorerTreeView.KeyPress(var Key: Char);
begin
inherited;
Container.TreeKeyPress(Self, Key);
end;
procedure TdxPSExplorerTreeView.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited;
Container.TreeMouseDown(Self, Button, Shift, X, Y);
end;
procedure TdxPSExplorerTreeView.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
Pt: TPoint;
Node: TTreeNode;
begin
if Button = mbRight then
begin
Pt := MakePoint(X, Y);
{$IFDEF DELPHI5}
{$IFNDEF DELPHI7}
Pt := ScreenToClient(Pt);
{$ENDIF}
{$ENDIF}
Node := GetNodeAt(Pt.X, Pt.Y);
if Node <> nil then
begin
Node.Focused := True;
Node.Selected := True;
end;
end;
inherited;
end;
procedure TdxPSExplorerTreeView.WndProc(var Message: TMessage);
var
Node: TTreeNode;
begin
if (Message.Msg = WM_LBUTTONDOWN) or (Message.Msg = WM_LBUTTONDBLCLK) then
with TWMMouse(Message) do
if Keys and MK_LBUTTON = MK_LBUTTON then
begin
Node := GetNodeAt(XPos, YPos);
if Node <> nil then
UpdateDragMode(Node);
end;
try
inherited;
except
end;
end;
function TdxPSExplorerTreeView.CanDragNode(ANode: TTreeNode): Boolean;
begin
Result := (Container = nil) or Container.CanDragNode(ANode);
end;
procedure TdxPSExplorerTreeView.DrawFlatEdge;
var
R: TRect;
DC: HDC;
begin
GetWindowRect(Handle, R);
OffsetRect(R, -R.Left, -R.Top);
DC := GetWindowDC(Handle);
try
FrameRect(DC, R, GetSysColorBrush(COLOR_BTNSHADOW));
InflateRect(R, -1, -1);
FrameRect(DC, R, GetSysColorBrush(COLOR_WINDOW));
finally
ReleaseDC(Handle, DC);
end;
end;
function TdxPSExplorerTreeView.GetInfoTip(AnItem: HTREEITEM): string;
var
ExplorerItem: TCustomdxPSExplorerItem;
begin
ExplorerItem := TCustomdxPSExplorerItem(Items.GetNode(AnItem).Data);
if ExplorerItem <> nil then
Result := ExplorerItem.InfoTip
else
Result := '';
if Result <> '' then
Result := Result + ' ' + #0#0;
end;
function TdxPSExplorerTreeView.MakeDragBitmap(ANode: TTreeNode): Graphics.TBitmap;
const
Format: UINT = DT_LEFT or DT_CENTER or DT_END_ELLIPSIS or DT_SINGLELINE;
var
S: string;
R: TRect;
begin
S := ANode.Text;
Result := Graphics.TBitmap.Create;
with Result do
begin
Width := Images.Width + 2 + Self.Canvas.TextWidth(S) + 1;
Height := TreeView_GetItemHeight(Self.Handle);
R := MakeRect(0, 0, Width, Height);
Canvas.Brush.Color := clWhite;
Canvas.FillRect(R);
Images.Draw(Canvas, 0, 0, ANode.ImageIndex);
Canvas.Font.Assign(Self.Font);
Canvas.Brush.Style := bsClear;
Inc(R.Left, Images.Width + 2);
Windows.DrawText(Canvas.Handle, PChar(S), Length(S), R, Format);
Canvas.Brush.Style := bsSolid;
end;
end;
procedure TdxPSExplorerTreeView.UpdateDragMode(ANode: TTreeNode);
const
DragModesMap: array[Boolean] of TDragMode = (dmManual, dmAutomatic);
begin
DragMode := DragModesMap[CanDragNode(ANode)];
end;
function TdxPSExplorerTreeView.GetIsMouseInScrollArea: Boolean;
var
ScrollArea: TdxPSExplorerTreeViewScrollArea;
begin
Result := True;
for ScrollArea := Low(ScrollArea) to High(ScrollArea) do
if IsMouseInScrollAreaBounds[ScrollArea] then Exit;
Result := False;
end;
function TdxPSExplorerTreeView.GetIsMouseInScrollAreaBound(ScrollArea: TdxPSExplorerTreeViewScrollArea): Boolean;
begin
Result := PtInRect(ScrollAreaBounds[ScrollArea], ScreenToClient(Mouse.CursorPos));
end;
function TdxPSExplorerTreeView.GetScrollActiveAreas: TdxPSExplorerTreeViewScrollAreas;
var
ScrollArea: TdxPSExplorerTreeViewScrollArea;
begin
Result := [];
for ScrollArea := Low(ScrollArea) to High(ScrollArea) do
if IsMouseInScrollAreaBounds[ScrollArea] then
Include(Result, ScrollArea);
end;
function TdxPSExplorerTreeView.GetScrollAreaBounds(ScrollArea: TdxPSExplorerTreeViewScrollArea): TRect;
type
TScrollBarKind = (sbkHorz, sbkVert);
function HasScrollBar(AScrollBarKind: TScrollBarKind): Boolean;
const
ScrollBarKindMap: array[TScrollBarKind] of Integer = (WS_HSCROLL, WS_VSCROLL);
begin
Result := Windows.GetWindowLong(Handle, GWL_STYLE) and ScrollBarKindMap[AScrollBarKind] <> 0;
end;
function ScrollBarWidth(AScrollBarKind: TScrollBarKind): Integer;
const
ScrollBarWidthIndexMap: array[TScrollBarKind] of Integer = (SM_CYHSCROLL, SM_CXVSCROLL);
begin
Result := GetSystemMetrics(ScrollBarWidthIndexMap[AScrollBarKind]);
end;
begin
case ScrollArea of
etsaLeft:
Result := MakeRect(0, 0, ScrollAreaWidth, Height);
etsaTop:
Result := MakeRect(0, 0, Width, ScrollAreaHeight);
etsaRight:
begin
Result := MakeRect(Width - ScrollAreaWidth, 0, Width, Height);
if HasScrollBar(sbkVert) then
Dec(Result.Left, ScrollBarWidth(sbkVert));
end;
else //etsaBottom
begin
Result := MakeRect(0, Height - ScrollAreaHeight, Width, Height);
if HasScrollBar(sbkHorz) then
Dec(Result.Top, ScrollBarWidth(sbkHorz));
end;
end;
end;
procedure TdxPSExplorerTreeView.SetFlat(Value: Boolean);
begin
if FFlat <> Value then
begin
FFlat := Value;
RecreateWnd;
end;
end;
procedure TdxPSExplorerTreeView.OnExpandTimer(Sender: TObject);
begin
FExpandTimer.Enabled := False;
if DropTarget = FSavedDropTarget then
begin
ImageList_DragShowNolock(False);
try
DropTarget.Expand(False);
finally
Update;
ImageList_DragShowNolock(True);
end;
end;
end;
procedure TdxPSExplorerTreeView.OnScrollTimer(Sender: TObject);
procedure DoScroll(AMessage: Cardinal; AScrollCode: Integer);
begin
Perform(AMessage, AScrollCode, 0);
end;
const
ScrollMessages: array[TdxPSExplorerTreeViewScrollArea] of Cardinal = (WM_HSCROLL, WM_VSCROLL, WM_HSCROLL, WM_VSCROLL);
ScrollCodes: array[TdxPSExplorerTreeViewScrollArea] of Integer = (SB_LINELEFT, SB_LINEUP, SB_LINERIGHT, SB_LINEDOWN);
var
ScrollActiveAreas: TdxPSExplorerTreeViewScrollAreas;
ScrollArea: TdxPSExplorerTreeViewScrollArea;
begin
ScrollActiveAreas := Self.ScrollActiveAreas * FSavedScrollActiveAreas;
if ScrollActiveAreas <> [] then
begin
ImageList_DragShowNolock(False);
try
for ScrollArea := Low(ScrollArea) to High(ScrollArea) do
if ScrollArea in ScrollActiveAreas then
DoScroll(ScrollMessages[ScrollArea], ScrollCodes[ScrollArea]);
finally
Update;
ImageList_DragShowNolock(True);
end;
end;
FSavedScrollActiveAreas := Self.ScrollActiveAreas;
end;
{$IFDEF WMCONTEXTMENU}
procedure TdxPSExplorerTreeView.WMContextMenu(var Message: TWMContextMenu);
var
KeyState: TKeyboardState;
begin
inherited;
GetKeyboardState(KeyState);
MouseUp(mbRight, KeyboardStateToShiftState(KeyState), Message.Pos.X, Message.Pos.Y);
end;
{$ENDIF}
procedure TdxPSExplorerTreeView.WMNCPaint(var Message: TWMNCPaint);
begin
inherited;
if Flat then DrawFlatEdge;
end;
procedure TdxPSExplorerTreeView.CMHintShow(var Message: TCMHintShow);
function HasInfoTip: Boolean;
var
Node: TTreeNode;
begin
Result := dxPSGlbl.CanShowHints;
if Result then
begin
with Message.HintInfo^.CursorPos do
Node := GetNodeAt(X, Y);
Result := (Node <> nil) and (GetInfoTip(Node.ItemId) <> '');
end;
end;
var
Node: TTreeNode;
begin
if HasInfoTip then
begin
with Message.HintInfo^ do
begin
Node := GetNodeAt(CursorPos.X, CursorPos.Y);
CursorRect := Node.DisplayRect(True);
Windows.MapWindowPoints(Handle, 0, CursorRect, 2);
HintStr := GetInfoTip(Node.ItemId);
HintPos.Y := CursorRect.Top + Windows.GetSystemMetrics(SM_CYCURSOR);
HintPos.X := CursorRect.Left + Windows.GetSystemMetrics(SM_CXCURSOR);
HintMaxWidth := ClientWidth;
end;
Message.Result := 0;
end
else
inherited;
end;
{ TdxPSExplorerTreeViewContainer }
class function TdxPSExplorerTreeViewContainer.TreeViewClass: TCustomTreeViewClass;
begin
Result := TdxPSExplorerTreeView;
end;
procedure TdxPSExplorerTreeViewContainer.InitializeTreeContainer;
begin
inherited;
TreeView.Container := Self;
TreeView.Flat := Host.Flat;
TreeView.OnCancelEdit := TreeCancelEdit;
end;
function TdxPSExplorerTreeViewContainer.GetTreeView: TdxPSExplorerTreeView;
begin
Result := TdxPSExplorerTreeView(inherited TreeView)
end;
initialization
TCustomdxPSExplorerTreeViewContainer.Register;
TdxPSExplorerTreeViewContainer.Register;
finalization
TdxPSExplorerTreeViewContainer.Unregister;
TCustomdxPSExplorerTreeViewContainer.Unregister;
end.