* Synchronize with main VTV repository up to svn rev 419

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3346 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
blikblum
2014-07-20 13:11:13 +00:00
parent e0ef4c244c
commit b7ba0d3727

View File

@ -3,7 +3,7 @@ unit VirtualTrees;
{$mode delphi}{$H+} {$mode delphi}{$H+}
{$packset 1} {$packset 1}
// Version 5.0.0 // Version 5.0.1
// //
// The contents of this file are subject to the Mozilla Public License // The contents of this file are subject to the Mozilla Public License
// Version 1.1 (the "License"); you may not use this file except in compliance // Version 1.1 (the "License"); you may not use this file except in compliance
@ -105,7 +105,7 @@ const
VTMajorVersion = 5; VTMajorVersion = 5;
VTMinorVersion = 0; VTMinorVersion = 0;
VTReleaseVersion = 0; VTReleaseVersion = 1;
VTTreeStreamVersion = 2; VTTreeStreamVersion = 2;
VTHeaderStreamVersion = 6; // The header needs an own stream version to indicate changes only relevant to the header. VTHeaderStreamVersion = 6; // The header needs an own stream version to indicate changes only relevant to the header.
@ -157,6 +157,9 @@ const
ChangeTimer = 5; ChangeTimer = 5;
StructureChangeTimer = 6; StructureChangeTimer = 6;
SearchTimer = 7; SearchTimer = 7;
ThemeChangedTimer = 8;
ThemeChangedTimerDelay = 500;
// Need to use this message to release the edit link interface asynchronously. // Need to use this message to release the edit link interface asynchronously.
WM_CHANGESTATE = WM_APP + 32; WM_CHANGESTATE = WM_APP + 32;
@ -183,9 +186,11 @@ const
IID_IDragSourceHelper: TGUID = (D1: $DE5BF786; D2: $477A; D3: $11D2; D4: ($83, $9D, $00, $C0, $4F, $D9, $18, $D0)); IID_IDragSourceHelper: TGUID = (D1: $DE5BF786; D2: $477A; D3: $11D2; D4: ($83, $9D, $00, $C0, $4F, $D9, $18, $D0));
IID_IDropTarget: TGUID = (D1: $00000122; D2: $0000; D3: $0000; D4: ($C0, $00, $00, $00, $00, $00, $00, $46)); IID_IDropTarget: TGUID = (D1: $00000122; D2: $0000; D3: $0000; D4: ($C0, $00, $00, $00, $00, $00, $00, $46));
CLSID_DragDropHelper: TGUID = (D1: $4657278A; D2: $411B; D3: $11D2; D4: ($83, $9A, $00, $C0, $4F, $D9, $18, $D0)); CLSID_DragDropHelper: TGUID = (D1: $4657278A; D2: $411B; D3: $11D2; D4: ($83, $9A, $00, $C0, $4F, $D9, $18, $D0));
DSH_ALLOWDROPDESCRIPTIONTEXT = $1;
SID_IDropTargetHelper = '{4657278B-411B-11D2-839A-00C04FD918D0}'; SID_IDropTargetHelper = '{4657278B-411B-11D2-839A-00C04FD918D0}';
SID_IDragSourceHelper = '{DE5BF786-477A-11D2-839D-00C04FD918D0}'; SID_IDragSourceHelper = '{DE5BF786-477A-11D2-839D-00C04FD918D0}';
SID_IDragSourceHelper2 = '{83E07D0D-0C5F-4163-BF1A-60B274051E40}';
SID_IDropTarget = '{00000122-0000-0000-C000-000000000046}'; SID_IDropTarget = '{00000122-0000-0000-C000-000000000046}';
// Help identifiers for exceptions. Application developers are responsible to link them with actual help topics. // Help identifiers for exceptions. Application developers are responsible to link them with actual help topics.
@ -720,14 +725,21 @@ type
sizeDragImage: TSize; sizeDragImage: TSize;
ptOffset: TPoint; ptOffset: TPoint;
hbmpDragImage: HBITMAP; hbmpDragImage: HBITMAP;
ColorRef: TColorRef; crColorKey: TColorRef;
end; end;
IDragSourceHelper = interface(IUnknown) IDragSourceHelper = interface(IUnknown)
[SID_IDragSourceHelper] [SID_IDragSourceHelper]
function InitializeFromBitmap(var SHDragImage: TSHDragImage; pDataObject: IDataObject): HRESULT; stdcall; function InitializeFromBitmap(SHDragImage: PSHDragImage; pDataObject: IDataObject): HRESULT; stdcall;
function InitializeFromWindow(Window: HWND; var ppt: TPoint; pDataObject: IDataObject): HRESULT; stdcall; function InitializeFromWindow(Window: HWND; var ppt: TPoint; pDataObject: IDataObject): HRESULT; stdcall;
end; end;
{$EXTERNALSYM IDragSourceHelper}
IDragSourceHelper2 = interface(IDragSourceHelper)
[SID_IDragSourceHelper2]
function SetFlags(dwFlags: DWORD): HRESULT; stdcall;
end;
{$EXTERNALSYM IDragSourceHelper2}
IVTDragManager = interface(IUnknown) IVTDragManager = interface(IUnknown)
['{C4B25559-14DA-446B-8901-0C879000EB16}'] ['{C4B25559-14DA-446B-8901-0C879000EB16}']
@ -2042,6 +2054,7 @@ type
FLastClickPos: TPoint; // Used for retained drag start and wheel mouse scrolling. FLastClickPos: TPoint; // Used for retained drag start and wheel mouse scrolling.
FOperationCount: Cardinal; // Counts how many nested long-running operations are in progress. FOperationCount: Cardinal; // Counts how many nested long-running operations are in progress.
FOperationCanceled: Boolean; // Used to indicate that a long-running operation should be canceled. FOperationCanceled: Boolean; // Used to indicate that a long-running operation should be canceled.
FChangingTheme: Boolean; // Used to indicate that a theme change is goi ng on
{$ifdef EnableAccessible} {$ifdef EnableAccessible}
// MSAA support // MSAA support
@ -2315,6 +2328,7 @@ type
procedure SetVisible(Node: PVirtualNode; Value: Boolean); procedure SetVisible(Node: PVirtualNode; Value: Boolean);
procedure SetVisiblePath(Node: PVirtualNode; Value: Boolean); procedure SetVisiblePath(Node: PVirtualNode; Value: Boolean);
procedure StaticBackground(Source: TBitmap; Target: TCanvas; const OffsetPosition: TPoint; const R: TRect); procedure StaticBackground(Source: TBitmap; Target: TCanvas; const OffsetPosition: TPoint; const R: TRect);
procedure SetWindowTheme(const Theme: String);
procedure TileBackground(Source: TBitmap; Target: TCanvas; const Offset: TPoint; R: TRect); procedure TileBackground(Source: TBitmap; Target: TCanvas; const Offset: TPoint; R: TRect);
function ToggleCallback(Step, StepSize: Integer; Data: Pointer): Boolean; function ToggleCallback(Step, StepSize: Integer; Data: Pointer): Boolean;
protected protected
@ -2474,6 +2488,7 @@ type
procedure DoGetLineStyle(var Bits: Pointer); virtual; procedure DoGetLineStyle(var Bits: Pointer); virtual;
function DoGetNodeHint(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; virtual; function DoGetNodeHint(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; virtual;
function DoGetNodeTooltip(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; virtual; function DoGetNodeTooltip(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; virtual;
function DoGetNodeExtraWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; virtual;
function DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; virtual; function DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; virtual;
function DoGetPopupMenu(Node: PVirtualNode; Column: TColumnIndex; const Position: TPoint): TPopupMenu; virtual; function DoGetPopupMenu(Node: PVirtualNode; Column: TColumnIndex; const Position: TPoint): TPopupMenu; virtual;
procedure DoGetUserClipboardFormats(var Formats: TFormatEtcArray); virtual; procedure DoGetUserClipboardFormats(var Formats: TFormatEtcArray); virtual;
@ -3010,7 +3025,7 @@ type
property CutCopyCount: Integer read GetCutCopyCount; property CutCopyCount: Integer read GetCutCopyCount;
property DragImage: TVTDragImage read FDragImage; property DragImage: TVTDragImage read FDragImage;
property VTVDragManager: IVTDragManager read GetDragManager; property VTVDragManager: IVTDragManager read GetDragManager;
property DropTargetNode: PVirtualNode read FDropTargetNode; property DropTargetNode: PVirtualNode read FDropTargetNode write FDropTargetNode;
property EditLink: IVTEditLink read FEditLink; property EditLink: IVTEditLink read FEditLink;
property EmptyListMessage: String read FEmptyListMessage write SetEmptyListMessage; property EmptyListMessage: String read FEmptyListMessage write SetEmptyListMessage;
property Expanded[Node: PVirtualNode]: Boolean read GetExpanded write SetExpanded; property Expanded[Node: PVirtualNode]: Boolean read GetExpanded write SetExpanded;
@ -3230,6 +3245,7 @@ type
procedure GetRenderStartValues(Source: TVSTTextSourceType; out Node: PVirtualNode; procedure GetRenderStartValues(Source: TVSTTextSourceType; out Node: PVirtualNode;
out NextNodeProc: TGetNextNodeProc); out NextNodeProc: TGetNextNodeProc);
function GetOptions: TCustomStringTreeOptions; function GetOptions: TCustomStringTreeOptions;
function GetStaticText(Node: PVirtualNode; Column: TColumnIndex): String;
function GetText(Node: PVirtualNode; Column: TColumnIndex): String; function GetText(Node: PVirtualNode; Column: TColumnIndex): String;
procedure InitializeTextProperties(var PaintInfo: TVTPaintInfo); procedure InitializeTextProperties(var PaintInfo: TVTPaintInfo);
procedure PaintNormalText(var PaintInfo: TVTPaintInfo; TextOutFlags: Integer; Text: String); procedure PaintNormalText(var PaintInfo: TVTPaintInfo; TextOutFlags: Integer; Text: String);
@ -3242,11 +3258,13 @@ type
protected protected
procedure AdjustPaintCellRect(var PaintInfo: TVTPaintInfo; out NextNonEmpty: TColumnIndex); override; procedure AdjustPaintCellRect(var PaintInfo: TVTPaintInfo; out NextNonEmpty: TColumnIndex); override;
function CanExportNode(Node: PVirtualNode): Boolean; function CanExportNode(Node: PVirtualNode): Boolean;
function CalculateStaticTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; const Text: String): Integer; virtual;
function CalculateTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; const Text: String): Integer; virtual; function CalculateTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; const Text: String): Integer; virtual;
function ColumnIsEmpty(Node: PVirtualNode; Column: TColumnIndex): Boolean; override; function ColumnIsEmpty(Node: PVirtualNode; Column: TColumnIndex): Boolean; override;
function DoCreateEditor(Node: PVirtualNode; Column: TColumnIndex): IVTEditLink; override; function DoCreateEditor(Node: PVirtualNode; Column: TColumnIndex): IVTEditLink; override;
function DoGetNodeHint(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; override; function DoGetNodeHint(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; override;
function DoGetNodeTooltip(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; override; function DoGetNodeTooltip(Node: PVirtualNode; Column: TColumnIndex; var LineBreakStyle: TVTTooltipLineBreakStyle): String; override;
function DoGetNodeExtraWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; override;
function DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; override; function DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; override;
procedure DoGetText(Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; procedure DoGetText(Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var Text: String); virtual; var Text: String); virtual;
@ -3303,6 +3321,7 @@ type
function SaveToCSVFile(const FileNameWithPath : TFileName; const IncludeHeading : Boolean) : Boolean; function SaveToCSVFile(const FileNameWithPath : TFileName; const IncludeHeading : Boolean) : Boolean;
property ImageText[Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex]: String read GetImageText; property ImageText[Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex]: String read GetImageText;
property StaticText[Node: PVirtualNode; Column: TColumnIndex]: String read GetStaticText;
property Text[Node: PVirtualNode; Column: TColumnIndex]: String read GetText write SetText; property Text[Node: PVirtualNode; Column: TColumnIndex]: String read GetText write SetText;
end; end;
@ -5510,29 +5529,23 @@ begin
if HandleAllocated then if HandleAllocated then
begin begin
{$ifdef ThemeSupport}
//todo
{
if IsWinVistaOrAbove and ((tsUseThemes in FStates) or if IsWinVistaOrAbove and ((tsUseThemes in FStates) or
((toThemeAware in ToBeSet) and StyleServices.Enabled)) and ((toThemeAware in ToBeSet) and StyleServices.Enabled)) and
(toUseExplorerTheme in (ToBeSet + ToBeCleared)) then (toUseExplorerTheme in (ToBeSet + ToBeCleared)) then
if toUseExplorerTheme in ToBeSet then if toUseExplorerTheme in ToBeSet then
begin begin
SetWindowTheme(Handle, 'explorer', nil); SetWindowTheme('explorer');
DoStateChange([tsUseExplorerTheme]); DoStateChange([tsUseExplorerTheme]);
end end
else else
if toUseExplorerTheme in ToBeCleared then if toUseExplorerTheme in ToBeCleared then
begin begin
SetWindowTheme(Handle, '', nil); SetWindowTheme('');
DoStateChange([], [tsUseExplorerTheme]); DoStateChange([], [tsUseExplorerTheme]);
end; end;
}
{$endif ThemeSupport}
if not (csLoading in ComponentState) then if not (csLoading in ComponentState) then
begin begin
{$ifdef ThemeSupport}
if (toThemeAware in ToBeSet + ToBeCleared) or (toUseExplorerTheme in ToBeSet + ToBeCleared) then if (toThemeAware in ToBeSet + ToBeCleared) or (toUseExplorerTheme in ToBeSet + ToBeCleared) then
begin begin
if (toThemeAware in ToBeSet) and StyleServices.Enabled then if (toThemeAware in ToBeSet) and StyleServices.Enabled then
@ -5544,24 +5557,23 @@ begin
PrepareBitmaps(True, False); PrepareBitmaps(True, False);
RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_VALIDATE or RDW_FRAME); RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_VALIDATE or RDW_FRAME);
end; end;
{$endif ThemeSupport}
if toChildrenAbove in ToBeSet + ToBeCleared then if toChildrenAbove in ToBeSet + ToBeCleared then
begin begin
InvalidateCache; InvalidateCache;
if FUpdateCount = 0 then if FUpdateCount = 0 then
begin begin
ValidateCache; ValidateCache;
Invalidate; Invalidate;
end; end;
end; end;
Invalidate; Invalidate;
end; end;
end; end;
end;
end; end;
end; end;
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -6074,33 +6086,39 @@ var
Height: Integer; Height: Integer;
DragSourceHelper: IDragSourceHelper; DragSourceHelper: IDragSourceHelper;
DragInfo: TSHDragImage; DragInfo: TSHDragImage;
lDragSourceHelper2: IDragSourceHelper2;// Needed to get Windows Vista+ style drag hints.
lNullPoint: TPoint;
begin begin
Width := DragImage.Width; Width := DragImage.Width;
Height := DragImage.Height; Height := DragImage.Height;
// Determine whether the system supports the drag helper interfaces. // Determine whether the system supports the drag helper interfaces.
if Assigned(DataObject) and Succeeded(CoCreateInstance(CLSID_DragDropHelper, nil, CLSCTX_INPROC_SERVER, if Assigned(DataObject) and Succeeded(CoCreateInstance(CLSID_DragDropHelper, nil, CLSCTX_INPROC_SERVER,
IID_IDragSourceHelper, DragSourceHelper)) then IDragSourceHelper, DragSourceHelper)) then
begin begin
Include(FStates, disSystemSupport); Include(FStates, disSystemSupport);
lNullPoint := Point(0,0);
// Supply the drag source helper with our drag image. if Supports(DragSourceHelper, IDragSourceHelper2, lDragSourceHelper2) then
DragInfo.sizeDragImage.cx := Width; lDragSourceHelper2.SetFlags(DSH_ALLOWDROPDESCRIPTIONTEXT);// Show description texts
DragInfo.sizeDragImage.cy := Height; if not Succeeded(DragSourceHelper.InitializeFromWindow(0, lNullPoint, DataObject)) then begin // First let the system try to initialze the DragSourceHelper, this works fine e.g. for file system objects
DragInfo.ptOffset.x := Width div 2; // Supply the drag source helper with our drag image.
DragInfo.ptOffset.y := Height div 2; DragInfo.sizeDragImage.cx := Width;
//todo: replace CopyImage. Alternatively reimplement Drag support DragInfo.sizeDragImage.cy := Height;
{$ifndef INCOMPLETE_WINAPI} DragInfo.ptOffset.x := Width div 2;
DragInfo.hbmpDragImage := CopyImage(DragImage.Handle, IMAGE_BITMAP, Width, Height, LR_COPYRETURNORG); DragInfo.ptOffset.y := Height div 2;
{$else} //lcl
DragInfo.hbmpDragImage := 0; //todo: replace CopyImage. Alternatively reimplement Drag support
{$endif} {$ifndef INCOMPLETE_WINAPI}
DragInfo.ColorRef := ColorToRGB(FColorKey); DragInfo.hbmpDragImage := CopyImage(DragImage.Handle, IMAGE_BITMAP, Width, Height, LR_COPYRETURNORG);
if not Succeeded(DragSourceHelper.InitializeFromBitmap(DragInfo, DataObject)) then {$else}
begin DragInfo.hbmpDragImage := 0;
DeleteObject(DragInfo.hbmpDragImage); {$endif}
Exclude(FStates, disSystemSupport); DragInfo.crColorKey := ColorToRGB(FColorKey);
if not Succeeded(DragSourceHelper.InitializeFromBitmap(@DragInfo, DataObject)) then
begin
DeleteObject(DragInfo.hbmpDragImage);
Exclude(FStates, disSystemSupport);
end;
end; end;
end end
else else
@ -7057,7 +7075,7 @@ begin
// If the text is taller than the given height, perform no vertical centration as this // If the text is taller than the given height, perform no vertical centration as this
// would make the text even less readable. // would make the text even less readable.
//Using Max() fixes badly positioned text if Extra Large fonts have been activated in the Windows display options //Using Max() fixes badly positioned text if Extra Large fonts have been activated in the Windows display options
TextPos.Y := Max(-5,(ClientSize.Y - TextSize.cy) div 2); TextPos.Y := Max(-5, (ClientSize.Y - TextSize.cy) div 2);
end end
else else
begin begin
@ -7248,7 +7266,11 @@ begin
if Layout = blGlyphLeft then if Layout = blGlyphLeft then
MinLeft := HeaderGlyphPos.X + HeaderGlyphSize.X + FSpacing; MinLeft := HeaderGlyphPos.X + HeaderGlyphSize.X + FSpacing;
if FCheckBox and (Owner.Header.MainColumn = Self.Index) then if FCheckBox and (Owner.Header.MainColumn = Self.Index) then
Dec(HeaderGlyphPos.X, 2 + 2 * Integer(toShowRoot in Owner.FHeader.Treeview.TreeOptions.FPaintOptions)); Dec(HeaderGlyphPos.X, 2 + 2 * Integer(toShowRoot in Owner.FHeader.Treeview.TreeOptions.FPaintOptions))
else
if Owner.Header.MainColumn <> Self.Index then
Dec(HeaderGlyphPos.X, 2);
// Finally transform header glyph to its actual position. // Finally transform header glyph to its actual position.
Inc(HeaderGlyphPos.X, Client.Left); Inc(HeaderGlyphPos.X, Client.Left);
Inc(HeaderGlyphPos.Y, Client.Top); Inc(HeaderGlyphPos.Y, Client.Top);
@ -11601,6 +11623,12 @@ begin
if HandleAllocated then if HandleAllocated then
DestroyWindowHandle; DestroyWindowHandle;
} }
// Release FDottedBrush in case WM_NCDESTROY hasn't been triggered.
if FDottedBrush <> 0 then
DeleteObject(FDottedBrush);
FDottedBrush := 0;
FOptions.Free; FOptions.Free;
FreeAndNil(FHeader); FreeAndNil(FHeader);
@ -11755,7 +11783,7 @@ begin
VAlign := MulDiv(Integer(Node.NodeHeight), Node.Align, 100); VAlign := MulDiv(Integer(Node.NodeHeight), Node.Align, 100);
end; end;
VButtonAlign := VAlign - FPlusBM.Height div 2; VButtonAlign := VAlign - FPlusBM.Height div 2 - (FPlusBM.Height and 1);
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -14632,6 +14660,17 @@ begin
end; end;
end; end;
//----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.SetWindowTheme(const Theme: String);
begin
FChangingTheme := True;
//lcl: todo
//UxTheme.SetWindowTheme(Handle, PAnsiChar(Theme), nil);
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.TileBackground(Source: TBitmap; Target: TCanvas; const Offset: TPoint; R: TRect); procedure TBaseVirtualTree.TileBackground(Source: TBitmap; Target: TCanvas; const Offset: TPoint; R: TRect);
@ -14644,7 +14683,6 @@ var
SourceX, SourceX,
SourceY, SourceY,
TargetX, TargetX,
DeltaY: Integer; DeltaY: Integer;
begin begin
@ -15463,6 +15501,7 @@ begin
KillTimer(Handle, EditTimer); KillTimer(Handle, EditTimer);
KillTimer(Handle, ScrollTimer); KillTimer(Handle, ScrollTimer);
KillTimer(Handle, SearchTimer); KillTimer(Handle, SearchTimer);
KillTimer(Handle, ThemeChangedTimer);
FSearchBuffer := ''; FSearchBuffer := '';
FLastSearchNode := nil; FLastSearchNode := nil;
@ -16898,8 +16937,13 @@ begin
DoStateChange([tsUseThemes]) DoStateChange([tsUseThemes])
else else
DoStateChange([], [tsUseThemes]); DoStateChange([], [tsUseThemes]);
RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_VALIDATE or RDW_FRAME);
end; // Updating the visuals here will not work correctly. Therefore we postpone
// the update by using a timer.
if not FChangingTheme then
SetTimer(Handle, ThemeChangedTimer, ThemeChangedTimerDelay, nil);
FChangingTheme := False;
end;
{$endif} {$endif}
{$endif ThemeSupport} {$endif ThemeSupport}
@ -16943,6 +16987,11 @@ begin
FSearchBuffer := ''; FSearchBuffer := '';
FLastSearchNode := nil; FLastSearchNode := nil;
end; end;
ThemeChangedTimer:
begin
KillTimer(Handle, ThemeChangedTimer);
RecreateWnd(Self);
end;
end; end;
end; end;
{$ifdef DEBUG_VTV}Logger.ExitMethod([lcMessages,lcTimer],'WMTimer');{$endif} {$ifdef DEBUG_VTV}Logger.ExitMethod([lcMessages,lcTimer],'WMTimer');{$endif}
@ -17703,17 +17752,19 @@ begin
{$ifdef DEBUG_VTV}Logger.Send([lcInfo],'Handle (CreateWnd)',Handle);{$endif} {$ifdef DEBUG_VTV}Logger.Send([lcInfo],'Handle (CreateWnd)',Handle);{$endif}
DoStateChange([], [tsWindowCreating]); DoStateChange([], [tsWindowCreating]);
{$ifdef ThemeSupport} if StyleServices.Enabled and (toThemeAware in TreeOptions.PaintOptions) then
if StyleServices.Enabled and (toThemeAware in TreeOptions.PaintOptions) then begin
DoStateChange([tsUseThemes]);
if (toUseExplorerTheme in FOptions.FPaintOptions) and IsWinVistaOrAbove then
begin begin
DoStateChange([tsUseThemes]); DoStateChange([tsUseExplorerTheme]);
//todo SetWindowTheme('explorer');
//if (toUseExplorerTheme in FOptions.FPaintOptions) and IsWinVistaOrAbove then
// SetWindowTheme(Handle, 'explorer', nil);
end end
else else
{$endif ThemeSupport} DoStateChange([], [tsUseExplorerTheme]);
DoStateChange([], [tsUseThemes]); end
else
DoStateChange([], [tsUseThemes, tsUseExplorerTheme]);
// Because of the special recursion and update stopper when creating the window (or resizing it) // Because of the special recursion and update stopper when creating the window (or resizing it)
// we have to manually trigger the auto size calculation here. // we have to manually trigger the auto size calculation here.
@ -17776,8 +17827,9 @@ var
begin begin
ImageHit := HitInfo.HitPositions * [hiOnNormalIcon, hiOnStateIcon] <> []; ImageHit := HitInfo.HitPositions * [hiOnNormalIcon, hiOnStateIcon] <> [];
LabelHit := hiOnItemLabel in HitInfo.HitPositions; LabelHit := hiOnItemLabel in HitInfo.HitPositions;
ItemHit := ((hiOnItem in HitInfo.HitPositions) and ((toFullRowDrag in FOptions.FMiscOptions) or ItemHit := ((hiOnItem in HitInfo.HitPositions) and
(toFullRowSelect in FOptions.FSelectionOptions))); ((toFullRowDrag in FOptions.FMiscOptions) or (toFullRowSelect in FOptions.FSelectionOptions)));
// In report mode only direct hits of the node captions/images in the main column are accepted as hits. // In report mode only direct hits of the node captions/images in the main column are accepted as hits.
if (toReportMode in FOptions.FMiscOptions) and not (ItemHit or ((LabelHit or ImageHit) and if (toReportMode in FOptions.FMiscOptions) and not (ItemHit or ((LabelHit or ImageHit) and
(HitInfo.HitColumn = FHeader.MainColumn))) then (HitInfo.HitColumn = FHeader.MainColumn))) then
@ -17785,7 +17837,7 @@ begin
if Assigned(HitInfo.HitNode) then if Assigned(HitInfo.HitNode) then
begin begin
if ItemHit or LabelHit or ImageHit or not (toShowDropmark in FOptions.FPaintOptions) then if LabelHit or ImageHit or not (toShowDropmark in FOptions.FPaintOptions) then
Result := dmOnNode Result := dmOnNode
else else
if ((NodeRect.Top + NodeRect.Bottom) div 2) > P.Y then if ((NodeRect.Top + NodeRect.Bottom) div 2) > P.Y then
@ -19174,8 +19226,20 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.DoGetNodeExtraWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer;
// Returns the pixel width of extra space occupied by node contents (for example, static text).
begin
Result := 0;
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; function TBaseVirtualTree.DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer;
// Returns the pixel width of a node.
begin begin
Result := 0; Result := 0;
end; end;
@ -20065,7 +20129,15 @@ procedure TBaseVirtualTree.DragAndDrop(AllowedEffects: LongWord;
begin begin
{$ifdef Windows} {$ifdef Windows}
ActiveX.DoDragDrop(DataObject, VTVDragManager as IDropSource, AllowedEffects, @DragEffect); //lcl
//todo
{
if IsWinVistaOrAbove then begin
SHDoDragDrop(Self.Handle, DataObject, nil, AllowedEffects, DragEffect); // supports drag hints on Windows Vista and later
end
else
}
ActiveX.DoDragDrop(DataObject, VTVDragManager as IDropSource, AllowedEffects, @DragEffect);
{$endif} {$endif}
end; end;
@ -21359,8 +21431,9 @@ begin
DoStateChange([], [tsEditPending]); DoStateChange([], [tsEditPending]);
end; end;
if not (tsEditing in FStates) or DoEndEdit then if (tsEditing in FStates) then
begin DoEndEdit;
// Focus change. Don't use the SetFocus method as this does not work for MDI windows. // Focus change. Don't use the SetFocus method as this does not work for MDI windows.
if not Focused and CanFocus then if not Focused and CanFocus then
begin begin
@ -21611,7 +21684,6 @@ begin
if AutoDrag and IsAnyHit and (FStates * [tsLeftButtonDown, tsRightButtonDown, tsMiddleButtonDown] <> []) then if AutoDrag and IsAnyHit and (FStates * [tsLeftButtonDown, tsRightButtonDown, tsMiddleButtonDown] <> []) then
BeginDrag(False); BeginDrag(False);
end; end;
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -23157,7 +23229,7 @@ begin
for I := 0 to IndentSize - 1 do for I := 0 to IndentSize - 1 do
begin begin
DoBeforeDrawLineImage(PaintInfo.Node, I + Ord(not (toShowRoot in TreeOptions.PaintOptions)), XPos); DoBeforeDrawLineImage(PaintInfo.Node, I + Ord(not (toShowRoot in TreeOptions.PaintOptions)), XPos);
DrawLineImage(PaintInfo, XPos, CellRect.Top, NodeHeight[Node] - 1, VAlignment, NewStyles[I], DrawLineImage(PaintInfo, XPos, CellRect.Top, NodeHeight[Node] - 1, VAlignment - 1, NewStyles[I],
BidiMode <> bdLeftToRight); BidiMode <> bdLeftToRight);
Inc(XPos, Offset); Inc(XPos, Offset);
end; end;
@ -23170,7 +23242,7 @@ begin
for I := 0 to IndentSize - 1 do for I := 0 to IndentSize - 1 do
begin begin
DoBeforeDrawLineImage(PaintInfo.Node, I + Ord(not (toShowRoot in TreeOptions.PaintOptions)), XPos); DoBeforeDrawLineImage(PaintInfo.Node, I + Ord(not (toShowRoot in TreeOptions.PaintOptions)), XPos);
DrawLineImage(PaintInfo, XPos, CellRect.Top, NodeHeight[Node], VAlignment, LineImage[I], DrawLineImage(PaintInfo, XPos, CellRect.Top, NodeHeight[Node], VAlignment - 1, LineImage[I],
BidiMode <> bdLeftToRight); BidiMode <> bdLeftToRight);
Inc(XPos, Offset); Inc(XPos, Offset);
end; end;
@ -26616,88 +26688,89 @@ begin
StartOperation(okGetMaxColumnWidth); StartOperation(okGetMaxColumnWidth);
try try
if Assigned(FOnBeforeGetMaxColumnWidth) then if Assigned(FOnBeforeGetMaxColumnWidth) then
FOnBeforeGetMaxColumnWidth(FHeader, Column, UseSmartColumnWidth); FOnBeforeGetMaxColumnWidth(FHeader, Column, UseSmartColumnWidth);
// Don't check the event here as descendant trees might have overriden the DoGetImageIndex method. // Don't check the event here as descendant trees might have overriden the DoGetImageIndex method.
WithImages := Assigned(FImages); WithImages := Assigned(FImages);
if WithImages then if WithImages then
ImageOffset := FImages.Width + 2 ImageOffset := FImages.Width + 2
else else
ImageOffset := 0; ImageOffset := 0;
WithStateImages := Assigned(FStateImages); WithStateImages := Assigned(FStateImages);
if WithStateImages then if WithStateImages then
StateImageOffset := FStateImages.Width + 2 StateImageOffset := FStateImages.Width + 2
else else
StateImageOffset := 0; StateImageOffset := 0;
if Assigned(FCheckImages) then if Assigned(FCheckImages) then
CheckOffset := FCheckImages.Height + 2 CheckOffset := FCheckImages.Width + 2
else else
CheckOffset := 0; CheckOffset := 0;
if UseSmartColumnWidth then // Get first visible node which is in view. if UseSmartColumnWidth then // Get first visible node which is in view.
Run := GetTopNode Run := GetTopNode
else else
Run := GetFirstVisible(nil, True); Run := GetFirstVisible(nil, True);
if Column = FHeader.MainColumn then if Column = FHeader.MainColumn then
begin begin
if toFixedIndent in FOptions.FPaintOptions then if toFixedIndent in FOptions.FPaintOptions then
NodeLeft := FIndent NodeLeft := FIndent
else
begin
if toShowRoot in FOptions.FPaintOptions then
NodeLeft := Integer((GetNodeLevel(Run) + 1) * FIndent)
else
NodeLeft := Integer(GetNodeLevel(Run) * FIndent);
end;
WithCheck := (toCheckSupport in FOptions.FMiscOptions) and Assigned(FCheckImages);
end
else else
begin begin
if toShowRoot in FOptions.FPaintOptions then NodeLeft := 0;
NodeLeft := Integer((GetNodeLevel(Run) + 1) * FIndent) WithCheck := False;
else
NodeLeft := Integer(GetNodeLevel(Run) * FIndent);
end; end;
WithCheck := (toCheckSupport in FOptions.FMiscOptions) and Assigned(FCheckImages); // Consider node margin at the left of the nodes.
end Inc(NodeLeft, FMargin);
else
begin
NodeLeft := 0;
WithCheck := False;
end;
// Consider node margin at the left of the nodes. // Decide where to stop.
Inc(NodeLeft, FMargin); if UseSmartColumnWidth then
LastNode := GetNextVisible(BottomNode)
else
LastNode := nil;
// Decide where to stop. while Assigned(Run) and not OperationCanceled do
if UseSmartColumnWidth then begin
LastNode := GetNextVisible(BottomNode) TextLeft := NodeLeft;
else if WithCheck and (Run.CheckType <> ctNone) then
LastNode := nil; Inc(TextLeft, CheckOffset);
if WithImages and HasImage(Run, ikNormal, Column) then
Inc(TextLeft, ImageOffset);
if WithStateImages and HasImage(Run, ikState, Column) then
Inc(TextLeft, StateImageOffset);
while Assigned(Run) and not OperationCanceled do CurrentWidth := DoGetNodeWidth(Run, Column);
begin Inc(CurrentWidth, DoGetNodeExtraWidth(Run, Column));
TextLeft := NodeLeft; Inc(CurrentWidth, DoGetCellContentMargin(Run, Column).X);
if WithCheck and (Run.CheckType <> ctNone) then
Inc(TextLeft, CheckOffset);
if WithImages and HasImage(Run, ikNormal, Column) then
Inc(TextLeft, ImageOffset);
if WithStateImages and HasImage(Run, ikState, Column) then
Inc(TextLeft, StateImageOffset);
CurrentWidth := DoGetNodeWidth(Run, Column); if Result < (TextLeft + CurrentWidth) then
Inc(CurrentWidth, DoGetCellContentMargin(Run, Column).X); Result := TextLeft + CurrentWidth;
if Result < (TextLeft + CurrentWidth) then // Get next visible node and update left node position if needed.
Result := TextLeft + CurrentWidth; NextNode := GetNextVisible(Run, True);
if NextNode = LastNode then
Break;
if (Column = Header.MainColumn) and not (toFixedIndent in FOptions.FPaintOptions) then
Inc(NodeLeft, CountLevelDifference(Run, NextNode) * Integer(FIndent));
Run := NextNode;
end;
if toShowVertGridLines in FOptions.FPaintOptions then
Inc(Result);
// Get next visible node and update left node position if needed. if Assigned(FOnAfterGetMaxColumnWidth) then
NextNode := GetNextVisible(Run, True); FOnAfterGetMaxColumnWidth(FHeader, Column, Result);
if NextNode = LastNode then
Break;
if (Column = Header.MainColumn) and not (toFixedIndent in FOptions.FPaintOptions) then
Inc(NodeLeft, CountLevelDifference(Run, NextNode) * Integer(FIndent));
Run := NextNode;
end;
if toShowVertGridLines in FOptions.FPaintOptions then
Inc(Result);
if Assigned(FOnAfterGetMaxColumnWidth) then
FOnAfterGetMaxColumnWidth(FHeader, Column, Result);
finally finally
EndOperation(okGetMaxColumnWidth); EndOperation(okGetMaxColumnWidth);
@ -28978,6 +29051,10 @@ var
SelectLevel: Integer; // > 0 if current node is selected or child/grandchild etc. of a selected node SelectLevel: Integer; // > 0 if current node is selected or child/grandchild etc. of a selected node
FirstColumn: TColumnIndex; // index of first column which is at least partially visible in the given window FirstColumn: TColumnIndex; // index of first column which is at least partially visible in the given window
MaxRight,
ColLeft,
ColRight: Integer;
SavedTargetDC: Integer; SavedTargetDC: Integer;
PaintWidth: Integer; PaintWidth: Integer;
CurrentNodeHeight: Integer; CurrentNodeHeight: Integer;
@ -29046,7 +29123,7 @@ begin
// Prepare the current selection rectangle once. The corner points are absolute tree coordinates. // Prepare the current selection rectangle once. The corner points are absolute tree coordinates.
SelectionRect := OrderRect(FNewSelRect); SelectionRect := OrderRect(FNewSelRect);
{$ifdef DEBUG_VTV}Logger.Send([lcPaintDetails, lcSelection],'SelectionRect', SelectionRect);{$endif} {$ifdef DEBUG_VTV}Logger.Send([lcPaintDetails, lcSelection],'SelectionRect', SelectionRect);{$endif}
DrawSelectionRect := IsMouseSelecting and not IsRectEmpty(SelectionRect); DrawSelectionRect := IsMouseSelecting and not IsRectEmpty(SelectionRect) and (GetKeyState(VK_LBUTTON) < 0);
{$ifdef DEBUG_VTV}Logger.Watch([lcPaintDetails],'DrawSelectionRect',DrawSelectionRect);{$endif} {$ifdef DEBUG_VTV}Logger.Watch([lcPaintDetails],'DrawSelectionRect',DrawSelectionRect);{$endif}
// R represents an entire node (all columns), but is a bit unprecise when it comes to // R represents an entire node (all columns), but is a bit unprecise when it comes to
// trees without any column defined, because FRangeX only represents the maximum width of all // trees without any column defined, because FRangeX only represents the maximum width of all
@ -29098,7 +29175,7 @@ begin
if Assigned(PaintInfo.Node) then if Assigned(PaintInfo.Node) then
begin begin
ButtonX := Round((Integer(FIndent) - FPlusBM.Width) / 2); ButtonX := Round((Integer(FIndent) - FPlusBM.Width) / 2) + 1;
// ----- main node paint loop // ----- main node paint loop
while Assigned(PaintInfo.Node) do while Assigned(PaintInfo.Node) do
@ -29111,7 +29188,7 @@ begin
SelectLevel := DetermineLineImageAndSelectLevel(PaintInfo.Node, LineImage); SelectLevel := DetermineLineImageAndSelectLevel(PaintInfo.Node, LineImage);
IndentSize := Length(LineImage); IndentSize := Length(LineImage);
if not (toFixedIndent in FOptions.FPaintOptions) then if not (toFixedIndent in FOptions.FPaintOptions) then
ButtonX := (IndentSize - 1) * FIndent + Round((FIndent - FPlusBM.Width) / 2); ButtonX := (IndentSize - 1) * Integer(FIndent) + Round((Integer(FIndent) - FPlusBM.Width) / 2) + 1;
// Initialize node if not already done. // Initialize node if not already done.
if not (vsInitialized in PaintInfo.Node.States) then if not (vsInitialized in PaintInfo.Node.States) then
@ -29540,30 +29617,40 @@ begin
R.Right := R.Left + Items[FirstColumn].FWidth; R.Right := R.Left + Items[FirstColumn].FWidth;
end; end;
// Initialize MaxRight.
MaxRight := Target.X - 1;
PaintInfo.Canvas.Font.Color := FColors.GridLineColor; PaintInfo.Canvas.Font.Color := FColors.GridLineColor;
while (FirstColumn <> InvalidColumn) and (R.Left < TargetRect.Right + Target.X) do while (FirstColumn <> InvalidColumn) and (MaxRight < TargetRect.Right + Target.X) do
begin begin
if (poGridLines in PaintOptions) and // Determine left and right coordinate of the current column
(toFullVertGridLines in FOptions.FPaintOptions) and ColLeft := Items[FirstColumn].Left;
(toShowVertGridLines in FOptions.FPaintOptions) and ColRight := (ColLeft + Items[FirstColumn].FWidth);
(not (hoAutoResize in FHeader.FOptions) or (Cardinal(FirstColumn) < TColumnPosition(Count - 1))) then
// Check wether this column needs to be painted at all.
if (ColRight >= MaxRight) then
begin begin
DrawDottedVLine(PaintInfo, R.Top, R.Bottom, R.Right - 1); R.Left := MaxRight; // Continue where we left off
Dec(R.Right); R.Right := ColRight; // Paint to the right of the column
MaxRight := ColRight; // And record were to start the next column.
if (poGridLines in PaintOptions) and
(toFullVertGridLines in FOptions.FPaintOptions) and
(toShowVertGridLines in FOptions.FPaintOptions) and
(not (hoAutoResize in FHeader.FOptions) or (Cardinal(FirstColumn) < TColumnPosition(Count - 1))) then
begin
DrawDottedVLine(PaintInfo, R.Top, R.Bottom, R.Right - 1);
Dec(R.Right);
end;
if not (coParentColor in Items[FirstColumn].FOptions) then
PaintInfo.Canvas.Brush.Color := Items[FirstColumn].FColor
else
PaintInfo.Canvas.Brush.Color := Color;
PaintInfo.Canvas.FillRect(R);
end; end;
if not (coParentColor in Items[FirstColumn].FOptions) then
PaintInfo.Canvas.Brush.Color := Items[FirstColumn].FColor
else
PaintInfo.Canvas.Brush.Color := Color;
PaintInfo.Canvas.FillRect(R);
FirstColumn := GetNextVisibleColumn(FirstColumn); FirstColumn := GetNextVisibleColumn(FirstColumn);
if FirstColumn <> InvalidColumn then
begin
R.Left := Items[FirstColumn].Left;
R.Right := R.Left + Items[FirstColumn].FWidth;
end;
end; end;
// Erase also the part of the tree not covert by a column. // Erase also the part of the tree not covert by a column.
@ -31854,6 +31941,21 @@ begin
Result := FOptions as TCustomStringTreeOptions; Result := FOptions as TCustomStringTreeOptions;
end; end;
//----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.GetStaticText(Node: PVirtualNode; Column: TColumnIndex): String;
begin
Assert(Assigned(Node), 'Node must not be nil.');
if not (vsInitialized in Node.States) then
InitNode(Node);
Result := '';
DoGetText(Node, Column, ttStatic, Result);
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.GetText(Node: PVirtualNode; Column: TColumnIndex): String; function TCustomVirtualStringTree.GetText(Node: PVirtualNode; Column: TColumnIndex): String;
@ -31927,6 +32029,7 @@ var
R: TRect; R: TRect;
DrawFormat: Cardinal; DrawFormat: Cardinal;
Size: TSize; Size: TSize;
Height: Integer;
begin begin
{$ifdef DEBUG_VTV}Logger.EnterMethod([lcPaintDetails],'PaintNormalText') ;{$endif} {$ifdef DEBUG_VTV}Logger.EnterMethod([lcPaintDetails],'PaintNormalText') ;{$endif}
@ -31936,6 +32039,7 @@ begin
R := ContentRect; R := ContentRect;
//todo_lcl See how TextStyle should be set //todo_lcl See how TextStyle should be set
//Canvas.TextFlags := 0; //Canvas.TextFlags := 0;
InflateRect(R, -FTextMargin, 0);
// Multiline nodes don't need special font handling or text manipulation. // Multiline nodes don't need special font handling or text manipulation.
// Note: multiline support requires the Unicode version of DrawText, which is able to do word breaking. // Note: multiline support requires the Unicode version of DrawText, which is able to do word breaking.
@ -31944,7 +32048,7 @@ begin
// for 9x/Me. // for 9x/Me.
if vsMultiline in Node.States then if vsMultiline in Node.States then
begin begin
InflateRect(R, -FTextMargin, 0); Height := ComputeNodeHeight(Canvas, Node, Column);
DoPaintText(Node, Canvas, Column, ttNormal); DoPaintText(Node, Canvas, Column, ttNormal);
// Disabled node color overrides all other variants. // Disabled node color overrides all other variants.
if (vsDisabled in Node.States) or not Enabled then if (vsDisabled in Node.States) or not Enabled then
@ -31955,10 +32059,13 @@ begin
DrawFormat := DT_NOPREFIX or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL or AlignmentToDrawFlag[Alignment]; DrawFormat := DT_NOPREFIX or DT_WORDBREAK or DT_END_ELLIPSIS or DT_EDITCONTROL or AlignmentToDrawFlag[Alignment];
if BidiMode <> bdLeftToRight then if BidiMode <> bdLeftToRight then
DrawFormat := DrawFormat or DT_RTLREADING; DrawFormat := DrawFormat or DT_RTLREADING;
// Center the text vertically if it fits entirely into the content rect.
if R.Bottom - R.Top > Height then
InflateRect(R, 0, (Height - R.Bottom - R.Top) div 2);
end end
else else
begin begin
InflateRect(R, -FTextMargin, 0);
FFontChanged := False; FFontChanged := False;
TripleWidth := FEllipsisWidth; TripleWidth := FEllipsisWidth;
DoPaintText(Node, Canvas, Column, ttNormal); DoPaintText(Node, Canvas, Column, ttNormal);
@ -32184,7 +32291,25 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.CalculateTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; const Text: String): Integer; function TCustomVirtualStringTree.CalculateStaticTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
const Text: String): Integer;
begin
Result := 0;
if (Length(Text) > 0) and (Alignment <> taCenter) and not
(vsMultiline in Node.States) and (toShowStaticText in TreeOptions.FStringOptions) then
begin
DoPaintText(Node, Canvas, Column, ttStatic);
Inc(Result, DoTextMeasuring(Canvas, Node, Column, Text).cx);
Inc(Result, FTextMargin);
end;
end;
//----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.CalculateTextWidth(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
const Text: String): Integer;
// Determines the width of the given text. // Determines the width of the given text.
@ -32273,6 +32398,17 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.DoGetNodeExtraWidth(Node: PVirtualNode; Column: TColumnIndex;
Canvas: TCanvas = nil): Integer;
begin
if Canvas = nil then
Canvas := Self.Canvas;
Result := CalculateStaticTextWidth(Canvas, Node, Column, StaticText[Node, Column]);
end;
//----------------------------------------------------------------------------------------------------------------------
function TCustomVirtualStringTree.DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer; function TCustomVirtualStringTree.DoGetNodeWidth(Node: PVirtualNode; Column: TColumnIndex; Canvas: TCanvas = nil): Integer;
// Returns the text width of the given node in pixels. // Returns the text width of the given node in pixels.