Delphi Tips 
-----------------------------

0220  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/26 西坂良幸 rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/26 西坂良幸 編集
ツリービューのノードをドラッグ&ドロップで移動させる


TTreeViewでは、DragImageにこだわらなければ,DragModeプロパティを dmAutomatic に設定すれば、OnDragOver、OnDragDropイベントを使うだけで簡単にできます。

OnDragOverイベントのAcceptは,ユーザーがドロップするオブジェクトをそのコントロールが受け入れることを示すだけです。

ツリー構造ですので、移動が無限ルーチンに陥らないように工夫します。
下記では、
IsFamilyメソッドで、ファミリー内にその上位ノードを移動するのか
を判定し、MoveNodeメソッドですべての子ノードが移動できるように
しています。

type
  TForm1 = class(TForm)
    // <省略>
    ・・・・・
    ・・・・・
  private
    procedure MoveNode(Parent, Source: TTreeNode);
    function IsFamily(Parent, Source: TTreeNode):boolean;
  public
  end;

    // <省略>
    ・・・・・
    ・・・・・

procedure TForm1.FormCreate(Sender: TObject);
var
  i:integer;
  Node:TTreeNode;
begin
  // 適当にtreeを作成
  for i := 1 to 20 do
  begin
    node := TreeView1.Items.Add(nil,'A00'+IntToStr(i));
    node.ImageIndex := 0;
    node.SelectedIndex := 1;
  end;
end;

// 移動と削除−−すべての子ノードを移動する
procedure TForm1.MoveNode(Parent, Source: TTreeNode);
var
  node: TTreeNode;
begin
  node := TreeView1.Items.AddChild(Parent,Source.Text);
  node.ImageIndex := Source.ImageIndex;
  node.SelectedIndex := Source.SelectedIndex;
  while Source.Count > 0  do
    // 再帰させる
    MoveNode(Node, TTreeNode(Source.Item[0]));
  Source.Delete;
end;

// Sourceの一族にParentがあれば true の判定
function TForm1.IsFamily(Parent, Source: TTreeNode):boolean;
var
  i:integer;
  node: TTreeNode;
begin
  result := false;
  for i := 0 to Source.Count - 1 do
  begin
    node := Source.Item[i];
    if Node.AbsoluteIndex = Parent.AbsoluteIndex then
      result := true
    else
      // 再帰させる
      result := IsFamily(Parent, Node);
    if result then break;
  end;
end;

// ドロップ後の処理
procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
Var
  Node:TTreeNode;
begin
  if (Sender is TTreeView) and (Source is TTreeView) then
  begin   //ツリーからツリー
    with Sender, Source as TTreeView do
    begin
      //新親の親
      Node := GetNodeAt(X,Y);
      if Node = Selected then
      begin
        MessageDlg('同じ所に移動はできません。', mtInformation, [mbOk], 0);
        Exit;
      end;
      //ツリーのアイテムを移動し削除
      Items.BeginUpdate;
      if IsFamily(Node, Selected) then
        //無限循環を避ける
        MessageDlg('この移動はできません。', mtInformation, [mbOk], 0)
      else
        MoveNode(Node, Selected);
      Items.EndUpdate;
    end;
  end;
end;

// ソースを確認する
procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  Accept := (Source as TTreeView) = TreeView1;
end;

参照: [Delphi-ML:3727] [Delphi-ML:22691] [Delphi-ML:30411] <Win95> <コンポーネント >

[新規作成] [最新の情報に更新]

How To
Lounge
KeyWords


Tips
Delphi
Home
Osamu Takeuchi osamu@big.or.jp