2014-12-15 6 views
0

C++ Builder 6에서 프로그램을 만들었는데 지금 문제가 있습니다. Unit1.cpp, Unit1.h, Unit2.cpp, Unit2.h, Unit3.cpp, Unit3.h :동적 StringGrid C++ Builder

나는 6 개 파일이 있습니다.

Unit1.cpp은 주 양식 용 파일입니다.

문제 : 기능 void __fastcall TForm3::Button1Click(TObject *Sender)Unit1.cppUnit2.cpp에 표시됩니다 TStringGrid에 만들려고합니다. 다음 번 클릭은 새로운 이름으로 새 TStringGrid을 작성해야합니다 (이전에 존재)

문제점을 수정하려고했지만 일부 코드를 작성했지만 충분하지 않습니다. Unit1.h에서
내가 추가 :

void __fastcall MyFunction(TStringGrid *Grid1); 

Unit1.cpp 나는 추가 : Unit3.cpp에서

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

나는 추가 :

#include "Unit1.h" 

과 버튼 클릭 기능은 다음과 같습니다

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

이제이 방법을 사용하여 동적으로 TStringGrid을 만들었습니다. 버튼을 누른 횟수만큼 TStringGrid (고유 한 이름으로)을 얼마나 많이 생성합니까? (이제 TStringGridUnit1.h에 신고해야합니다.)

+1

모든 양식, 구성 요소, 개체 및 기능의 이름을 지정하는 것이 좋습니다. 모든 것이 "ClassName #"인 코드는 유지하기 쉽지 않습니다. 나는 회사의 코드베이스에 대한 경험으로 이야기한다. – caps

+0

어떤 Unit.h에서 "StringGrind를 Unit.h에 선언해야합니다"에서 말한 것처럼'StringGrid'를 선언하고 있습니까? – caps

+0

Unit 1h에서 선언했습니다. – john

답변

0

먼저 코드가 인 경우 TStringGrid이 여러 개 생성됩니다. 양식의 같은 위치에 같은 크기의 모든 항목을 만들면 상단에있는 모양 만 볼 수 있습니다.

-

은 당신이 (Form1->dynamically_created_TStringGrid) 할 수 있기를 원하는 것은 불가능하지만 비슷한 동작을 얻기 위해 사용 가능한 방법 중 몇 가지가있다.

당신이 AddStringGrid()를 호출하고 반환 값을 저장할 수있는이 방법을 사용하여 표준 : : 벡터 방법

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 
} 

. 그런 다음 주어진 TStringGridForm1에 조작하려면 GetStringGridByName을 호출하고 조작하려는 TStringGrid의 이름을 전달하십시오. 회원 인 경우에도 std::map과 매우 비슷한 것을 구현할 수 있습니다.

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 
} 

버전은 기본적으로 동적으로 생성 TStringGrid 대신을 찾는 Parent -> Children 관계를 사용에 저장내 직감은 std::vector 방법보다 느리고 안전하지 않다고 말하고 있지만 어떤 증거도 없습니다. std::vector은 색인으로 액세스하거나 반복자를 통해 사용할 수있는 반면, 부여한 고유 이름을 "잊어 버리면"StringGrid에 도착하는 간단하고 안정적인 방법을 제공하지 않습니다. GetChildren이 있지만 매우 직관적으로 보이지는 않습니다.

-

는 처음에 나는 당신이 메모리는 TForm1::MyFunction를 호출 할 때마다 누수 얻을 것이라고 생각하지만 난 Builder 6 documentation correctly을 이해하고있어 경우, 그 사실이 아니다 :

TComponent의 클래스 또한 인 소유권 개념이 VCL 및 CLX 전체에 전파됩니다. 소유자 및 구성 요소 두 가지 속성이 소유권을 지원합니다. 모든 구성 요소에는 다른 구성 요소를 소유자로 참조하는 소유자 등록 정보 이 있습니다. 구성 요소가 다른 구성 요소를 소유하고있을 수 있습니다. 이 경우 모든 소유 된 구성 요소는 구성 요소의 Array 속성 에서 참조됩니다.

구성 요소의 생성자는 에 사용되는 단일 매개 변수를 사용하여 새 구성 요소의 소유자를 지정합니다. 전달 된 소유자가있는 경우 새 구성 요소가 소유자의 구성 요소 목록에 추가됩니다. 을 제외하고 구성 요소 목록을 사용하여 소유 구성 요소를 참조하는 경우이 속성 은 소유 구성 요소를 자동으로 제거합니다. 구성 요소에 소유자가있는 경우 으로 표시되므로 소유자가 삭제되면 해당 구성 요소가 삭제됩니다. 예를 들어, TForm은 TComponent의 자손이므로 폼이 소멸 될 때 폼에 소유 된 모든 구성 요소가 파괴되고 메모리가 해제됩니다. 이 경우 해당 소멸자가 호출 될 때 양식의 모든 구성 요소가 올바르게 정리되어 있다고 가정합니다. 심지어 GRID1에 해당 함수에 전달할 때마다 new 에드 객체를 할당하는 있지만, 이러한 개체가 여전히 Form2가 소유하고 정리됩니다

[.PDF 페이지 53] 그래서

Form2이 파괴되었을 때.

당신이 OP에 게시 한 구현을 고수하면, 사용자가 OP에 게시하지 않은 한 마지막 문자열을 제외한 문자열 격자를 조작 할 수 없다는 점에 유의해야합니다. Form2->Array.

+0

답변을 주셔서 감사합니다, 나는 그것이 그렇게 복잡하다는 것을 몰랐습니다. – john

+0

답변이 만족 스럽다면 확인란을 클릭하여 답변을 수락하십시오. 당신은 여기 새로 왔기 때문에 아마도 사이트의 둘러보기를 따라 가야 할 것입니다 : http://stackoverflow.com/tour – caps

+0

프로그램이 작동하는 동안 stringgrid (편집 필드로 입력 된 자동차에 대한 데이터를 유지하기 위해서) 만 만들고 싶습니다. 자동차는 Listbox1에 나열되어 있습니다. 하나의 파일을 선택하고 버튼을 클릭하면 선택된 자동차의 데이터가 포함 된 stringgrid가 표시됩니다. – john