C++ Builder高手进阶 (三)用BCB设计DBTreeView组件(续二)

类别:编程语言 点击:0 评论:0 推荐:
 

//续二

void __fastcall TDBTreeView::FillChildTreeNodes(int ParentID, TTreeNode* Node, bool Nest)

{//用指定值填充子节点

    TQuery* AQuery = new TQuery(this);//创建一个数据集控件

    AnsiString strSql, strText;

    int iID, iParentID;

    int iImageIndex, iSelectedIndex;

    TTreeNode* TreeNode;

    TDBTreeNodeData NodeData;

    //设置数据集的各项参数

    AQuery->DatabaseName = ((TTable*)(FDataLink->DataSource->DataSet))->DatabaseName;//设置数据库名

    AQuery->Close();//关闭数据集

    AQuery->SQL->Clear();//清空原SQL语句

 

    strSql = "SELECT * FROM " + ((TTable*)(FDataLink->DataSource->DataSet))->TableName + " WHERE ";

    strSql += FParentIDField + "=:PID";

 

    AQuery->SQL->Add(strSql);//指定新的SQL语句

    AQuery->ParamByName("PID")->AsInteger = ParentID;

    AQuery->Open();//打开数据集

 

    this->Items->BeginUpdate();//开始更新DBTreeView组件显示

 

    while (!AQuery->Eof)//未到数据集尾部

    {

        strText = AQuery->FieldByName(FDisplayField)->AsString;//取得显示字段内容

        iID = AQuery->FieldByName(FPrimaryIDField)->AsInteger;//取得主标识字段内容

        iParentID = AQuery->FieldByName(FParentIDField)->AsInteger;//取得父标识字段内容

 

        TreeNode = this->Items->AddChild(Node, strText);//将上面取得的相关数据追加到新节点

        iImageIndex = iSelectedIndex = -1;//设置节点位图与选中时位图

        if (FOnSetImageIndex) FOnSetImageIndex(this, iID, iParentID, TreeNode->Level, iImageIndex, iSelectedIndex);//如果设置位图发生变化,则触发相关事件

        TreeNode->ImageIndex = iImageIndex;//设置节点位图及选中时位图

        TreeNode->SelectedIndex = iSelectedIndex;

 

        NodeData.ID = iID;//取得节点主标识,父标识,并按其追加一个新节点

        NodeData.ParentID = iParentID;

        AddDataToNode(TreeNode, NodeData);

 

        if (Nest) FillChildTreeNodes(iID, TreeNode);//如果指定参数Nest为true,则递归调用以填充所有子节点

        AQuery->Next();//移动到下一条记录

    }

 

    this->Items->EndUpdate();//结束DBTreeView组件更新

 

    AQuery->Close();//关闭数据集

    delete AQuery;//删除临时创建的数据集控件

}

void __fastcall TDBTreeView::AddDataToNode(TTreeNode* Node, TDBTreeNodeData& Data)

{//追加数据到节点

    TDBTreeNodeData* pData = new TDBTreeNodeData;

    *pData = Data;

    Node->Data = pData;

}

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

TDBTreeNodeData __fastcall TDBTreeView::GetNodeData(TTreeNode* Node)

{//取得指定节点的数据

    return *(TDBTreeNodeData*)(Node->Data);

}

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

void __fastcall TDBTreeView::Loaded(void)

{//调用原Load方法

    TCustomTreeView::Loaded();

    /* TODO : Loaded */

}

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

void __fastcall TDBTreeView::Notification(Classes::TComponent* AComponent, Classes::TOperation Operation)

{

 //事件响应

 TCustomTreeView::Notification(AComponent, Operation);//调用原方法

  if ((Operation == opRemove) && (FDataLink != NULL) && (AComponent == DataSource))//如果操作为opRemove以及数据连接不为空且指定组件为数据源,则

      DataSource = NULL;//使数据源为空

}

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

void __fastcall TDBTreeView::Edit(const tagTVITEMA &Item)

{//编辑节点

    TCustomTreeView::Edit(Item);//调用原方法

 

    if (FAllowModifyDB)//如果允许修改,则

    {

        TTreeNode* Node;

        AnsiString DatabaseName = ((TTable*)(FDataLink->DataSource->DataSet))->DatabaseName;

        AnsiString TableName = ((TTable*)(FDataLink->DataSource->DataSet))->TableName;

        TDBTreeNodeData NodeData;

        TQuery* AQuery = new TQuery(this);//新建一个数据集

        AnsiString strSql;

 

        if ((Item.state & TVIF_PARAM) != 0) Node = (TTreeNode*)(Item.lParam);

        else Node = Items->GetNode(Item.hItem);

 

        NodeData = GetNodeData(Node);

        strSql = "UPDATE " + TableName + " SET " + FDisplayField + " =:NewDispText WHERE " + FPrimaryIDField + "=:ID";//用指定条件更新数据集

 

        AQuery->Close();//关闭数据集

        AQuery->DatabaseName = DatabaseName;//设置数据库连接

        AQuery->SQL->Clear();//清空原SQL语句

        AQuery->SQL->Add(strSql);//追加SQL语句

        AQuery->ParamByName("NewDispText")->AsString = Node->Text;//对SQL中的参数进行赋值

        AQuery->ParamByName("ID")->AsInteger = NodeData.ID;

        AQuery->ExecSQL();//打开数据集

 

        delete AQuery;//删除临时创建的数据集控件

    }

}

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

