动态StringGrid C ++ Builder

时间:2014-12-15 17:00:53

标签: c++ c++builder stringgrid

我在C ++ Builder 6中创建了一个程序,现在我遇到了一个问题。

我有6个文件:Unit1.cppUnit1.hUnit2.cppUnit2.hUnit3.cppUnit3.h

Unit1.cpp是主要表单的文件。

问题:我想在功能void __fastcall TForm3::Button1Click(TObject *Sender)TStringGrid中创建一个Unit1.cppUnit2.cpp。下一次单击应创建具有新名称(先前存在)的新TStringGrid

我试图解决我的问题,我写了一些代码,但这对我来说还不够 在Unit1.h我添加了:

void __fastcall MyFunction(TStringGrid *Grid1);  

Unit1.cpp我添加了:

void __fastcall TForm1::MyFunction(TStringGrid *Grid1)
{
        Grid1 = new TStringGrid(Form2);
        Grid1->Parent = Form2;
}

Unit3.cpp我添加了:

#include "Unit1.h"

和按钮点击功能是:

 void __fastcall TForm3::Button1Click(TObject *Sender)
     {
         Form1->MyFunction(Form1->Grid);  //Grid was declarated previous in Unit1.h
     }

现在,当我使用此方法时,我动态创建TStringGrid,但只有一个。如何按下按钮的次数创建尽可能多的TStringGrid(具有唯一名称)? (现在我必须在TStringGrid)中声明Unit1.h

1 个答案:

答案 0 :(得分:0)

首先,请注意您的代码 正在创建多个TStringGrid。它只是在窗体上的相同位置创建所有相同尺寸的所有内容,因此您只能在顶部看到它。

-

您希望能够做什么(Form1->dynamically_created_TStringGrid)是不可能的,但有几种方法可以让您获得类似的行为。

std :: vector方法

<强> Unit1.h

#ifndef Unit1H
#define Unit1H
#include <vector>
//your other includes here

class PACKAGE Form1 : public TForm
{
__published:    //IDE-managed Components
    //your components here
private:
    /.../
    std::vector<TStringGrid *> SGridVec;
public:
    /.../
    AnsiString AddStringGrid(); 
    TStringGrid * GetStringGridByName(const AnsiString &Name);
    TStringGrid * GetStringGridByIndex(const unsigned int Index);
}

<强> Unit1.cpp

AnsiString TForm1::AddStringGrid()
{
    SGridVec.push_back(new TStringGrid(Form2));    //Form2 is owner and handles memory management
    if (SGridVec.back())
    {
        SGridVec.back()->Parent = Form2;
        SGridVec.back()->Name = "some uniquely generated name";
        return SGridVec.back()->Name;
    }
    return "";  //add was unsuccessful
}

TStringGrid * TForm1::GetStringGridByName(const AnsiString &Name)
{
    for(std::vector<TStringGrid *>::iterator sgItr = SGridVec.begin();
        sgItr != SGridVec.end();
        ++sgItr)
    {
        if (*sgItr && (*sgItr)->Name == Name)
        {
            return *sgItr;
        }
    }
    return NULL;  //StringGrid with Name was not found
}

TStringGrid * TForm1::GetStringGridByIndex(const unsigned int Index)
{
    if (Index < SGridVec.size() && SGridVec.at(Index) != NULL)
        return SGridVec.at(Index);
    return NULL;  //StringGrid at Index was not found
}

使用此方法,您可以调用AddStringGrid()并存储返回值。然后,当您想要操纵TStringGrid上的给定Form1时,您会调用GetStringGridByName并传入您想要操作的TStringGrid的名称。您还可以使用std::map实现非常类似的内容,即使是public成员。

FindChildControl方法

<强> Unit1.h

#ifndef Unit1H
#define Unit1H
#include <map>
//your other includes here

class PACKAGE Form1 : public TForm
{
__published:    //IDE-managed Components
    //your components here
public:
    /.../
    AnsiString AddStringGrid(); 
}

<强> Unit1.cpp

AnsiString TForm1::AddStringGrid()
{
    TStringGrid *temp_ptr = new TStringGrid(Form2);    //Form2 is owner and handles memory management
    if (temp_ptr)
    {
        temp_ptr->Parent = Form2;
        temp_ptr->Name = "some uniquely generated name";
        return temp_ptr->Name;
    }
    return "";  //add was unsuccessful
}

void SomeClass::SomeFunctionThatUsesForm2sTStrinGrids(/.../)
{
    /.../  //some code
    TStrinGrid *temp_ptr = static_cast<TStringGrid *>(Form2->FindChildControl("name of control"));
    if (temp_ptr)
    {
        //do stuff to the string grid
    }
    /.../  //some other code
}

此版本基本上使用Parent -> Children关系来查找动态创建的TStringGrid,而不是将其存储在std::vector.我的直觉中表示它比{{1}更慢且更不安全方法,但我没有任何证据。如果你忘记&#34;它也没有提供任何简单,可靠的方式来获得std::vector s。您给它们的唯一名称,而StringGrid允许您通过索引访问它们,或者通过迭代器(如果您可以使用它)。有std::vector,但使用起来看起来不太直观。

-

起初我以为每次拨打GetChildren时都会收到内存泄漏,但如果我理解Builder 6 documentation correctly,情况并非如此:

  

TComponent类还引入了所有权的概念   在整个VCL和CLX中传播。两个属性支持   所有权:所有者和组件。每个组件都有一个Owner属性   引用另一个组件作为其所有者。组件可能拥有   其他组件。在这种情况下,引用所有拥有的组件   组件的Array属性。

     

组件的构造函数采用一个用于的参数   指定新组件的所有者。如果传入的所有者存在,则   新组件将添加到所有者的组件列表中。除了   使用“组件”列表引用自有组件,此属性   还提供自动销毁自有组件。如   只要该组件具有所有者,它就会被销毁   老板被摧毁了。例如,因为TForm是其后代   TComponent,表单拥有的所有组件都被销毁了   表单被销毁时释放的内存。这假定所有的   表单上的组件在他们的时候正确地清理它们   析构函数被称为。

     

[.pdf page 53]

因此,即使每次将TForm1::MyFunction ed对象传递给Grid1时都要为其分配new ed对象,这些对象仍由Form2拥有,并在{{1}时清除被破坏了。

所有这一切,你应该知道,如果你坚持你在OP中发布的实现,你将无法操纵任何字符串网格,除了最后一个,除非你访问它们来自Form2