⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tree_util.cpp

📁 用C++制作家谱
💻 CPP
字号:
//----------------------------------------------------------------------------
//
//  tree_util.cpp
//  Chapter 30 - How To - Tree View Component Example
//
//  Paul Gustavson
//  pgustavson@simventions.com
//
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "tree_util.h"

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <olectl.h>  // for the CoCreateGuid call

//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
void __fastcall MoveUpTree(TTreeNode *item)
{
     if (item == NULL)
     {
	MessageBeep(MB_OK);
	return;
     }
     TNodeAttachMode AttachMode = naInsert;

     TTreeNode *ppItem = item->getPrevSibling();

     int level = item->Level;
     if (ppItem == NULL)
     {
          MessageBeep(MB_OK);
          return;
     }
     if (ppItem->Level != level)
     {
          MessageBeep(MB_OK);
          return;
     }
     item->MoveTo(ppItem, AttachMode);
}


//---------------------------------------------------------------------------
int __fastcall FindTreeNodeBasedOnLabel(TTreeNodes *Tree,AnsiString SearchString)
{
     TTreeNode *CurItem = Tree->GetFirstNode();
     if (CurItem) do
     {
          AnsiString title = CurItem->Text;
          StripParenCount(title);
          if (AnsiCompareStr(title,SearchString) == 0)
                       return CurItem->AbsoluteIndex;
          CurItem = CurItem->GetNext();
     } while (CurItem);
     return -1;  // couldn't find it..
}


//---------------------------------------------------------------------------
int  __fastcall FindTreeNodeBasedOnID(TTreeNodes *Tree,unsigned int ID)
{

     TTreeNode *CurItem = Tree->GetFirstNode();
    int count =0;
     if (CurItem) do
     {
          if (CurItem->Data)
          {
              if (PInfo(CurItem->Data)->ID == ID)
              {
                     return CurItem->AbsoluteIndex;
              }
              count++;
          }

          CurItem = CurItem->GetNext();
     } while (CurItem);
     return -1;  // couldn't find it..
}


//---------------------------------------------------------------------------
void __fastcall AddCountToNode(TTreeNodes* tree)
{
     tree->BeginUpdate();
     TTreeNode *CurItem = tree->GetFirstNode();
     while (CurItem)    //walk down all the nodes of the tree
     {
        CurItem->Count;
        AnsiString NewName = CurItem->Text;
        StripParenCount(NewName);

        if (CurItem->Count > 0)
             CurItem->Text = NewName + "  (" + CurItem->Count + ")";
        else
             CurItem->Text = NewName;
        CurItem = CurItem->GetNext();
     }
     tree->EndUpdate();
}


//---------------------------------------------------------------------------
bool __fastcall StripParenCount(AnsiString &text)
{
    AnsiString NewName;
    bool result = true;
    int location = text.AnsiPos("  (");
    if (location > 0)
    {
         NewName = text.SubString(1,(location-1));
         result = true;
    }
    else  // nothing to strip
    {
         result = false;
         return result;
    }
    text = NewName;
    return result;
}
//---------------------------------------------------------------------------

TInfo::TInfo()      // constructor
{
        type = 0;
        ID = 0;
        deleted = false;
        Name = "";
}


//---------------------------------------------------------------------------
TPersonalInfo::TPersonalInfo()    // constructor
{
	FirstName = "";
	LastName = "";
	DOB = ""; // Date of birth
	DOD = ""; // Date of death
        BirthPlace = "";
        Epitath = "";
        Residence = "";
        Gender = true;    // true = male, false = female
        Occupation = "";
        Notes = "";
        Mother = NULL;
        Father = NULL;
}
//---------------------------------------------------------------------------

void TPersonalInfo::DetermineParent(TPersonalInfo* parent)
{
    if (!parent)
        return;
    LastName = parent->LastName;
    if (parent->Gender) // parent is male, than fill in father info
        Father = parent;
    else
        Mother = parent;
}
//---------------------------------------------------------------------------

bool __fastcall AddToUndoRedoList(TTreeNodes * Tree, unsigned int ID, TInfo *info, int imageindex, bool deletedflag)
{
  // look for items that already have the ID we're going to insert and delete it...
   int index = 0;
   do
   {
        index = FindTreeNodeBasedOnID(Tree,ID);
        if (index != -1) Tree->Item[index]->Delete();
   } while (index > -1);

   // okay, now we can add it.
   TTreeNode *node = Tree->AddObjectFirst(NULL,info->Name,info);
   node->StateIndex = imageindex;
   node->ImageIndex = imageindex;
   info->deleted = deletedflag;

   return  (bool)Tree->Count;
}
//---------------------------------------------------------------------------