void __fastcall TDBTreeView::Expand(TTreeNode* Node)

{//展开指定节点

    TCustomTreeView::Expand(Node);//调用原原方法

 

    TDBTreeNodeData NodeData;

    TTreeNode* ANode;

 

    for (ANode = Node->getFirstChild(); ANode; ANode = Node->GetNextChild(ANode))//遍历指定节点的子节点

    {

        NodeData = GetNodeData(ANode);//取得节点数据

        if (ANode->Count == 0)//如果节点数据为0,则填充其子节点

          FillChildTreeNodes(NodeData.ID, ANode);

    }

}

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

void __fastcall TDBTreeView::KeyDown(Word &Key, Classes::TShiftState Shift)

{

   //键盘处理

   TWinControl::KeyDown(Key, Shift);//调用原键盘处理方法

 

    if (Key == VK_F2 && Shift == TShiftState())//如果是Shift+F2则

    {

        /* Handle 'F2' key */

        if (this->Selected != NULL)//编辑当前选中的节点

            this->Selected->EditText();

    }

}

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

void __fastcall TDBTreeView::Change(TTreeNode* Node)

{//处理节点发生变化事件

TCustomTreeView::Change(Node);//调用原方法

    static TTreeNode* OldNode = NULL;

    TTreeNode* SelectedNode = this->Selected;//取得已选节点指针

    TDBTreeNodeData NodeData;

    TTable *ATable = (TTable*)(FDataLink->DataSource->DataSet);//指定数据集

 

    if (OldNode == SelectedNode) return;//如果旧节点等于选中的节点则直接返回

    if (ATable == NULL) return;//如果数据集为空则直接返回

    if (SelectedNode == NULL) return;//如果没有已选节点则直接返回

    NodeData = GetNodeData(SelectedNode);//取得指定节点数据

    ATable->SetKey();//按指定条件查找数据记录

    ATable->FieldByName(FPrimaryIDField)->AsInteger = NodeData.ID;

    ATable->GotoKey();

    OldNode = SelectedNode;//旧节点等于现在已选节点

}

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

bool __fastcall TDBTreeView::CustomDrawItem(TTreeNode* Node, TCustomDrawState State, TCustomDrawStage Stage, bool &PaintImages)

{

  //自绘节点

    bool Result;//调用原自绘方法

    Result = TCustomTreeView::CustomDrawItem(Node, State, Stage, PaintImages);

 

    /* TODO : ... */

    //TDBTreeNodeData NodeData = GetNodeData(Node);

    return Result;

}

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

void __fastcall TDBTreeView::FullExpand(void)

{//展开所有节点

    if (!Active)//如果DBTreeView不是活动状态,则抛出一个异常

        throw Exception("DBTreeView is Inactive.");

    this->Items->BeginUpdate();//开始更新DBTreeView

    ClearAllNodes();//清空所有节点

    FillChildTreeNodes(0, NULL, true);//填充子节点

    this->Items->EndUpdate();//结束更新

    TCustomTreeView::FullExpand();//调用原方法实现展开所有节点

}

 

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

void __fastcall TFieldNameProperty::GetValues(Classes::TGetStrProc Proc)

{//取得字段值

    int i;

    TDBTreeView* ADBTreeView;

 

    ADBTreeView = (TDBTreeView*)GetComponent(0);

    if (ADBTreeView->DataSource != NULL)//如果DBTreeView的数据源不为空,则

    {//遍历所有字段,并将其填充到相关字段属性中

        for (i = 0; i < ADBTreeView->DataSource->DataSet->FieldCount; i ++)

            Proc(ADBTreeView->DataSource->DataSet->Fields->Fields[i]->FieldName);

    }

    else

    {//否则抛出异常

        throw Exception("Missing DataSource property.");

    }

}

TTypeInfo* AnsiStringTypeInfo(void)

{

    //定义类型信息

TTypeInfo* TypeInfo = new TTypeInfo;

    TypeInfo->Name = "AnsiString";

    TypeInfo->Kind = tkLString;

    return TypeInfo;

}

《未完,见一篇DBTreeView开发总结》

本文地址:http://com.8s8s.com/it/it29443.htm