さて、ここで本当にトリッキーなものがあります...ヘッダーをChildNodeに描画/使用したいと思います。子ノードをテーブルで指定できるようにサブノードにヘッダーがあると見栄えがするので、このアイデアは合理的だと思います。VSTにある機能はありますか、それともまったく不可能ですか?
ご協力いただきありがとうございます。
さて、ここで本当にトリッキーなものがあります...ヘッダーをChildNodeに描画/使用したいと思います。子ノードをテーブルで指定できるようにサブノードにヘッダーがあると見栄えがするので、このアイデアは合理的だと思います。VSTにある機能はありますか、それともまったく不可能ですか?
ご協力いただきありがとうございます。
1.マスター/詳細グリッドビューにVirtualTreeViewを使用する方法はありますか?
いいえ、現時点ではそのような機能はありません。既存のコードへの非常に大きな介入が必要になるため、IMHOは利用できません。
2.子ノードの詳細グリッドビューの完全に機能するヘッダーを作成するにはどうすればよいですか?
いくつかの方法を考えると、子ノードのヘッダーの外観と動作をシミュレートする方法は、詳細グリッドビューにネストされたツリービューを使用すると便利だと思いました。これにより、詳細データが分離され、シミュレーション全体を最小化して、ネストされたツリービューを子ノードの長方形に配置することができます。
2.1。スタートアッププロジェクト
次のプロジェクトでは、子ノード内でのコントロールの配置などの簡単なタスクを実装するのがどれほど複雑になるかを示しています(元のVirtualTreeコードは含まれていません)。最終的な解決策としてではなく、スタートアッププロジェクトとしてそれをとってください。
2.2。既知の問題と制限:
OnExpanded
実装では、範囲とスクロールの位置が修正される前にイベントが発生します。これにより、コードがより複雑になり、大きな弱点があります。詳細ツリービューの境界は、ツリーが表示された後に更新されます。2.3。プロジェクトコード
Delphi 7での使用に関して、Delphi 2009で作成およびテストされました。次のコードのコメント付きバージョンの場合follow this link
:
Unit1.pas
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, VirtualTrees;
type
TVTScrollBarsUpdateEvent = procedure(Sender: TBaseVirtualTree; DoRepaint: Boolean) of object;
TVirtualStringTree = class(VirtualTrees.TVirtualStringTree)
private
FOnUpdateScrollBars: TVTScrollBarsUpdateEvent;
public
procedure UpdateScrollBars(DoRepaint: Boolean); override;
published
property OnUpdateScrollBars: TVTScrollBarsUpdateEvent read FOnUpdateScrollBars write FOnUpdateScrollBars;
end;
type
PNodeSubTree = ^TNodeSubTree;
TNodeSubTree = class
FChildTree: TVirtualStringTree;
end;
type
TForm1 = class(TForm)
Button1: TButton;
VirtualStringTree1: TVirtualStringTree;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure VirtualStringTree1AfterAutoFitColumns(Sender: TVTHeader);
procedure VirtualStringTree1BeforeDrawTreeLine(Sender: TBaseVirtualTree;
Node: PVirtualNode; Level: Integer; var PosX: Integer);
procedure VirtualStringTree1Collapsed(Sender: TBaseVirtualTree;
Node: PVirtualNode);
procedure VirtualStringTree1ColumnResize(Sender: TVTHeader;
Column: TColumnIndex);
procedure VirtualStringTree1Expanded(Sender: TBaseVirtualTree;
Node: PVirtualNode);
procedure VirtualStringTree1FocusChanging(Sender: TBaseVirtualTree; OldNode,
NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex;
var Allowed: Boolean);
procedure VirtualStringTree1FreeNode(Sender: TBaseVirtualTree;
Node: PVirtualNode);
procedure VirtualStringTree1MeasureItem(Sender: TBaseVirtualTree;
TargetCanvas: TCanvas; Node: PVirtualNode; var NodeHeight: Integer);
private
procedure InvalidateSubTrees(Tree: TBaseVirtualTree);
procedure ResizeSubTrees(Tree: TBaseVirtualTree);
procedure UpdateSubTreeBounds(Tree: TBaseVirtualTree; Node: PVirtualNode);
procedure OnUpdateScrollBars(Sender: TBaseVirtualTree; DoRepaint: Boolean);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TVirtualStringTree }
procedure TVirtualStringTree.UpdateScrollBars(DoRepaint: Boolean);
begin
inherited;
if HandleAllocated and Assigned(FOnUpdateScrollBars) then
FOnUpdateScrollBars(Self, DoRepaint);
end;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
ReportMemoryLeaksOnShutdown := True;
VirtualStringTree1.NodeDataSize := SizeOf(TNodeSubTree);
VirtualStringTree1.OnUpdateScrollBars := OnUpdateScrollBars;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Data: PNodeSubTree;
Node: PVirtualNode;
begin
Node := VirtualStringTree1.AddChild(nil);
Node := VirtualStringTree1.AddChild(Node);
VirtualStringTree1.InitNode(Node);
Data := VirtualStringTree1.GetNodeData(Node);
Data^ := TNodeSubTree.Create;
Data^.FChildTree := TVirtualStringTree.Create(nil);
with Data.FChildTree do
begin
Visible := False;
Parent := VirtualStringTree1;
Height := 150;
DefaultNodeHeight := 21;
Header.AutoSizeIndex := 0;
Header.Font.Charset := DEFAULT_CHARSET;
Header.Font.Color := clWindowText;
Header.Font.Height := -11;
Header.Font.Name := 'Tahoma';
Header.Font.Style := [];
Header.Height := 21;
Header.Options := [hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible];
TabStop := False;
with Header.Columns.Add do
begin
Width := 100;
Text := 'Header item 1';
end;
with Header.Columns.Add do
begin
Width := 100;
Text := 'Header item 2';
end;
end;
end;
procedure TForm1.VirtualStringTree1AfterAutoFitColumns(Sender: TVTHeader);
begin
InvalidateSubTrees(Sender.Treeview);
end;
procedure TForm1.VirtualStringTree1BeforeDrawTreeLine(Sender: TBaseVirtualTree;
Node: PVirtualNode; Level: Integer; var PosX: Integer);
begin
if Level = 1 then
PosX := 0;
end;
procedure TForm1.VirtualStringTree1Collapsed(Sender: TBaseVirtualTree;
Node: PVirtualNode);
var
Data: PNodeSubTree;
begin
Data := VirtualStringTree1.GetNodeData(Node.FirstChild);
if Assigned(Data^) and Assigned(Data^.FChildTree) then
Data^.FChildTree.Visible := False;
end;
procedure TForm1.VirtualStringTree1ColumnResize(Sender: TVTHeader;
Column: TColumnIndex);
begin
ResizeSubTrees(Sender.Treeview);
end;
procedure TForm1.VirtualStringTree1Expanded(Sender: TBaseVirtualTree;
Node: PVirtualNode);
var
Data: PNodeSubTree;
begin
Data := VirtualStringTree1.GetNodeData(Node.FirstChild);
if Assigned(Data^) and Assigned(Data^.FChildTree) then
Data^.FChildTree.Visible := True;
end;
procedure TForm1.VirtualStringTree1FocusChanging(Sender: TBaseVirtualTree;
OldNode, NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex;
var Allowed: Boolean);
begin
if Sender.GetNodeLevel(NewNode) = 1 then
begin
Allowed := False;
if Sender.AbsoluteIndex(OldNode) > Sender.AbsoluteIndex(NewNode) then
Sender.FocusedNode := Sender.GetPreviousSibling(OldNode)
else
if OldNode <> Sender.GetLastChild(nil) then
Sender.FocusedNode := Sender.GetNextSibling(OldNode)
else
Sender.FocusedNode := OldNode;
end;
end;
procedure TForm1.VirtualStringTree1FreeNode(Sender: TBaseVirtualTree;
Node: PVirtualNode);
var
Data: PNodeSubTree;
begin
Data := VirtualStringTree1.GetNodeData(Node);
if Assigned(Data^) then
begin
if Assigned(Data^.FChildTree) then
Data^.FChildTree.Free;
Data^.Free;
end;
end;
procedure TForm1.VirtualStringTree1MeasureItem(Sender: TBaseVirtualTree;
TargetCanvas: TCanvas; Node: PVirtualNode; var NodeHeight: Integer);
var
Data: PNodeSubTree;
begin
if VirtualStringTree1.GetNodeLevel(Node) = 1 then
begin
Data := VirtualStringTree1.GetNodeData(Node);
if Assigned(Data^) and Assigned(Data^.FChildTree) then
NodeHeight := Data^.FChildTree.Height + 8;
end;
end;
procedure TForm1.InvalidateSubTrees(Tree: TBaseVirtualTree);
var
Data: PNodeSubTree;
Node: PVirtualNode;
begin
Node := Tree.GetFirst;
while Assigned(Node) do
begin
if Tree.HasChildren[Node] then
begin
Data := Tree.GetNodeData(Node.FirstChild);
if Assigned(Data^) and Assigned(Data^.FChildTree) then
begin
Data^.FChildTree.Header.Invalidate(nil);
Data^.FChildTree.Invalidate;
end;
end;
Node := Tree.GetNextSibling(Node);
end;
end;
procedure TForm1.ResizeSubTrees(Tree: TBaseVirtualTree);
var
Node: PVirtualNode;
begin
Node := Tree.GetFirst;
while Assigned(Node) do
begin
if Tree.HasChildren[Node] then
UpdateSubTreeBounds(Tree, Node.FirstChild);
Node := Tree.GetNextSibling(Node);
end;
end;
procedure TForm1.UpdateSubTreeBounds(Tree: TBaseVirtualTree; Node: PVirtualNode);
var
R: TRect;
Data: PNodeSubTree;
begin
if Assigned(Node) then
begin
Data := Tree.GetNodeData(Node);
if Assigned(Data^) and Assigned(Data^.FChildTree) and
Data^.FChildTree.Visible then
begin
R := Tree.GetDisplayRect(Node, -1, False, True);
R.Left := R.Left + (Tree as TVirtualStringTree).Indent;
R.Top := R.Top + 4;
R.Right := R.Right - 8;
R.Bottom := R.Bottom - 4;
Data^.FChildTree.BoundsRect := R;
end;
end;
end;
procedure TForm1.OnUpdateScrollBars(Sender: TBaseVirtualTree; DoRepaint: Boolean);
begin
ResizeSubTrees(Sender);
end;
end.
Unit1.dfm
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 282
ClientWidth = 468
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
DesignSize = (
468
282)
PixelsPerInch = 96
TextHeight = 13
object VirtualStringTree1: TVirtualStringTree
Left = 8
Top = 8
Width = 371
Height = 266
Anchors = [akLeft, akTop, akRight, akBottom]
Header.AutoSizeIndex = 0
Header.Font.Charset = DEFAULT_CHARSET
Header.Font.Color = clWindowText
Header.Font.Height = -11
Header.Font.Name = 'Tahoma'
Header.Font.Style = []
Header.Height = 21
Header.Options = [hoColumnResize, hoDblClickResize, hoDrag, hoShowSortGlyphs, hoVisible]
TabOrder = 0
TreeOptions.MiscOptions = [toVariableNodeHeight]
OnAfterAutoFitColumns = VirtualStringTree1AfterAutoFitColumns
OnBeforeDrawTreeLine = VirtualStringTree1BeforeDrawTreeLine
OnCollapsed = VirtualStringTree1Collapsed
OnColumnResize = VirtualStringTree1ColumnResize
OnExpanded = VirtualStringTree1Expanded
OnFocusChanging = VirtualStringTree1FocusChanging
OnFreeNode = VirtualStringTree1FreeNode
OnMeasureItem = VirtualStringTree1MeasureItem
ExplicitWidth = 581
ExplicitHeight = 326
Columns = <
item
Position = 0
Width = 75
WideText = 'Column 1'
end
item
Position = 1
Width = 75
WideText = 'Column 2'
end
item
Position = 2
Width = 75
WideText = 'Column 3'
end>
end
object Button1: TButton
Left = 385
Top = 8
Width = 75
Height = 25
Anchors = [akTop, akRight]
Caption = 'Button1'
TabOrder = 1
OnClick = Button1Click
ExplicitLeft = 595
end
end
2.4。スクリーンショット