C++ Builder Tips


TreeViewで多段階層のノードのドラッグ&ドロップでの移動


TreeViewで多段階層のノードをその子ごとドラッグ&ドロップで移動をします。
まず、OnDragOverドラッグ部分を書きます。同じツリービュー内の移動か、ドラッグ先があるかを調べます。
次に、OnDragDropにドロップ部分を書きます。MoveNode()関数とIsSubFolder()関数は作成した関数です。
MoveNode()関数でノードの移動を行います。再帰関数でフォルダの下位階層をすべて移動するような動作をします。
IsSubFolder()関数です。フォルダ移動をそのフォルダのサブフォルダに対して行うと、MoveNode内の再帰で無限ループをしてしまいますのでそれをチェックするために使います。
void __fastcall TfMain::TreeViewDragOver(TObject *Sender, TObject *Source,
      int X, int Y, TDragState State, bool &Accept)
{
 TTreeView *pTree;
 TTreeNode *pNode;
 
 pTree = (TTreeView*)Source;
 pNode = TreeView->GetNodeAt(X,Y);
 
 if((pTree == TreeView) && (pNode!=NULL))
 {
  Accept = true;
 }
 else
 {
  Accept = false;
 }
}

void __fastcall TfMain::TreeViewDragDrop(TObject *Sender, TObject *Source,
      int X, int Y)
{
 TTreeNode *pNode;

 if(Sender == TreeView && Source == TreeView)
 {
  pNode = TreeView->GetNodeAt(X,Y);
  if(pNode == TreeView->Selected)
  {
      return;
  }
  else
  {
      if(IsSubFolder(TreeView->Selected,pNode))
      {
          AnsiString msg;
          msg = pNode->Text + "は" + TreeView->Selected->Text + "のサブフォルダです。\nサブフォルダには移動できません。";
          MessageBox(Handle,msg.c_str(),"警告",MB_OK);
      }
      else
      {
          TreeView->Items->BeginUpdate();
          MoveNode(TreeView->Selected,pNode);
          TreeView->Items->EndUpdate();
      }
  }
 }
}

void TfMain::MoveNode(TTreeNode* Source, TTreeNode* Destination)
{
 TTreeNode* newNode;
 
 newNode = TreeView->Items->AddChildObject(Destination,Source->Text,Source->Data);
 newNode->ImageIndex = Source->ImageIndex;
 newNode->SelectedIndex = Source->SelectedIndex;
 newNode->StateIndex = Source->StateIndex;
 
 while(Source->Count > 0) //再帰部分
 {
     MoveNode(Source->Item[0],newNode);
 }
 Source->Delete();
 TreeView->Selected = newNode;
}

bool TfMain::IsSubFolder(TTreeNode* Source, TTreeNode* Destination)
{
 TTreeNode* node;

 for(int i=0;i < Source->Count;i++)
 {
  node = Source->Item[i];
  if(node->AbsoluteIndex == Destination->AbsoluteIndex)
  {
   return true;
  }
  else
  {
   if(IsSubFolder(node,Destination))
   return true;
  }
 }
 return false;
}



目次に戻る
Copyright(c) 2008 WoodenSoldier Software