unsigned int __fastcall GetNewID()
{
    GUID guid;
    ::CoCreateGuid(&guid);
    return guid.Data1;
}
//---------------------------------------------------------------------------

void __fastcall ClearAll(TTreeNodes* tree)
{
     TTreeNode *CurItem = tree->GetFirstNode();
     TInfo *info;
     while (CurItem)    //walk down all the nodes of the tree and delete data
     {
        if (CurItem->Data)
        {
                info = (TInfo*)( CurItem->Data);
                delete info;
        }
        CurItem = CurItem->GetNext();
     }
     // now that all the data is deleted, the tree can be delete
     tree->Clear();
}

//---------------------------------------------------------------------------
void __fastcall ClearDeletedItems(TTreeNodes* tree)   // makes soft deletes hard deletes
{
     tree->BeginUpdate();  // prevent screen update of tree view
     TTreeNode *CurItem = tree->GetFirstNode();
     TTreeNode *NextItem;
     TInfo *info;
     while (CurItem)    //walk down all the nodes of the tree and delete appropriate nodes
     {
        NextItem = CurItem->GetNext();   // keep track of potential next node
        if (CurItem->Data)
        {
            info = (TInfo*)(CurItem->Data);
            if (info->deleted)
                NextItem = DeleteNode(CurItem,false,false,NULL); // hard delete, no message, no undo list
        }
        CurItem = NextItem;
     }
     tree->EndUpdate();  // enabled screen update
}


//---------------------------------------------------------------------------
TTreeNode* __fastcall DeleteNode(TTreeNode *node, bool displaymessage, bool soft, TTreeNodes * undolist)
{
// recursive function

    if (!node) return NULL;  // no tree node.. get out
    TTreeNode *tempnode = NULL;

    // take care of children first
    int count = node->Count;
    while (count > 0)  // can't use HasChildren property for soft deletes
    {
        int response = IDYES;
        if (displaymessage)
        {
           // notify user of branch deletion
          response =
              Application->MessageBox("Are you sure you wish to delete branch?",
                    "Node Has Children", MB_YESNO);
        }
        if (response == IDNO)
        {
            MessageBeep(MB_OK);
            return NULL;
        }
        else
        {
            displaymessage = false;
            tempnode =  node->GetPrevChild(tempnode);
            if (tempnode == NULL)
                tempnode = node->GetLastChild();
            if (tempnode)
                    DeleteNode(tempnode,false,soft,NULL);  // call itself with next child,
            //messages are no longer displayed (false), no need for undo list (NULL)
            if (!soft)
                    tempnode = NULL;
        }
        count--; // decrment children count
    }
    if (soft) // soft delete (undo support)
    {
        TInfo * info;
        if (node->Data)
            info = (TInfo*)(node->Data);
        else
        {   // better add data in case the user hits undo
            // Here's where we add the information to the tree
            info = new TPersonalInfo;
            info->ID = GetNewID();   // get a unique id
            info->Name = node->Text;
            node->Data = (void*)info; // now add it as an object to the node
        }
        info->deleted = true;  // mark it for deletion
        if (undolist)
            AddToUndoRedoList(undolist,info->ID, info, node->ImageIndex,true);
        node->OverlayIndex = 0;
        return node->GetNext();  // return the next node
    }
    else // hard delete (no undo support)
    {
        TTreeNode* nextnode = node->GetNext(); // get the next node before we delete it
        if (node->Data)
        {
                TInfo * info = (TInfo*)(node->Data);
                delete info;           // delete data
        }
        node->Delete();     // delete node
        return nextnode;
    }
}
//---------------------------------------------------------------------------

void __fastcall UndeleteNode(TTreeNode *node)   // this is recursive too
{
   if (!node) return;
   TTreeNode* tempnode = NULL;
   int count = node->Count;  // check the children
   while (count > 0)
   {
          tempnode =  node->GetNextChild(tempnode);
          if (tempnode == NULL)
              tempnode = node->getFirstChild();
          if (tempnode)
                  UndeleteNode(tempnode);
          count--;
   }
   node->OverlayIndex = -1;
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -