立即前往

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
查看全部活动
热门活动
  • 智算采购季 热销S6云服务器2核4G限时88元/年起,部分主机可加赠对象存储组合包!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 一键部署Llama3大模型学习机 0代码一键部署,预装最新主流大模型Llama3与StableDiffusion
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 产品能力
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      C++ N 叉树在 CLI 中的应用

      首页 知识中心 软件开发 文章详情页

      C++ N 叉树在 CLI 中的应用

      2024-11-19 09:36:19 阅读次数:19

      CLI,应用

      应用:

      C++ N 叉树在 CLI 中的应用

       C++ N 叉树在 CLI 中的应用

       C++ N 叉树在 CLI 中的应用

       _Tree.h

      /*******************************************************************************************
      文件名							: _Tree.h
      
      
      功能								: 树型数据结构
      
      创建时间							: 2016年07月31日
      
      最后一次修改时间				    :  2023年01月01日
      ********************************************************************************************/
      #ifndef __TREE_H_
      #define __TREE_H_
      
      #ifdef _CLR_
          using namespace System::Windows::Forms;
      #endif
      
      
      #include "_List.h"
      #include "_Color.h"
      #include "_Font.h"
      #include "_DataType.h"
      #include "_KeyBinaryFile.h"
      
      #define  _NTREENODE_DEBUG_
      //#define _NTREE_DEBUG_
      
      _LF_BEGIN_
      
      
      /// <summary>
      /// 二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,
      /// 而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分 [1]  。二叉树是n个
      /// 有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合
      /// 为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点
      /// </summary>
      class _BTreeNode : public _Object
      {
      public:
      
          /// <summary>
          /// 键值,在所有节点中都是唯一的
          /// </summary>
          __int64 KeyValue;
      
      
          /// <summary>
          /// 所带的二进制数据
          /// </summary>
          _ByteArray Data;
      
      
          /// <summary>
          /// 所带的二进制数据类型
          /// </summary>
          _DataType  DataType;
      
      
          /// <summary>
          /// 在树型控件中显示的文本
          /// </summary>
          _string DispalyText;
      
      
          /// <summary>
          /// 在树型控件中显示文本的字体颜色
          /// </summary>
          _Color DisplayForeColor;
      
          /// <summary>
          /// 在树型控件中显示显示文本的背景颜色
          /// </summary>
          _Color DisplayBackColor;
      
      
          /// <summary>
          /// 在树型控件中显示显示的字体
          /// </summary>
          _Font DispalyFont;
      
      
          __int64 LeftKeyValue;
          __int64 RightKeyValue;
      
          _BTreeNode* Left;
          _BTreeNode* Right;
      
      };
      
      
      
      
      class _BTree
      {
      private:
          _BTreeNode  _root;
      
      
      };
      
      
      
      
      /// <summary>
      /// N叉树
      /// </summary>
      class _NTreeNode : public _Object
      {
      private:
      
          void InitData(const _string& sDispalyText = _t(""));
      
      public:
          /// <summary>
          /// 分隔字符串
          /// </summary>
          static const _string SplitString;
      
      public:
          /// <summary>
         /// 键值,在所有节点中都是唯一的
         /// </summary>
          __int64 KeyValue;
      
      
          /// <summary>
          /// 所带的二进制数据
          /// </summary>
          _ByteArray Data;
           
      
          /// <summary>
          /// 在树型控件中显示的文本
          /// </summary>
          _string DispalyText;
      
      
          /// <summary>
          /// 在树型控件中显示文本的字体颜色
          /// </summary>
          _Color DisplayForeColor;
      
          /// <summary>
          /// 在树型控件中显示显示文本的背景颜色
          /// </summary>
          _Color DisplayBackColor;
      
      
          /// <summary>
          /// 在树型控件中显示显示的字体
          /// </summary>
          _Font DispalyFont;
      
      
          /// <summary>
          /// 第一个子结点键值
          /// </summary>
          __int64 FirstChildKeyValue;
           
          /// <summary>
          /// 下一个兄弟结点键值
          /// </summary>
          __int64 NextSiblingKeyValue;
      
      
      
          /// <summary>
          /// 所带的二进制数据类型
          /// </summary>
          _DataType  DataType;
      
      public:
      
          /// <summary>
          /// 第一个子结点
          /// </summary>
          _NTreeNode* FirstChild;
      
          /// <summary>
          /// 下一个兄弟结点
          /// </summary>
          _NTreeNode* NextSibling;
      
      public:
      
      
      
          /// <summary>
          /// 判断 tnChild 是否 tnParent 的直系子结点,如果是,则返回 true
          /// </summary>
          /// <param name="tnChild"></param>
          /// <returns></returns>
          /// 创建时间:2022-07-18 最后一次修改时间:2022-07-18
          bool IsMyChild(const _NTreeNode* pChild);
      
      
      
          /// <summary>
          /// 判断 tnChild 是否父结点,如果是,则返回 true
          /// </summary>
          /// <param name="tnParent">父结点</param>
          /// <returns></returns>
          /// 创建时间:2022-07-18 最后一次修改时间:2022-07-18
          bool IsMyParent(const _NTreeNode* pParent);
      
      public:
      
      
          _NTreeNode();
          _NTreeNode(const _string sDisplayText);
      
          _NTreeNode(const _NTreeNode&  Node);
      
      
      
          _string GetPackageDataAdd(const bool& IsOldVersion)const;
      
      
          /// <summary>
          /// 把其他八种数据打包进 Data 数据中
          /// </summary>
          /// <param name="IsOldVersion"></param>
          _ByteArray& PackageData(_ByteArray& baResult, const bool& IsOldVersion);
      
          /// <summary>
          /// 分拆打包后的数据
          /// </summary>
          /// <param name="IsOldVersion"></param>
          void SplitData(const bool &IsOldVersion);
      };
      
      
      
      /// <summary>
      /// N叉树,此N叉树要求有且只有一个根节点
      /// </summary>
      class _NTree : public _Object
      {
      private:
      
          //固定名子,原来用控件名子,但是一旦控件名字更改,就是个bug,文件打不开了。
          static const _string ConstName;
      
      private:
          /// <summary>
          /// 根节点
          /// </summary>
          _NTreeNode* _Root = null;
      
          /// <summary>
          /// 节点数
          /// </summary>
          int  _Count; 
      
           
      
          /// <summary>
          /// 当前操作的文件名
          /// </summary>
          _string _FullPathName = _t("");
       
      private:
          int _DeleteSolitaryNode(const _NTreeNode* pDelete);
          void _GetNodeChildrenAll(const  _NTreeNode* pParent, _DList<_NTreeNode*>& dResult)const;
      
      
      public:  //--------------------------------------------------------------属性
      
          /// <summary>
          /// 设置文件名
          /// </summary>
          /// <param name="sFullPathName"></param>
          inline void SetFullPathName(const _string& sFullPathName) { _FullPathName = sFullPathName; }
      
          /// <summary>
          /// 获取文件名
          /// </summary>
          /// <returns></returns>
          inline const _string& GetFullPathName()const { return _FullPathName; }
      
          /// <summary>
          /// 返回结点数
          /// </summary>
          /// <returns></returns>
          inline int Count() const { return _Count; }
      
      
          /// <summary>
          /// 返回根节点
          /// </summary>
          /// <returns></returns>
          inline  _NTreeNode* Root()const { return _Root; }
           
          /// <summary>
          /// 文件内容是否更改
          /// </summary>
          bool IsModify = false;
      
      public:
          /// <summary>
          /// 清空内存
          /// </summary>
          /// <param name="pNode"></param>
          void ClearMemory();
      
      
          inline ~_NTree() {
      #ifdef _NTREE_DEBUG_
              d.PrintError(_t("inline ~_NTree()"));
      #endif
              ClearMemory(); 
          }
      
      
          inline _NTree() { 
      #ifdef _NTREE_DEBUG_
              d.PrintError(_t("inline _NTree()"));
      #endif
              _Count = 0;
              _Root = null; 
          }     
      
      public:
          void _FindNode(const  _NTreeNode* pFindStart, const _NTreeNode* pNode, _DList<const _NTreeNode*>& dResult);
          _DList<_NTreeNode*> GetNodeAll() const;
      
      public:
      
          _NTreeNode* FindIsFirstChild(const _NTreeNode* pFindStart, const _NTreeNode* pFind); 
          _NTreeNode* FindPrent(const _NTreeNode* pStart, const _NTreeNode* pChild);  
          _NTreeNode* FindPrevSibling(const _NTreeNode* pStart, const _NTreeNode* pNode);    
          _NTreeNode* GetLastSibling(const _NTreeNode* pFirstSibling);
          _DList<const _NTreeNode*> FindNode(const _NTreeNode* pNode);
          _NTreeNode* AddNode(_NTreeNode* pParent, const _NTreeNode* pNode);
          _NTreeNode* AddNode(_NTreeNode* pParent, const _string& sDisplayText);
       
       
      
          bool RemoveNode(const _NTreeNode* pRemove);
      
      
          _string BuildInFile(const _string& sFullPathName);
      
      
        
          _NTreeNode* Find(const _DList<_NTreeNode*>& tnList, const __int64& iKeyValue)const;
          _NTreeNode* Find(const _DList<_NTreeNode*>& tnList, const _string& sKeyValue)const;
      
          _NTreeNode* Find(const _NTreeNode* tnFindStart, const __int64& iKeyValue)const;
          _NTreeNode* Find(const _NTreeNode* tnFindStart, const _string& sKeyValue)const;
      
          void SaveSiblingAndChild(_NTreeNode* pNode, _KeyBinaryFile& kbf);
           
          inline _NTreeNode* FindKeyValue(const _string &sKeyValue) { return Find(_Root, sKeyValue.ToInt64()); }
      
      
          /// <summary>
          /// 以 char 表示的二进制数据
          /// </summary>
          /// <returns></returns>
          _StrA GetFirstNodeDataA()const;
      
          /// <summary>
          /// 以 wchar 表示的二进制数据
          /// </summary>
          /// <returns></returns>
          _StrW GetFirstNodeDataW()const;
      
          /// <summary>
          /// 以 char 表示的二进制数据
          /// </summary>
          /// <returns></returns>
          void SetFirstNodeData(const _StrA&sData);
       
          void Display()const;
          void Display(const _NTreeNode* pNode,const int nLevel = 1)const;
      
      #if _CLR_
           
      
          void BuildInTreeView(TreeView^ tv, TreeNode^ tnParent, const _NTreeNode* pNode, int nImageIndex);
          void BuildInTreeView(TreeView^ tv,const int iImageIndex = -1);
      
          _StrW GetTreeNodeDataW(TreeNode^ tn);
          _StrA GetTreeNodeDataA(TreeNode^ tn);
      
          void Save(TreeView^ tv, const _string& sFullPathName, bool bReWrite = false);
      
          inline void Save(TreeView^ tv) { Save(tv, _FullPathName, true); }
       
      
          void AfterLabelEdit_Event(Object^ sender, NodeLabelEditEventArgs^ e);
      
       
          void UpdateTreeViewNode(TreeView^ tv, TreeNode^ tnModify, String^ sDispalyText = _t(""));
      
          void TreeViewSelectedNodeDelete(TreeView^ tv);
       
          void TreeViewSelectedNodeAddNewNode(TreeView^ tv, String^ sDisplayText = _t("新节点"));
           
          void ChangeSelectedNodeData(TreeView^ tv, String^ sData);
       
      
       
          void AfterLabelEdit_Event(TreeView^ tv, Object^ sender, NodeLabelEditEventArgs^ e);
      
          void TreeViewNodeAttributeChange(TreeNode^ tnNode);
      
          void ItemDrag_Event(TreeView^ tv, Object^ sender, ItemDragEventArgs^ e);
      
          void DragDrop_Event(TreeView^ tv, Object^ sender, DragEventArgs^ e);
       
          void DragEnter_Event(TreeView^tv, Object^ sender, DragEventArgs^ e);
      
          _NTreeNode* GetinitTreeViewTreeNode(TreeView^tv, String^ sText);
       
          TreeNode^ TreeViewAddRootNode(TreeView^ tv, String^ sText);
        
          String^ TreeViewSelectNodeMoveUp(TreeView^ tv);
      
       
          String^ TreeViewSelectNodeMoveDown(TreeView^ tv);
       
       
      #endif
       
      };
       
      
       
      /// <summary>
      /// 数据树
      /// </summary>
      class _TreeViewData : public _Object
      {
      
      };
      
      
      _LF_END_
      
       
      
      
      
      
      
      #endif // !_LF_LTREE_H_
      

      Tree.cpp

      #include "_Tree.h"
      #include "global_c_all.h"
      
      _LF_BEGIN_
      
      
      const _string _NTreeNode::SplitString = _t("||||");
      
       
      
      void _NTreeNode::InitData(const _string& sDispalyText)
      {
      
      #ifdef _NTREENODE_DEBUG_
          //_cout << _t("void _NTreeNode::InitData(const _string& sDispalyText)\n");
      #endif
      
          KeyValue = _DataTime::GetTimeStamp(); //键值,在所有节点中都是唯一的
      
          //Data  //所带的二进制数据
      
          DataType = _DataType::dtWChar; // 所带的二进制数据类型
      
          DispalyText = _t("新节点");//在树型控件中显示的文本
      
          DisplayForeColor = _Color::Black; //在树型控件中显示文本的字体颜色
      
          DisplayBackColor = _Color::White; //在树型控件中显示显示文本的背景颜色
      
          DispalyFont = _Font();  //在树型控件中显示显示的字体
      
          FirstChildKeyValue = -1;  //第一个子结点键值
      
          FirstChild = null;  //第一个子结点
      
          NextSiblingKeyValue = -1;  //下一个兄弟结点键值
      
          NextSibling = null;      //下一个兄弟结点
      }
      
      _NTreeNode::_NTreeNode()
      {
          InitData();
      
      }
      
      _NTreeNode::_NTreeNode(const _string sDisplayText)
      {
          InitData();
          DispalyText = sDisplayText;
      }
      
      
      _NTreeNode::_NTreeNode(const _NTreeNode& Node)
      {  
          KeyValue = Node.KeyValue; //键值,在所有节点中都是唯一的
      
          Data = Node.Data; //所带的二进制数据
      
          DataType = Node.DataType;// 所带的二进制数据类型
      
          DispalyText = Node.DispalyText;//在树型控件中显示的文本
      
          DisplayForeColor = Node.DisplayForeColor;//在树型控件中显示文本的字体颜色
      
          DisplayBackColor = Node.DisplayBackColor;//在树型控件中显示显示文本的背景颜色
      
          DispalyFont = Node.DispalyFont;//在树型控件中显示显示的字体
      
          FirstChildKeyValue = Node.FirstChildKeyValue;//第一个子结点键值
      
          FirstChild = Node.FirstChild;//第一个子结点
      
          NextSiblingKeyValue = Node.NextSiblingKeyValue;//下一个兄弟结点键值
      
          NextSibling = Node.NextSibling;//下一个兄弟结点
      }
      
      _string _NTreeNode::GetPackageDataAdd(const bool& IsOldVersion) const
      {
          if (IsOldVersion)  //旧版本在磁盘中保存 7 + 1(Data) 个字段
          {
      #if _CLR_
              //Data |||| KeyValue |||| FirstChildKeyValue |||| NextSiblingKeyValue ||||  DispalyText |||| DisplayForeColor |||| DisplayBackColor |||| DispalyFont + ||||  Length 
      
              // Length  = |||| KeyValue |||| FirstChildKeyValue |||| NextSiblingKeyValue ||||  DispalyText |||| DisplayForeColor |||| DisplayBackColor |||| DispalyFont + ||||
      
      
      
              if (KeyValue == -1 || DispalyText.Length == 0 || DispalyText == _t("") )
                  throw gcnew Exception(L"KeyValue == -1 || DispalyText == null ||  DispalyText == "" || DispalyFont == null");
      
              _string sAdd(_t(""), 1000);
      
              sAdd.Add(SplitString);
              sAdd.Add(KeyValue.ToString());
              sAdd.Add(SplitString);
              sAdd.Add(FirstChildKeyValue.ToString());
              sAdd.Add(SplitString);
              sAdd.Add(NextSiblingKeyValue.ToString());
              sAdd.Add(SplitString);
              sAdd.Add(DispalyText);
              sAdd.Add(SplitString);
      
      
              System::Drawing::ColorConverter^ cc = gcnew System::Drawing::ColorConverter();
              String^ tmp = cc->ConvertToString((Color)DisplayForeColor);
              sAdd.Add(tmp);
              sAdd.Add(SplitString);
      
      
              tmp = cc->ConvertToString((Color)DisplayBackColor);
              sAdd.Add(tmp);
              sAdd.Add(SplitString);
      
      
              System::Drawing::FontConverter^ fc = gcnew System::Drawing::FontConverter();
              tmp = fc->ConvertToString(DispalyFont);
              sAdd.Add(tmp);
              sAdd.Add(SplitString);
      
      
      
              sAdd.Add(sAdd.Length.ToString());
      
              return sAdd;        
      #else
              d.PrintError(_t("_string _NTreeNode::GetPackageDataAdd(const bool& IsOldVersion) const: 代码未完成!"));
      #endif
          }
          else //新版本在磁盘中保存 8 + 1(Data) 个字段 , 个了一个 DataType
          {
              /*
              //Data |||| KeyValue |||| FirstChildKeyValue |||| NextSiblingKeyValue ||||  DispalyText |||| DisplayForeColor |||| DisplayBackColor |||| DispalyFont + |||| + DataType + |||| + Length 
      
              // Length  = |||| KeyValue |||| FirstChildKeyValue |||| NextSiblingKeyValue ||||  DispalyText |||| DisplayForeColor |||| DisplayBackColor |||| DispalyFont + |||| DataType + ||||
      
              if (KeyValue == -1 || DispalyText == null || DispalyText == _t("") )
                  throw gcnew Exception(L"KeyValue == -1 || DispalyText == null ||  DispalyText == "" || DispalyFont == null");
      
              _string sAdd(_t(""), 1000);
      
              sAdd.Add(SplitString);
              sAdd.Add(KeyValue.ToString());
              sAdd.Add(SplitString);
              sAdd.Add(FirstChildKeyValue.ToString());
              sAdd.Add(SplitString);
              sAdd.Add(NextSiblingKeyValue.ToString());
              sAdd.Add(SplitString);
              sAdd.Add(DispalyText);
              sAdd.Add(SplitString);
      
      
              System::Drawing::ColorConverter^ cc = gcnew System::Drawing::ColorConverter();
              String^ tmp = cc->ConvertToString((Color)DisplayForeColor);
              sAdd.Add(tmp);
              sAdd.Add(SplitString);
      
      
              tmp = cc->ConvertToString((Color)DisplayBackColor);
              sAdd.Add(tmp);
              sAdd.Add(SplitString);
      
      
              System::Drawing::FontConverter^ fc = gcnew System::Drawing::FontConverter();
              tmp = fc->ConvertToString(DispalyFont);
              sAdd.Add(tmp);
              sAdd.Add(SplitString);
               
      
              tmp = ((int)DataType).ToString();
              sAdd.Add(tmp);
              sAdd.Add(SplitString);
      
      
              sAdd.Add(sAdd.Length.ToString());
      
              return sAdd;
      
              */
      
              d.PrintError(_t("_string _NTreeNode::GetPackageDataAdd(const bool& IsOldVersion) const: 代码未完成!"));
          }
      
      
          return _t("");
      
      }
      
      
      
      /// <summary>
      /// 把其他八种数据打包进 Data 数据中
      /// </summary>
      /// <param name="IsOldVersion"></param>
      /// 创建时间:????-??-?? 最后一次修改时间:2023-01-04
      _ByteArray& _NTreeNode::PackageData(_ByteArray &baResult, const bool& IsOldVersion)
      {
          baResult.ClearMemory();
      
          if (IsOldVersion)
          {
              baResult.Add(Data);
      
              _string s = GetPackageDataAdd(IsOldVersion);
               
              baResult.Add((_byte*)s.Data, s.Length * sizeof(_char));
          }
          else
          {
      
              //打包九个字段
      
      
              _ByteArray  baTemp;
      
              //Data.Length +  Data 
              //KeyValue 
              //FirstChildKeyValue 
              //NextSiblingKeyValue  
              //DispalyText  
              //DisplayForeColor  
              //DisplayBackColor 
              //DispalyFont 
              //DataType  
      
              //------------------------------------------Data
              baResult.SetBuffer(Data.Length + 200);
       
      
              baResult.AddInt(Data.Length);
              baResult.Add(Data.Data, Data.Length);
      
              //---------------------------------------KeyValue
              baResult.AddInt64(KeyValue);
      
              //---------------------------------------FirstChildKeyValue
              baResult.AddInt64(FirstChildKeyValue);
      
              //---------------------------------------NextSiblingKeyValue
              baResult.AddInt64(NextSiblingKeyValue);
      
              //---------------------------------------DispalyText
              baResult.AddInt(DispalyText.DataMemoryLength);
              baResult.Add((_byte*)DispalyText.Data,DispalyText.DataMemoryLength);
      
              //---------------------------------------DisplayForeColor
              baResult.AddInt(DisplayForeColor.PackageMemory(baTemp).Length);
              baResult.Add(baTemp.Data, baTemp.Length);
      
              //---------------------------------------DisplayBackColor
              baResult.AddInt(DisplayBackColor.PackageMemory(baTemp).Length);
              baResult.Add(baTemp.Data, baTemp.Length);
             
              //---------------------------------------DispalyFont
              baResult.AddInt(DispalyFont.PackageMemory(baTemp).Length);
              baResult.Add(baTemp.Data, baTemp.Length);
      
              //---------------------------------------DataType
              baResult.AddInt((int)DataType);        
               
          }
      
          return baResult;
      }
      
      
      
      /// <summary>
      /// 分拆打包后的数据
      /// </summary>
      /// <param name="IsOldVersion"></param>
      /// 创建时间:????-??-?? 最后一次修改时间:2023-01-04
      void _NTreeNode::SplitData(const bool& IsOldVersion)
      { 
          if (IsOldVersion)//旧版本在磁盘中保存 7 + 1(Data) 个字段
          {
      #if _CLR_
              //Data |||| KeyValue |||| FirstChildKeyValue |||| NextSiblingKeyValue ||||  DispalyText |||| DisplayForeColor |||| DisplayBackColor |||| DispalyFont + ||||  Length 
      
              // Length  = |||| KeyValue |||| FirstChildKeyValue |||| NextSiblingKeyValue ||||  DispalyText |||| DisplayForeColor |||| DisplayBackColor |||| DispalyFont + ||||
      
              _string NewData = _t("");
      
              //_string tmp(_t(""), Data.Length);
              //tmp.Add((_char*)Data.Data, Data.Length / sizeof(_char));
      
              _string tmp;
              tmp.TrusteeshipMem(Data.Data, Data.MemoryLength);
              Data.GiveUpMem();
               
      
      
              int nLengthStart = tmp.LastIndexOf(SplitString);
      
              if (nLengthStart == -1)
                  throw gcnew Exception("nLengthStart = -1");
      
      
              _string sLength = tmp.SubStr(nLengthStart + SplitString.Length, tmp.Length - nLengthStart - SplitString.Length);
      
              
              if (!sLength.IsArabicDigitString())
                  throw gcnew Exception("!sLength->isNumberString()");
      
      
              int nAttribute = System::Convert::ToInt32(sLength);
      
      
              NewData = tmp.SubStr(0, tmp.Length - nAttribute - sLength.Length);
      
      
              _string sAttribute = tmp.SubStr(NewData.Length + SplitString.Length, nAttribute - SplitString.Length - SplitString.Length);
      
              _StringList ls(sAttribute, SplitString, false);
      
      
              if (ls.Count != 7)
                  throw gcnew Exception( _t("sAttribute = ") + sAttribute + "分隔sAttribute错误, ls->Count != 7");
      
      
              KeyValue = System::Convert::ToInt64(ls[0]);
      
              FirstChildKeyValue = System::Convert::ToInt64(ls[1]);
      
              NextSiblingKeyValue = System::Convert::ToInt64(ls[2]);
      
              DispalyText = ls[3];
      
              System::Drawing::ColorConverter^ cc = gcnew System::Drawing::ColorConverter();
              DisplayForeColor = (System::Drawing::Color)cc->ConvertFromString(ls[4]);
              DisplayBackColor = (System::Drawing::Color)cc->ConvertFromString(ls[5]);
      
      
              System::Drawing::FontConverter^ fc = gcnew System::Drawing::FontConverter();
              DispalyFont = (System::Drawing::Font^)fc->ConvertFromString(ls[6]);
               
              
              Data.TrusteeshipMem(NewData);
      #else
              d.ThrowException(_t("void _NTreeNode::SplitData(const bool& IsOldVersion): 代码未完成!"));
      #endif
          }
          else
          {
              /*
              //打包九个字段
      
      
              _ByteArray  baNew, baTemp;
      
              //Data.Length +  Data 
              //KeyValue 
              //FirstChildKeyValue 
              //NextSiblingKeyValue  
              //DispalyText  
              //DisplayForeColor  
              //DisplayBackColor 
              //DispalyFont 
              //DataType  
      
              //------------------------------------------Data
              baNew.SetBuffer(Data.Length + 200);
       
      
              baNew.AddInt(Data.Length);
              baNew.Add(Data.Data, Data.Length);       
      
              //---------------------------------------KeyValue
              baNew.AddInt64(KeyValue);
      
              //---------------------------------------FirstChildKeyValue
              baNew.AddInt64(FirstChildKeyValue);
      
              //---------------------------------------NextSiblingKeyValue
              baNew.AddInt64(NextSiblingKeyValue);
      
              //---------------------------------------DispalyText
              baNew.AddInt(DispalyText.GetDataMemoryLength);
              baNew.Add((_byte*)DispalyText.Data,DispalyText.GetDataMemoryLength);
      
              //---------------------------------------DisplayForeColor
              baNew.AddInt(DisplayForeColor.PackageMemory(baTemp).Length);
              baNew.Add(baTemp.Data, baTemp.Length);
      
              //---------------------------------------DisplayBackColor
              baNew.AddInt(DisplayBackColor.PackageMemory(baTemp).Length);
              baNew.Add(baTemp.Data, baTemp.Length);
             
              //---------------------------------------DispalyFont
              baNew.AddInt(DispalyFont.PackageMemory(baTemp).Length);
              baNew.Add(baTemp.Data, baTemp.Length);
      
              //---------------------------------------DataType
              baNew.AddInt(DataType);
               
              Data.TrusteeshipMem(baNew); //释放本身内存,托管其它对象
              */
      
              //拆分九个字段
      
      
              _ByteArray  baAll;
              baAll.TrusteeshipMem(Data);
      
              _byte* p = baAll.Data;
      
      
              //-----------------------------Data
              int n = *(int*)p;
              p += sizeof(int);
      
              Data.ClearMemory();
              Data.Add(p, n);
      
              p += n;
      
              //-----------------------------KeyValue
              KeyValue = *(__int64*)p;
              p += sizeof(__int64);
      
              //-----------------------------FirstChildKeyValue
              FirstChildKeyValue = *(__int64*)p;
              p += sizeof(__int64);
      
              //-----------------------------NextSiblingKeyValue
              NextSiblingKeyValue = *(__int64*)p;
              p += sizeof(__int64);
      
              //-----------------------------DispalyText
              n = *(int*)p;
              p += sizeof(int);
              DispalyText.Clear();
              DispalyText.Add((_char*)p, n / sizeof(_char));
              p += n;
      
              //-----------------------------DisplayForeColor
              n = *(int*)p;
              p += sizeof(int);
              DisplayForeColor.SplitFromMemory(p);
      
              p += n;
      
              //-----------------------------DisplayBackColor
              n = *(int*)p;
              p += sizeof(int);
              DisplayBackColor.SplitFromMemory(p);
      
              p += n;
      
      
              //-----------------------------DispalyFont
              n = *(int*)p;
              p += sizeof(int);
              DispalyFont.SplitFromMemory(p);
      
              p += n;
      
      
              //-----------------------------DataType
              DataType = (_DataType) (*(int*)p);
      
          }
      }
      
      
      bool _NTreeNode::IsMyChild(const _NTreeNode* pChild)
      {
          if (pChild == null) return false;
      
          _NTreeNode* pTemp = FirstChild;
      
          while (pTemp != null)
          {
              if (pTemp == pChild)
                  return true;
      
              pTemp = pTemp->NextSibling;
          }
      
          return false;
      }
      
      bool _NTreeNode::IsMyParent(const _NTreeNode* pParent)
      {
          if (pParent == null) return false;
      
          const _NTreeNode* pTemp = pParent->FirstChild;
      
          while (pTemp != null)
          {
              if (pTemp == this)
                  return true;
      
              pTemp = pTemp->NextSibling;
          }
      
          return false;
      }
       
      
      
      
      
      //------------------------------------------------------------------------------------_NTree 定义
      
      const _string _NTree::ConstName = _t("TreeView");
      
      
      
      
      
      
      /// <summary>
      /// 判断pFind是否pFindStart或者pFindStart下面任何一个节点的第一个子节点,如果不是返回NULL,否则返回它的父节点。
      /// </summary>
      /// <param name="pFindStart">查找开始位置</param>
      /// <param name="pFind">所查找的节点</param>
      /// <returns>找到则返回父节点,否则返回NULL</returns>
      _NTreeNode* _NTree::FindIsFirstChild(const _NTreeNode* pFindStart, const _NTreeNode* pFind)
      {
          if (pFindStart == pFind || pFindStart == null) return null;
      
          _NTreeNode* pNode = (_NTreeNode*)pFindStart;
      
          while (pNode != null)
          {
              if (pNode->FirstChild == pFind)
                  return pNode;
              else
              {
                  _NTreeNode* pTemp = FindIsFirstChild(pNode->FirstChild, pFind);
                  if (pTemp != null)
                      return pTemp;
              }
              pNode = pNode->NextSibling;
          }
          return null;
      }
      
      
      /// <summary>
      /// 遍历所有节点,查找它的子结点,如果子结点包含 pChild,则返回此结点
      /// </summary>
      /// <param name="pStart">开始位置</param>
      /// <param name="pChild">子结点</param>
      /// <returns></returns>
      /// 创建时间:2022-07-18 最后一次修改时间:2023-01-02
      _NTreeNode* _NTree::FindPrent(const _NTreeNode* pStart, const _NTreeNode* pChild)
      {
          if (pStart == null || pChild == null || pStart == pChild ) return null;
      
          _NTreeNode* pTemp = (_NTreeNode*)pStart;
      
          while (pTemp != null)
          { 
              if (pTemp->IsMyChild(pChild))
                  return pTemp;
      
              _NTreeNode* pResult = FindPrent(pTemp->FirstChild, pChild);
      
              if (pResult != null)
              {
      
                  return pResult;
              }
      
              pTemp = pTemp->NextSibling;
          }
      
      
          return null;
      }
      
      
      /// <summary>
      /// 从tnStart处遍历二叉树,查找 pNode的上一个兄弟节点
      /// </summary>
      /// <param name="pStart">查找开始处</param>
      /// <param name="pNode">查找的节点</param>
      /// <returns>找到则返回上一个兄弟节点,否则返回NULL</returns>
      /// 创建时间:????-??-?? 最后一次修改时间:2022-07-18
      _NTreeNode* _NTree::FindPrevSibling(const _NTreeNode* pStart, const _NTreeNode* pNode)
      {
          if (pStart == pNode || pStart == null)
              return null;
      
          _NTreeNode* tn = (_NTreeNode * )pStart;
      
          while (tn != null)
          {
              if (tn->NextSibling == pNode)
                  return tn;
              else
              {
                  if (tn->FirstChild != null)
                  {
                      _NTreeNode* tmp = FindPrevSibling(tn->FirstChild, pNode);
      
                      if (tmp != null)
                          return tmp;
                  }
              }
      
              tn = tn->NextSibling;
          }
      
          return null;
      }
      
      
      /// <summary>
      /// 获取pNode最后一个兄弟节点
      /// </summary>
      /// <param name="pFirstSibling"></param>
      /// <returns></returns>
      _NTreeNode* _NTree::GetLastSibling(const _NTreeNode* pNode)
      {
          if (pNode == null) return null;
      
          _NTreeNode* pTemp = pNode->NextSibling;
      
          if (pTemp == null)
          {
              return (_NTreeNode*)pNode;
          }
          else
          { 
              while (true)
              {
                  if (pTemp->NextSibling == null)
                  {
                      return pTemp;
                  }
                  else
                  {
                      pTemp = pTemp->NextSibling;
                  }
              }
          }
      }
      
      
      /// <summary>
      /// 删除从树型目录独立出来的孤链,返回删除的个数
      /// </summary>
      /// <param name="pDelete"></param>
      /// <returns></returns>
      /// 创建时间:2023-01-05 最后一次修改时间:2023-01-08
      int _NTree::_DeleteSolitaryNode(const _NTreeNode* pDelete)
      {
          _DList< _NTreeNode*> dl;
          _GetNodeChildrenAll(pDelete, dl);
           
          auto p = dl.First();
      
          while (p != null)
          {
      
      #ifdef  _NTREE_DEBUG_
              d.PrintError( _t("int _NTree::_DeleteSolitaryNode(const _NTreeNode* pDelete):") + p->Data->DispalyText);
      #endif
              _Memory::Delete<_NTreeNode>(p->Data,1);
      
              p = p->Next;
          }
      
          _Count = _Count - dl.Count;
      
          return dl.Count;
      }
      
      
      
      /// <summary>
      /// 删除结点
      /// </summary>
      /// <param name="pRemove"></param>
      /// <returns></returns>
      /// 创建时间:2023-01-05 最后一次修改时间:2023-01-08
      bool _NTree::RemoveNode(const _NTreeNode* pRemove)
      {
          if (pRemove == null) return false;
      
          if (_Root == pRemove) //删除根节点
          {
              ClearMemory();
              return true;
          }
           
          _NTreeNode* pParent = FindPrent(_Root, pRemove);
      
          if (pParent == null) //没有父结点,又不是根结点
          {
              d.ThrowException(_t("bool _NTree::RemoveNode(const _NTreeNode * pRemove) : N叉树构建错误!"));
          }
          else  //在这里删除 pRemove
          { 
              _NTreeNode*  pPrev = this->FindPrevSibling(_Root, pRemove);  //上一个亲兄弟节点
              _NTreeNode* pNext = pRemove->NextSibling;   //下一个兄弟结点
              if (pPrev != null) //有上一个兄弟结点
              {
                  if (pNext != null) //有上一个兄弟结点,也有下一个兄弟节点
                  {
                      pPrev->NextSibling = pNext;
                      pPrev->NextSiblingKeyValue = pNext->KeyValue;
                      _DeleteSolitaryNode(pRemove);
                  }
                  else //有上一个兄弟结点,没有下一下亲兄弟节眯
                  {
                      pPrev->NextSibling = null;
                      pPrev->NextSiblingKeyValue = -1;
                      _DeleteSolitaryNode(pRemove);
                  }
              }
              else  //没有上一个兄弟结点,那么它是它父结点的第一个子结点
              {
                  if (pNext != null)  
                  {
                      pParent->FirstChild = pNext;
                      pParent->FirstChildKeyValue = pNext->KeyValue;
                      _DeleteSolitaryNode(pRemove);
                  }
                  else //没有兄弟结点,是单独的一个子结点
                  {
                      pParent->FirstChild = null;
                      pParent->FirstChildKeyValue = - 1;
      
                      _DeleteSolitaryNode(pRemove);
                  }
              }
      
              return true;
          }
      }
      
      
      
      /// <summary>
      /// 从文件中建立树,返回上次TreeNode最后一次所选节点Name       
      /// </summary>
      /// <returns></returns>
      /// <exception cref="Exception"></exception>
      /// 创建时间:????-??-?? 最后一次修改时间:2023-01-05
      _string _NTree::BuildInFile(const _string& sFullPathName)
      {
          ClearMemory();  //清除数据     
      
          _FullPathName = sFullPathName;
      
          _KeyBinaryFile kbf(sFullPathName);
      
          kbf.Open();
           
      
          //CSharp_slist ls = kbf->getIncludeKeyList(tvName + CSharp_TreeViewTreeNode^->m_Split);
          //这里有一个 bug ,旧的 TreeView 建立的,在新的TreeView显示不了,因为这跟名子相关,TreeView控件名子变了,为了不改动大量的代码
          //每次文件保存时,写入TreeView控件的名子 
          //String tvName = kbf->getString("Last_TreeView_Name", "");
      
          /*
          String tvName = kbf->getString("Last_TreeView_Name", "");
      
          if (tvName == "") //旧的文件是显示不了的,但是用新版本程序保存一下时,就可以显示出来了。
          {
              tvName = m_TreeView->Name;
              lg->ShowError("无法读取最后写入文件时TreeView控件的名子,将启用新的默认TreeView控件名称。", "BuildInFile");
          }
          */
      
          _StringList ls = kbf.GetIncludeKeyList(_NTree::ConstName + _NTreeNode::SplitString);
      
      
          //d.PrintError(ls.ToString());
           
      
          //以前版本的 constName 都是 TreeView 控件的名子,一旦控件名子改了,就建立不了数据了。
          //-------------------------------------------------------------------------------------版本兼容
          _string  oldConstName = _t("");
          if (ls.Count == 0)
          {
              ls = kbf.GetIncludeKeyList(_NTreeNode::SplitString);
      
              if (ls.Count > 0)
              {
                  oldConstName = _StringList(ls[0], _NTreeNode::SplitString, false)[0];
              } 
          }
          else
          {
              oldConstName = ConstName;
          }
      
      
          //------------------------------------------------------------------------------------------------
      
      
      
          if (ls.Count == 0) return _t("-1");
      
      
      
          _DList<_NTreeNode*> tnList;
      
          for (int i = 0; i < ls.Count; ++i)
          {
      
              _KeyData* kd = kbf.GetData(ls[i]);
              _Count = 0;
              if (kd != null)
              {
                  _NTreeNode* tnNew = _Memory::New< _NTreeNode>(1);
                  ++_Count; //计数器,计算分配的内存个数。
      
                  tnNew -> Data = kd->Data;
                  tnNew->SplitData(kbf.IsOldVersion());
                  tnList.Add(tnNew);
              }        
          }
      
      
          //建立关系
          _DListNode<_NTreeNode*>* dn = tnList.First();
      
          while (dn != null)
          {
              _NTreeNode* tvtn = dn->Data;
              _NTreeNode* tn = null;
      
              if (tvtn->FirstChildKeyValue != -1)
              {
                  tn = Find(tnList, tvtn->FirstChildKeyValue);
                  if (tn == null)
                  {
                      _string sError = _t("_string _NTree::BuildInFile(const _string& sFullPathName):无法找到FirstChild!");
                      d.ThrowException(sError);
                  }
                  else
                      tvtn->FirstChild = tn;
              }
      
              if (tvtn->NextSiblingKeyValue != -1)
              {
                  tn = Find(tnList, tvtn->NextSiblingKeyValue);
                  if (tn == null)
                  {
                      _string sError = _t("_string _NTree::BuildInFile(const _string& sFullPathName):无法找到NextSibling!");
                      d.ThrowException(sError);
                  }      
                  else
                      tvtn->NextSibling = tn;
              }
      
              dn = dn->Next;
          }
      
         
      
          //--------------------------------------建立树,设置根节点
      
          //建立First节点
          _string sFirstKeyValue = kbf.GetString(oldConstName + _t("_First"), _t(""));
          _string sSelectName = kbf.GetString(oldConstName + _t("_Select"), _t(""));
      
          kbf.ClearData();
           
      
          int n = ls.IndexOf(oldConstName + _NTreeNode::SplitString + sFirstKeyValue);
      
          //d.PrintError(oldConstName + _NTreeNode::SplitString + sFirstKeyValue);
           
          if (n != -1)
          {
              _Root = tnList[n]; //建立根节点
      
          }
          else
          {
              _string sError = _t("_string _NTree::BuildInFile(const _string& sFullPathName):不能建立First节点!");
              d.ThrowException(sError);
               
          }     
      
           
          return sSelectName;  
            
      }
      
      
      
      
      /// <summary>
      /// 清除内存
      /// </summary>
      void _NTree::ClearMemory() 
      { 
          _DList<_NTreeNode*>  dlAll;
           
          _GetNodeChildrenAll(_Root, dlAll);
      
          _DListNode<_NTreeNode*> *pNode = dlAll.First();
      
          while (pNode != null)
          {
              _Memory::Delete< _NTreeNode>(pNode->Data, 1);
      
              pNode = pNode->Next;
          }
          _Root = null;
          _Count = 0;
      }
      
      /// <summary>
      ///  遍历整个树,查找指针值相等 或者 KeyVlue 相等的节点,如果不是返回 1 或 0,说明建立的树是错误树。
      /// </summary>
      /// <param name="pFindStart"></param>
      /// <param name="pChild"></param>
      /// <param name="dResult"></param>
      /// </summary>    /// 创建时间:2023-01-02 最后一次修改时间:2023-01-02
      void _NTree::_FindNode(const  _NTreeNode* pFindStart, const _NTreeNode* pNode, _DList<const _NTreeNode*>& dResult)
      { 
          if (pNode == null || pFindStart == null) return;
           
      
          if (pFindStart == pNode || pFindStart->KeyValue == pNode->KeyValue)
          {
              dResult.Add(pFindStart);     
          }
      
          _NTreeNode* pTemp = (_NTreeNode*)pFindStart->FirstChild;
      
          while (pTemp != null)
          {
              _FindNode(pTemp, pNode, dResult);
      
              pTemp = pTemp->NextSibling;
          }
      }
      
      
      _DList<_NTreeNode*> _NTree::GetNodeAll() const
      {
          _DList<_NTreeNode*> dlResult;
      
          _GetNodeChildrenAll(_Root, dlResult);
      
          return dlResult;
        
      }
      
      
      /// <summary>
      /// 获取 pParent结点下的所有子结点,包括 pParent
      /// </summary>
      /// <param name="pStart"></param>
      /// <param name="dResult"></param>
      /// 创建时间:2023-01-02 最后一次修改时间:2023-01-05
      void _NTree::_GetNodeChildrenAll(const _NTreeNode* pParent, _DList<_NTreeNode*>& dResult)const
      {
          if (pParent == null) return;
             
       
          dResult.Add((_NTreeNode * )pParent);
      
          _NTreeNode* pTemp = (_NTreeNode*)pParent->FirstChild;
      
      
          while (pTemp != null)
          {
              _GetNodeChildrenAll(pTemp,dResult);
                
              pTemp = pTemp->NextSibling;
          }
      }
      
      
      /// <summary>
      /// 查找一个节点,如果KeyValue的值相等,也视为找到,找不到返回空链表值.
      /// </summary>
      /// <param name="pChild"></param>
      /// <returns></returns>
      /// 创建时间:2023-01-02 最后一次修改时间:2023-01-02
      _DList<const _NTreeNode*> _NTree::FindNode(const _NTreeNode* pNode)
      {
          _DList<const _NTreeNode*> dResult;
      
          _FindNode(_Root, pNode, dResult);
           
          return dResult;
      }
      
      
      
      /// <summary>
      /// 添加一个节点,如果父节点pParent为null,则默认添加到根节点中,
      /// 如果没有根节点,则添加的节点就是根节点,返回新添加的节点的指针。
      /// 这里不检查 pParent 是否树中的一个结点
      /// </summary>
      /// <param name="pParent"></param>
      /// <param name="pChild"></param>
      /// <returns></returns>
      /// 创建时间:2023-01-02 最后一次修改时间:2023-01-09
      _NTreeNode* _NTree::AddNode(_NTreeNode* pParent, const _NTreeNode* pNode)
      {
          if (_Root == null)
          {
              if (pParent != null) return null;
      
              _Root = _Memory::New< _NTreeNode>(1);
      
              *_Root = *pNode;
              _Root->FirstChild = null;
              _Root->NextSibling = null;
              _Count = 1;
      
              return _Root;
          }
      
           
          if (pParent == null && pNode == null) return null;
      
          if (pNode->FirstChild != null || pNode->NextSibling != null)
          {
              _string Error = _t("_NTreeNode* _NTree::AddChild(const _NTreeNode* pParent, const _NTreeNode* pChild): 只能添加一个孤立的节点!");
              d.PrintError(Error);
              throw Error;
          }
      
      
          _NTreeNode* pNew = _Memory::New< _NTreeNode>(1);
      
          *pNew = *pNode;
       
      
          
          //获取最后一个兄弟节点
          _NTreeNode* pLast = GetLastSibling(pParent->FirstChild);
      
          if (pLast == null)
          {
              pParent->FirstChild = pNew;
              pParent->FirstChildKeyValue = pNew->KeyValue;
          }
          else
          {
              pLast->NextSibling = pNew;
              pLast->NextSiblingKeyValue = pNew->KeyValue;
          }
      
      
          ++_Count;
      
          return pNew;
      }
      
      /// <summary>
      /// 添加一个节点,如果父节点pParent为null,则默认添加到根节点中,
      /// 如果没有根节点,则添加的节点就是根节点,返回新添加的节点的指
      /// 针。这里不检查 pParent 是否树中的一个结点
      /// </summary>
      /// <param name="tnList"></param>
      /// <param name="iFirstChildKeyValue"></param>
      /// <returns></returns>
      /// 创建时间:2023-01-17 最后一次修改时间:2023-01-17
      _NTreeNode* _NTree::AddNode(_NTreeNode* pParent, const _string& sDisplayText)
      {
      
          _NTreeNode* pNode  = _Memory::New<_NTreeNode>(1);
      
          pNode->DispalyText = sDisplayText;
      
      
          if (pParent == null)
          {
              if (_Root == null) {
                  _Root = pNode;
              }
              else
              {
                  _NTreeNode* pLast = GetLastSibling(_Root->FirstChild);
      
                  if (pLast == null)
                  {
                      _Root->FirstChild = pNode;
                      _Root->FirstChildKeyValue = pNode->FirstChildKeyValue;
                  }
                  else
                  {
                      pLast->NextSibling = pNode;
                      pLast->NextSiblingKeyValue = pNode->KeyValue;
                  }
              }
          }
          else
          {
              _NTreeNode* pLast = GetLastSibling(pParent->FirstChild);
      
              if (pLast == null)
              {
                  pParent->FirstChild = pNode;
                  pParent->FirstChildKeyValue = pNode->FirstChildKeyValue;
              }
              else
              {
                  pLast->NextSibling = pNode;
                  pLast->NextSiblingKeyValue = pNode->KeyValue;
              }
          }
      
      
          ++_Count;
      
          return pNode;
      }
      
      
      /// <summary>
      /// 在LDlist列表中查找键值为 iKeyValue 的结点
      /// </summary>
      /// <param name="tnList"></param>
      /// <param name="iFirstChildKeyValue"></param>
      /// <returns></returns>
      /// 创建时间:????-??-?? 最后一次修改时间:2022-07-18
      _NTreeNode* _NTree::Find(const _DList<_NTreeNode*>& tnList, const __int64& iKeyValue)const
      {
          _DListNode<_NTreeNode*>* tn = tnList.First();
      
          while (tn != null)
          {
              if (tn->Data->KeyValue == iKeyValue)
                  return tn->Data;
              tn = tn->Next;
          }
          return null;
      }
      
       
      _NTreeNode* _NTree::Find(const _DList<_NTreeNode*>& tnList, const _string& sKeyValue)const
      {
          return Find(tnList, sKeyValue.ToInt64());
      }
      
      /// <summary>
      /// 在结点 tnFindStart 中的子结点中查找节点键值为 iKeyValue 的结点,包括结点 tnFindStart
      /// </summary>
      /// <param name="tnFindStart">开始查找的结点</param>
      /// <param name="iKeyValue">键值</param>
      /// <returns>返回第一次出现的结点</returns>
      /// <exception cref="Exception"></exception>
      /// 创建时间:????-??-?? 最后一次修改时间:2022-07-18
      _NTreeNode* _NTree::Find(const _NTreeNode* tnFindStart, const __int64 &iKeyValue)const
      {
      
          if (tnFindStart == null || iKeyValue == -1)
              d.ThrowException(_t("_NTreeNode* _NTree::Find(const _NTreeNode* tnFindStart, const Int64 &iKeyValue): tnFindStart == null ||  iKeyValue == -1"));
      
          if (_Root == null)      return null;
      
          _NTreeNode* tnTmp = (_NTreeNode * )tnFindStart;
      
          while (tnTmp != null)
          {
              if (tnTmp->KeyValue == iKeyValue)  //查找节点本身
              {
                  return tnTmp;
              }
              else
              {
                  //查找节点的子节点
                  if (tnTmp->FirstChild != null)
                  {
                      _NTreeNode* tnFind = Find((_NTreeNode*)tnTmp->FirstChild, iKeyValue);
                      if (tnFind != null)
                      {
                          return tnFind;
                      }
                  }
              }
      
              //如果都还没找到,继续查找兄弟节点
              tnTmp = (_NTreeNode*)tnTmp->NextSibling;
          }
      
          return null;
      }
      
      
      
      /// <summary>
      /// 在结点 tnFindStart 中的子结点中查找节点键值为 iKeyValue 的结点,包括结点 tnFindStart
      /// </summary>
      /// <param name="tnFindStart">开始查找的结点</param>
      /// <param name="sKeyValue"></param>
      /// <returns>返回第一次出现的结点</returns>
      /// 创建时间:????-??-?? 最后一次修改时间:2022-07-18
      _NTreeNode* _NTree::Find(const _NTreeNode* tnFindStart, const _string& sKeyValue)const
      {
          if (!sKeyValue.IsArabicDigitString())
          {
              _string sError = _t("_NTreeNode* _NTree::Find(const _NTreeNode* tnFindStart, const _string& sKeyValue) 错误: sKeyValue=“") + sKeyValue + _t("” 不是数字!");  
              d.ThrowException(sError);
          }
      
          return Find(tnFindStart, sKeyValue.ToInt64());     
      }
      
      
      
      /// <summary>
      /// 把本节点、兄弟节点、子节点数据写入磁盘.
      /// 除非构建的链表,或者节点数据有问题,否则此函数是正确的。
      /// </summary>
      /// <param name="tvtnNode"></param>
      /// <param name="kbf"></param>
      /// 创建时间: ????-??-??      最后一次修改时间:2022-10-27 
      void _NTree::SaveSiblingAndChild(_NTreeNode* pNode, _KeyBinaryFile& kbf)
      { 
          if (pNode == null) return;
      
          _NTreeNode* pTemp = pNode;
          _ByteArray ba;
      
          while (pTemp != null)
          {
              _string sKeyString(_t(""), 100);
              
              
              sKeyString.Add(ConstName);
              sKeyString.Add(_NTreeNode::SplitString);
              sKeyString.Add(std::to_wstring(pTemp->KeyValue).c_str());
           
      
              kbf.AddByteArray(sKeyString, pTemp->PackageData(ba,false));
      
              //log::d(L"sKeyString = "+ sKeyString->ToString(), L"CSharp_TreeDataView::SaveSiblingAndChild");
      
              //log::d(L"tvtn->KeyValue.ToString() = " + tvtn->KeyValue.ToString(), L"CSharp_TreeDataView::SaveSiblingAndChild");
      
              //log::d(L"tvtn->DispalyText.ToString() = " + tvtn->DispalyText->ToString(), L"CSharp_TreeDataView::SaveSiblingAndChild");
      
              //log::d(tvtn->PackageData(), L"SaveSiblingAndChild");
      
      
              SaveSiblingAndChild(pTemp->FirstChild, kbf);
      
              pTemp = pTemp->NextSibling;
          }
      }
      
      
      /// <summary>
      /// 返回根节点的数据
      /// </summary>
      /// <returns></returns>
      _StrA _NTree::GetFirstNodeDataA() const
      {
          if (_Root != null)
              return (char*)_Root->Data.Data;
          else
              return "";
      }
      
      _StrW _NTree::GetFirstNodeDataW() const
      {
          if (_Root != null)
              return (wchar_t*)_Root->Data.Data;
          else
              return _t("");
      }
      
      void _NTree::SetFirstNodeData(const _StrA& sData)
      {
          if (_Root != null)
          {
              _Root->Data.ClearData();
              _Root->Data.AddStringA(sData); 
          }
          else
          {
              d.ShowError(_t("没有根节点!"), _t("void _NTree::SetFirstNodeData(const _string& sData)"));
          } 
      }
      
      void _NTree::Display() const
      {
          Display(_Root);
      }
      
      
      /// <summary>
      /// 
      /// </summary>
      /// <param name="pNode"></param>
      /// <param name="nLevel"></param>
      /// 创建时间:2023-01-17 最后一次修改时间:2023-01-17
      void _NTree::Display(const _NTreeNode* pNode, const int nLevel) const
      {
          
          _string sRoot;
      
          for (int i = 1; i < nLevel; ++i)
          {
              sRoot.Add('\t');
          }
      
          if (pNode != null)
          {
              _cout << sRoot << pNode->DispalyText << _t("\n");
              
          }
          else
          {
              return;
          }
      
          _NTreeNode* pChild = pNode->FirstChild;
      
          while (pChild != null)
          {
              Display(pChild, nLevel + 1);
      
              pChild = pChild->NextSibling;
          }
      }
      
       
      #if _CLR_
      
      void _NTree::Save(TreeView^ tv,const _string& sFullPathName, bool bReWrite)
      {
      
          if (sFullPathName.CSharp_Trim().Length == 0)
          {
              d.ShowError(sFullPathName + _t("\n文件名不能为空!"), _t("void _NTree::Save(const _string & sFullPathName, TreeView ^ tv, bool bReWrite)"));
          }
      
          if (sFullPathName.FileExists())
          {
              if (!bReWrite)
              {
                  d.ShowError(sFullPathName + _t("\n文件已存在!"), _t("void _NTree::Save(const _string & sFullPathName, TreeView ^ tv, bool bReWrite)"));
                  return;
              }
          }
      
          _KeyBinaryFile  kbf(sFullPathName);
      
          if (_Root != null)
          {
      
              kbf.AddString(ConstName + _t("_First"), _Root->KeyValue.ToString());
      
      
              if (tv != null)
              {
                  if (tv->SelectedNode != null)
                      kbf.AddString(ConstName + _t("_Select"), tv->SelectedNode->Name);
                  else
      
                      kbf.AddString(ConstName + _t("_Select"), _t("-1"));
              }
      
              SaveSiblingAndChild(_Root, kbf);
      
              kbf.SaveAnother(sFullPathName);
               
          }
          else  //空文件
          {
              kbf.SaveAnother(sFullPathName);
          }
      }
      
      
      void _NTree::BuildInTreeView(TreeView^ tv, TreeNode^ tnParent, const _NTreeNode* pNode, int nImageIndex)
      {
          //if (! CheckTreeViewTreeNode(tvtnNode, L"CSharp_Tree::BuildTreeView")) return;
      
          _NTreeNode* pn = (_NTreeNode *) pNode;
      
          while (pn != null)
          {
              TreeNode^ tn = gcnew TreeNode(pn->DispalyText);
              tn->Name = pn->KeyValue.ToString();
              tn->ForeColor = pn->DisplayForeColor; //tv->ForeColor;  
              //tn->BackColor =   pn->DisplayBackColor; //tv->ForeColor; 
               
              tn->NodeFont =  pn->DispalyFont; //tv->Font;  
      
              //d.PrintError(_geti((int)pn->DispalyFont.Size),"void _NTree::BuildInTreeView(");
      
              tn->ImageIndex = nImageIndex;
              tn->SelectedImageIndex = nImageIndex;
              tn->StateImageIndex = nImageIndex;
      
              if (tnParent == null)
                  tv->Nodes->Add(tn);
              else
                  tnParent->Nodes->Add(tn);
      
              BuildInTreeView(tv,tn, pn->FirstChild, nImageIndex);
      
              pn = pn->NextSibling;
          }
      }
      
      
      
      /// <summary>
      /// 把树显示在控件 TreeView 上
      /// </summary>
      /// <param name="tv"></param>
      void _NTree::BuildInTreeView(TreeView^ tv,const int iImageIndex)
      {
          if (tv == null) return;
      
          tv->Nodes->Clear();
      
          BuildInTreeView(tv, null, _Root, iImageIndex);
      
          tv->ExpandAll();
      }
      
      
      _StrW _NTree::GetTreeNodeDataW(TreeNode^ tn)
      {
          _NTreeNode* tvtn = Find(_Root, tn->Name);
      
          if (tvtn == null)
              throw gcnew Exception("tvtn == null");
      
          return (wchar_t*)tvtn->Data.Data;
      }
      
      _StrA _NTree::GetTreeNodeDataA(TreeNode^ tn)
      {
          _NTreeNode* tvtn = Find(_Root, tn->Name);
      
          if (tvtn == null)
              throw gcnew Exception("tvtn == null");
      
          return (char*)tvtn->Data.Data;
      }
      
      
      void _NTree::AfterLabelEdit_Event(Object^ sender, NodeLabelEditEventArgs^ e)
      {
          TreeView^ tv = (TreeView^)sender;
      
          if (e->Label != null && e->Label->Trim() != "")
          {
              UpdateTreeViewNode(tv,e->Node, e->Label);
              IsModify = true;
          }
          else
          {
              e->CancelEdit = true;
          }
      }
      
      /// <summary>
      /// TreeView的节点属性改变,同时更新CSharp_Tree^的节点。
      /// </summary>
      /// <param name="tnModify">发生改变的节点</param>
      /// <param name="sDispalyText">所显示的文本</param>
      /// <exception cref="Exception"></exception>
      /// 创建时间: 2022-03-05      最后一次修改时间:2022-03-05
      void _NTree::UpdateTreeViewNode(TreeView^ tv, TreeNode^ tnModify, String^ sDispalyText)
      {
          _NTreeNode* tnFind = Find(_Root, tnModify->Name);
      
          if (tnFind == null)
              throw gcnew Exception("tnFind = null");
      
          if (sDispalyText != _t(""))
              tnFind->DispalyText = sDispalyText;
          else
              tnFind->DispalyText = tnModify->Text;
      
          if (tnModify->NodeFont == null)  //如果没有设置时,新建的节点是NULL,自动跟TreeView的Font^相同
          {
              tnFind->DispalyFont = tv->Font;
          }
          else
          {
              tnFind->DispalyFont = tnModify->NodeFont;
          }
      
      
          tnFind->DisplayBackColor = tnModify->BackColor;
          tnFind->DisplayForeColor = tnModify->ForeColor;
      
      }
      
      void _NTree::TreeViewSelectedNodeDelete(TreeView^ tv)
      {
          TreeNode^ tn = tv->SelectedNode;
          if (tn != null)
          {
              if (MessageBox::Show(_t("真的要删除“") + tn->Text + _t("”吗?"), _t("删除提示"), MessageBoxButtons::YesNo, MessageBoxIcon::Question) == DialogResult::Yes)
              {
      
                  tv->Nodes->Remove(tn);
      
                  if (_Root == null)
                      throw gcnew Exception("First==null");
      
                  _NTreeNode* tnRemove = Find(_Root, tn->Name);
      
                  if (tnRemove == null)
                      throw gcnew Exception("tnRemove == null");
      
      
                  if (!RemoveNode(tnRemove))
                  {
                      throw gcnew Exception(" RemoveNode(tnRemove) == False");
                  }
      
                  IsModify = true;
              }
          }
      }
      
      void _NTree::TreeViewSelectedNodeAddNewNode(TreeView^ tv, String^ sDisplayText)
      {
      
          _NTreeNode  ntn;
           
          ntn.DispalyFont = tv->Font;
          ntn.DispalyText = sDisplayText;
          ntn.DisplayBackColor = tv->BackColor;
          ntn.DisplayForeColor = tv->ForeColor;
          ntn.NextSibling = null;
      
          TreeNode^ tn = gcnew TreeNode(sDisplayText);
          tn->Name = ntn.KeyValue.ToString();
      
      
          if (tv->SelectedNode == null) //如查没有选中根节点,则在根节点中加入子节点
          {
              if (tv->Nodes->Count == 0)
              {
                  tv->Nodes->Add(tn);
              }
              else
              {
                  tv->Nodes[0]->Nodes->Add(tn);
              }
             
              
              AddNode(null, &ntn);
          }
          else
          {
      
              tv->SelectedNode->Nodes->Add(tn);
      
              _NTreeNode *pParent = Find(_Root, tv->SelectedNode->Name);
      
              if (pParent == null)
              {
                  _string sErrorInfo = _t("NTree中无法找到 m_TreeView->SelectedNode->Name= “") + _string(tv->SelectedNode->Name) + _t("” 的节点");
                  d.ShowError(sErrorInfo, _t("CSharp_TreeDataView->TreeViewSelectedNodeAddNewNode"));
                  //log::d(sErrorInfo, L"CSharp_TreeDataView->TreeViewSelectedNodeAddNewNode");
                  return;
              }
      
              AddNode(pParent, &ntn);
      
          }
      
          tv->SelectedNode = tn;
          IsModify = true;
      
      }
      /// <summary>
      /// 改变节点数据
      /// </summary>
      /// <param name="sData"></param>
      void _NTree::ChangeSelectedNodeData(TreeView^ tv, String^ sData)
      {
          TreeNode^ tn = tv->SelectedNode;
      
          if (tn == null)
              throw gcnew Exception("tn == null");
      
          _NTreeNode* pntn = Find(_Root, tv->SelectedNode->Name);
      
          if (pntn == null)
              throw gcnew Exception("tvtn == null");
      
          pntn->Data.ClearData();
          
          //TreeView 都用 char
          pntn->Data.AddStringA(sData);   //pntn->Data.AddString(sData);
      
          if (tn->NodeFont != null)
          {
              pntn->DispalyFont = tn->NodeFont;
          }
      
          pntn->DispalyText = tn->Text;
          pntn->DisplayBackColor = tn->BackColor;
          pntn->DisplayForeColor = tn->ForeColor;
      
          IsModify = true;
      
      }
      
      
      
      
      /// <summary>
      /// TreeView控件的修改节点事件
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      /// <exception cref="Exception"></exception>
      /// 创建时间: ????-??-??      最后一次修改时间:2022-03-05
      void _NTree::AfterLabelEdit_Event(TreeView^ tv, Object^ sender, NodeLabelEditEventArgs^ e)
      {
          if (e->Label != null && e->Label->Trim() != "")
          {
              UpdateTreeViewNode(tv,e->Node, e->Label);
              IsModify = true;
          }
          else
          {
              e->CancelEdit = true;
          }
      }
      
      
      /// <summary>
      /// 改变字体或者前景色
      /// </summary>
      /// <param name="tnNode"></param>
      void _NTree::TreeViewNodeAttributeChange(TreeNode^ tnNode)
      {
          _NTreeNode* tn = Find(_Root, tnNode->Name);
      
          if (tn != null)
          {
              tn->DispalyFont = tnNode->NodeFont;
              tn->DispalyText = tnNode->Text;
              tn->DisplayForeColor = tnNode->ForeColor;
              tn->DisplayBackColor = tnNode->BackColor;
      
              IsModify = true;
          }
      }
      
      void _NTree::ItemDrag_Event(TreeView^ tv, Object^ sender, ItemDragEventArgs^ e)
      {
      
          if (e->Button == MouseButtons::Left)
          {
       
              tv->DoDragDrop(e->Item, DragDropEffects::Move);
              
          }
      }
      
      
      
      /// <summary> 
      /// 记住格式是: GetData("System.Windows.Forms.TreeNode") 不是: GetData("System.Windows::Forms::TreeNode");
      /// </summary>
      /// <param name="tv"></param>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      /// 创建时间:????-??-?? 最后一次修改时间:2023-01-11
      void _NTree::DragDrop_Event(TreeView^ tv, Object^ sender, DragEventArgs^ e)
      { 
      
          //获得拖放中的节点
          TreeNode^ tnMove = (TreeNode^)e->Data->GetData("System.Windows.Forms.TreeNode");
      
          if (tnMove == nullptr)
          {
              d.ShowError(_t("错误:tnMove == nullptr"), _t("void _NTree::DragDrop_Event(TreeView^ tv, Object^ sender, DragEventArgs^ e)"));
          }
      
          //根据鼠标坐标确定要移动到的目标节点
          Point p = Point(e->X, e->Y);
          Point pt = ((TreeView^)sender)->PointToClient(p);
      
      
          TreeNode^ tnTarget = tv->GetNodeAt(pt);
      
      
      
          if (tnTarget == null) { return; }
      
      
      
          if (tnMove->Nodes->Find(tnTarget->Name, true)->Length != 0)
          {
              ga.p(L"无法移动父节点到到它子节点中去!", L" void DragDrop_Event");
              return;
          }
      
      
      
          //不需要变动,因为把tnMove放在tnTarget下为子节点,而tnMove本身就是tnTarget的最后一个子节点。
          if (tnTarget->Nodes->Count > 0 && tnTarget->Nodes[tnTarget->Nodes->Count - 1] == tnMove)
              return;
      
      
          //----------------------------------------------------------------在CSharp_Tree^上操作
          _NTreeNode* ltnMove = Find(_Root, tnMove->Name);
      
          if (ltnMove == null)
          {
              throw gcnew Exception(L"无法找到节点:" + tnMove->Text);
          }
      
      
          //除去ltnMove
      
          _NTreeNode* ltnPrevSibling = FindPrevSibling(_Root, ltnMove);
      
          if (ltnPrevSibling != null)
          {
              ltnPrevSibling->NextSibling = ltnMove->NextSibling;
              ltnPrevSibling->NextSiblingKeyValue = ltnMove->NextSiblingKeyValue;
      
              //一定要设置ltnMove为孤链
              ltnMove->NextSibling = null;
              ltnMove->NextSiblingKeyValue = -1;
          }
          else
          {
              _NTreeNode* ltnParent = FindIsFirstChild(_Root, ltnMove);
      
              if (ltnParent != null)
              {
                  if (ltnMove->NextSibling != null)
                  {
      
                      ltnParent->FirstChild = ltnMove->NextSibling;
                      ltnParent->FirstChildKeyValue = ltnMove->NextSibling->KeyValue;
      
                      //一定要设置ltnMove为孤链
                      ltnMove->NextSibling = null;
                      ltnMove->NextSiblingKeyValue = -1;
                  }
                  else
                  {
                      ltnParent->FirstChild = null;
                      ltnParent->FirstChildKeyValue = -1;
                  }
              }
              else
              {
                  throw gcnew Exception(L"链接错误!");
              }
          }
      
          //查找目标节点
          _NTreeNode* ltnTarget = Find(_Root, tnTarget->Name);
      
          if (ltnTarget == null)
          {
              throw gcnew Exception(L"无法找到节点:" + tnTarget->Text);
          }
      
      
          //在目标节点未加上子节点ltnMove
          AddNode(ltnTarget,ltnMove);
           
      
          //-------------------------------------------------------------在控件上操作
      
          //如果目标节点为分组则添加到下级节点的未端,如果目标节点为素材文件则添加为同级节点
          TreeNode^ NewMoveNode = (TreeNode^)tnMove->Clone();
      
      
          tnTarget->Nodes->Insert(tnTarget->Nodes->Count, NewMoveNode);
      
          //更新当前拖动的节点选择
          tv->SelectedNode = NewMoveNode;
          //展开目标节点,便于显示拖放效果
          tnTarget->Expand();
      
          //移除拖放的节点
          tnMove->Remove();
      
          IsModify = true;
      
      }
      
      
      
      /// <summary>
      /// 记住格式是: "System.Windows.Forms.TreeNode"  不是:"System.Windows.Forms.TreeNode", 跟C#一样
      /// </summary>
      /// </summary>
      /// <param name="tv"></param>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      /// 创建时间:????-??-?? 最后一次修改时间:2023-01-11
      void _NTree::DragEnter_Event(TreeView^ tv, Object^ sender, DragEventArgs^ e)
      {
      
          /*
          auto a = e->Data->GetFormats();
      
          for each (String^ s in a)
          {
              d.PrintError(s);
          }
      
      
          if (e->Data->GetDataPresent("System.Windows.Forms.TreeNode"))
          {
              
          }
          */
      
          if (e->Data->GetDataPresent(_t("System.Windows.Forms.TreeNode")))
              e->Effect = DragDropEffects::Move;
          else
             e->Effect = DragDropEffects::None;
       
      }
      
      _NTreeNode* _NTree::GetinitTreeViewTreeNode(TreeView^ tv,String^ sText)
      {
          _NTreeNode* tvtnNew;
      
          if (sText != "")
              tvtnNew->DispalyText = sText;
          else
              tvtnNew->DispalyText = _t("新节点");
      
          if (tv->Font == null)
              throw gcnew Exception("m_TreeView->Font== null");
          tvtnNew->DispalyFont = tv->Font;
          tvtnNew->DisplayBackColor = tv->BackColor;
          tvtnNew->DisplayForeColor = tv->ForeColor;
      
          return tvtnNew;
      }
      
      
      TreeNode^ _NTree::TreeViewAddRootNode(TreeView^ tv, String^ sText)
      {
          _NTreeNode* tvtnNew = GetinitTreeViewTreeNode(tv,sText);
      
          AddNode(null, tvtnNew);
      
          TreeNode^ tnNew;
      
          if (sText != "")
              tnNew = tv->Nodes->Add(sText);
          else
              tnNew = tv->Nodes->Add("新节点");
      
          tnNew->Name = tvtnNew->KeyValue.ToString();
      
          IsModify = true;
      
          return tnNew;
      }
      
      
      /// <summary>
      /// 把选中的节点上移一位
      /// </summary>
      /// <returns></returns>
      /// 创建时间:2022-07-17 最后一次修改时间:2022-07-19
      String^ _NTree::TreeViewSelectNodeMoveUp(TreeView^ tv)
      {
      
      
          TreeNode^ tnSelect = tv->SelectedNode;
      
          if (tnSelect == null)
          {
              return _t("未先定节点");
          }
      
          _NTreeNode* tvtnSelect = Find(_Root, tnSelect->Name);
      
          _NTreeNode* tvtnSelectParent = FindPrent(_Root, tvtnSelect);
      
          if (tvtnSelectParent == null) return L"未找到父结点!";
      
      
          if (tvtnSelect == null) return L"未找到值为:+ " + tnSelect->Name + L" 的节点!";
      
          _NTreeNode* prevOne = FindPrevSibling(_Root, tvtnSelect);
      
          if (prevOne == null)  return L"上一个兄弟结点不存在,无法上移!";
      
      
      
          _NTreeNode* prevTwo = FindPrevSibling(_Root, prevOne);
      
          if (prevTwo == null)
          {
              //-----------------------------在TreeView中
              TreeNode^ tnParent = tnSelect->Parent;
              int nInsertIndex = tnSelect->Index - 1;
      
              if (tnParent != null)
              {
                  TreeNode^ newNode = (TreeNode^)tnSelect->Clone();    //克隆选中的节点
                  tnParent->Nodes->Insert(nInsertIndex, newNode);
                  tnSelect->Remove();
      
      
      
                  //------------------------------------------在 Tree中
                  //交换的是第一个结点,要找出它的父结点
      
                  Int64 iTempKey = tvtnSelect->NextSiblingKeyValue;
                  tvtnSelectParent->FirstChildKeyValue = tvtnSelect->KeyValue;
                  tvtnSelect->NextSiblingKeyValue = prevOne->KeyValue;
                  prevOne->NextSiblingKeyValue = iTempKey;
      
                  _NTreeNode* tnTemp = tvtnSelect->NextSibling;
                  tvtnSelectParent->FirstChild = tvtnSelect;
                  tvtnSelect->NextSibling = prevOne;
                  prevOne->NextSibling = tnTemp;
      
                  tv->SelectedNode = newNode;
              }
      
          }
          else
          {
              //-----------------------------在TreeView中
              TreeNode^ tnParent = tnSelect->Parent;
              int nInsertIndex = tnSelect->Index - 1;
      
              if (tnParent != null)
              {
                  TreeNode^ newNode = (TreeNode^)tnSelect->Clone();    //克隆选中的节点
                  tnParent->Nodes->Insert(nInsertIndex, newNode);
                  tnSelect->Remove();
      
                  //------------------------------------------在 Tree中
                  //交换中间结点,要找出它的父结点
      
                  Int64 iTempKey = tvtnSelect->NextSiblingKeyValue;
                  prevTwo->NextSiblingKeyValue = tvtnSelect->KeyValue;
                  tvtnSelect->NextSiblingKeyValue = prevOne->KeyValue;
                  prevOne->NextSiblingKeyValue = iTempKey;
      
                  _NTreeNode* tnTemp = tvtnSelect->NextSibling;
                  prevTwo->NextSibling = tvtnSelect;
                  tvtnSelect->NextSibling = prevOne;
                  prevOne->NextSibling = tnTemp;
      
                  tv->SelectedNode = newNode;
              }
          }
      
          return "";
      }
      
      /// <summary>
      /// 把选中的节点下移一位
      /// </summary>
      /// <returns></returns>
      /// 创建时间:2022-07-17 最后一次修改时间:2022-07-19
      String^ _NTree::TreeViewSelectNodeMoveDown(TreeView^ tv)
      {
      
          TreeNode^ tnSelect = tv->SelectedNode;
      
          if (tnSelect == null)
          {
              return "未先定节点";
          }
      
          _NTreeNode* tvtnSelect = Find(_Root, tnSelect->Name);
      
          _NTreeNode* tvtnSelectParent = FindPrent(_Root, tvtnSelect);
      
          if (tvtnSelectParent == null) return "未找到父结点!";
      
      
          if (tvtnSelect == null) return "未找到值为:+ " + tnSelect->Name + " 的节点!";
      
          _NTreeNode* nextOne = tvtnSelect->NextSibling;
      
      
          if (nextOne == null) return "下一个兄弟结点不存在,无法下移!";
      
      
          _NTreeNode* prevOne = FindPrevSibling(_Root, tvtnSelect);
      
      
      
          if (prevOne == null)  //第一节点移到下面
          {
              //-----------------------------在TreeView中
              TreeNode^ tnParent = tnSelect->Parent;
              int nInsertIndex = tnSelect->Index + 2;
      
              if (tnParent != null)
              {
                  TreeNode^ newNode = (TreeNode^)tnSelect->Clone();    //克隆选中的节点
                  tnParent->Nodes->Insert(nInsertIndex, newNode);
                  tnSelect->Remove();
      
      
      
                  //------------------------------------------在 Tree中
                  //交换的是第一个结点,要找出它的父结点
      
                  Int64 iTempKey = nextOne->NextSiblingKeyValue;
                  tvtnSelectParent->FirstChildKeyValue = nextOne->KeyValue;
                  nextOne->NextSiblingKeyValue = tvtnSelect->KeyValue;
                  tvtnSelect->NextSiblingKeyValue = iTempKey;
      
                  _NTreeNode* tnTemp = nextOne->NextSibling;
                  tvtnSelectParent->FirstChild = nextOne;
                  nextOne->NextSibling = tvtnSelect;
                  tvtnSelect->NextSibling = tnTemp;
      
                  tv->SelectedNode = newNode;
              }
      
          }
          else
          {
              //-----------------------------在TreeView中
              TreeNode^ tnParent = tnSelect->Parent;
              int nInsertIndex = tnSelect->Index + 2;
      
              if (tnParent != null)
              {
                  TreeNode^ newNode = (TreeNode^)tnSelect->Clone();    //克隆选中的节点
                  tnParent->Nodes->Insert(nInsertIndex, newNode);
                  tnSelect->Remove();
      
                  //------------------------------------------在 Tree中
                  //交换中间结点 
      
                  Int64 iTempKey = nextOne->NextSiblingKeyValue;
                  prevOne->NextSiblingKeyValue = nextOne->KeyValue;
                  nextOne->NextSiblingKeyValue = tvtnSelect->KeyValue;
                  tvtnSelect->NextSiblingKeyValue = iTempKey;
      
                  _NTreeNode* tnTemp = nextOne->NextSibling;
                  prevOne->NextSibling = nextOne;
                  nextOne->NextSibling = tvtnSelect;
                  tvtnSelect->NextSibling = tnTemp;
      
                  tv->SelectedNode = newNode;
              }
          }
      
          return _t("");
      }
      
      
      #endif
      
      
      _LF_END_
      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.csdn.net/weixin_42944928/article/details/129918481,作者:碧海蓝天2022,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:python—多线程之线程之间共享数据(Queue)

      下一篇:深入理解Java中的内存管理与优化

      相关文章

      2025-04-18 07:10:44

      使用shell脚本在Linux中管理Java应用程序

      在日常开发和运维工作中,管理基于Java的应用程序是一项基础且频繁的任务。

      2025-04-18 07:10:44
      jar , Java , Shell , 应用 , 操作 , 目录 , 脚本
      2025-04-18 07:09:19

      Java学习路线指南

      Java作为一种广泛使用的编程语言,不仅应用在Web开发、移动应用、企业级系统等领域,还在大数据、人工智能等前沿领域占有重要地位。由于其跨平台的特性和强大的社区支持,Java成为许多开发者入门编程或转向高级开发的首选语言。

      2025-04-18 07:09:19
      Java , JVM , 代码 , 学习 , 应用 , 开发 , 数据类型
      2025-04-14 08:45:36

      【Kafka】集成案例:与Spark大数据组件的协同应用

      Apache Kafka 是一个分布式流处理平台,主要用于构建实时数据管道和流式应用。Kafka 由 LinkedIn 开发,并于 2011 年开源,目前由 Apache 软件基金会进行管理。它以高吞吐量、低延迟和可扩展性著称。

      2025-04-14 08:45:36
      Kafka , Spark , 实时 , 应用
      2025-04-11 07:11:40

      读Java实战(第二版)笔记13_Java模块系统

      读Java实战(第二版)笔记13_Java模块系统

      2025-04-11 07:11:40
      Java , 子句 , 应用 , 模块 , 访问 , 路径
      2025-04-11 07:08:26

      探索 CodeWave低代码技术的魅力与应用

      在当今快速发展的数字化时代,企业面临着不断增长的应用需求以及对高效开发的迫切需求。低代码技术作为推动数字化转型的强大引擎,正在为企业带来全新的开发模式和效率。

      2025-04-11 07:08:26
      代码 , 企业 , 平台 , 应用 , 开发 , 组件
      2025-04-09 09:13:17

      python 如何判断一组数呈上升还是下降趋势

      要判断一组数(数列)是呈上升趋势、下降趋势还是无明显趋势,我们可以比较数列中相邻元素的差值。如果大部分差值都是正数,则数列呈上升趋势;如果大部分差值都是负数,则数列呈下降趋势;如果正负差值数量相当或差值接近于零,则数列无明显趋势。

      2025-04-09 09:13:17
      判断 , 差值 , 应用 , 数列 , 阈值
      2025-03-31 08:58:01

      探秘 Spring Application 启动流程:从初始化到运行的全景解析

      探秘 Spring Application 启动流程:从初始化到运行的全景解析

      2025-03-31 08:58:01
      Spring , 上下文 , 加载 , 启动 , 容器 , 应用
      2025-03-26 09:33:14

      谈谈微前端

      微前端是一种架构理念,它将较大的前端应用拆分为若干个可以独立交付的前端应用。这样的好处是每个应用大小及复杂度相对可控。在合理拆分应用的前提下,微前端能降低应用之间的耦合度,提升每个团队的自治能力。

      2025-03-26 09:33:14
      iframe , 前端 , 应用 , 路由 , 隔离
      2025-03-25 08:08:18

      Spring 家族的三剑客:深入解析 Spring Framework 、 Spring Boot 与 Spring MVC 的区别

      Spring 家族的三剑客:深入解析 Spring Framework 、 Spring Boot 与 Spring MVC 的区别

      2025-03-25 08:08:18
      Boot , MVC , Spring , View , Web , 应用
      2025-03-18 09:59:07

      Java与容器化:如何使用Docker和Kubernetes优化Java应用的部署

      Java与容器化:如何使用Docker和Kubernetes优化Java应用的部署

      2025-03-18 09:59:07
      Docker , Java , Kubernetes , Pod , 容器 , 应用 , 部署
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      32777

      阅读量

      4830243

      查看更多

      最新文章

      使用shell脚本在Linux中管理Java应用程序

      2025-04-18 07:10:44

      Java学习路线指南

      2025-04-18 07:09:19

      读Java实战(第二版)笔记13_Java模块系统

      2025-04-11 07:11:40

      探索 CodeWave低代码技术的魅力与应用

      2025-04-11 07:08:26

      探秘 Spring Application 启动流程:从初始化到运行的全景解析

      2025-03-31 08:58:01

      Spring 家族的三剑客:深入解析 Spring Framework 、 Spring Boot 与 Spring MVC 的区别

      2025-03-25 08:08:18

      查看更多

      热门文章

      游戏编程之十二 资源管理

      2023-02-15 08:38:56

      AIGC 时代:程序员的创新与机遇

      2024-12-18 08:24:44

      C#工程使用CLI无法调试进底层C++/C库

      2024-03-26 08:11:30

      AI模型如何重塑软件开发

      2024-12-11 06:19:22

      统信UOS命令行设置未签名软件安装权限

      2024-06-05 09:49:00

      HarmonyOS 学习笔记-深入探索API

      2024-12-19 08:42:50

      查看更多

      热门标签

      java Java python 编程开发 开发语言 代码 算法 线程 html Python 数组 C++ javascript c++ 元素
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      Java中的方法重写详解

      探索 CodeWave低代码技术的魅力与应用

      Spring 家族的三剑客:深入解析 Spring Framework 、 Spring Boot 与 Spring MVC 的区别

      函数与二元关系在编程中的应用

      【Java】内部类、枚举、泛型

      AI模型如何重塑软件开发

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 权益商城
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 权益商城
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号