CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Dynamiczne okno i odwołanie się do komponentu

Dynamiczne okno i odwołanie się do komponentu

dział ogólny

Dynamiczne okno i odwołanie się do komponentu

Nowy postprzez piotr.kwlk » środa, 9 marca 2011, 18:19

Aby przybliżyć problem, W orm1 tworze dynamicznie Form2, następnie to samo robię i z Form2 tworze dynamicznie Form3 i gdy chce przypisać wartość z Form3 do Form1->Edit1->Text program zgłasza błąd. Oto przykład:
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   TForm2 *Form2 = new TForm2(Application);
   Form2->Show();
}

 


KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include "Unit1.h"
#include "Unit3.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
   : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm2::Button2Click(TObject *Sender)
{
    TForm3 *Form3 = new TForm3(Application);
    Form3->Show();
}
//---------------------------------------------------------------------------
void __fastcall TForm2::fun(AnsiString a)
{
   //Form2->Edit1->Text=a;
   Edit1->Text = Form3->Edit1->Text;
}
 


KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit3.h"
#include "Unit2.h"
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm3 *Form3;
//---------------------------------------------------------------------------
__fastcall TForm3::TForm3(TComponent* Owner)
   : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm3::Button1Click(TObject *Sender)
{
   //Form2->Edit1->Text = "123";
   Form1->fun("aaa");
   //Form1->Edit1->Text=Edit1->Text;
}
//---------------------------------------------------------------------------
 


Przypuszczam, że rozwiązanie jest banalne ale ja na nie nie mogę wpaść. Dodam że używam BCB6.
Piotr
Avatar użytkownika
piotr.kwlk
Bladawiec
Bladawiec
 
Posty: 25
Dołączył(a): środa, 9 marca 2011, 17:34
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP
Kompilator: Builder 6
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne okno i odwolanie sie do komponetu

Nowy postprzez polymorphism » środa, 9 marca 2011, 19:27

KOD cpp:     UKRYJ  
void __fastcall TForm2::Button2Click(TObject *Sender)
{
    TForm3 *Form3 = new TForm3(Application);
    Form3->Show(); //<--- odwołujesz się do lokalnego wskaźnika 'Form3', zdefiniowanego linię wyżej.
}

void __fastcall TForm2::fun(AnsiString a)
{
   //Form2->Edit1->Text=a;
   Edit1->Text = Form3->Edit1->Text; //<--- odwołujesz się do globalnego wskaźnika 'Form3', zdefiniowanego w 'unit3.cpp'.
}

W przypadku globalnego wskaźnika, przy tworzeniu formy "z kodu", wskaźnik Form3 nie jest poprawnie zainicjalizowany. Stąd prawdopodobnie błąd, o którym piszesz. Przypisz temu wskaźnikowi wskaźnik this wewnątrz konstruktora TForm3.

Jeśli masz w planach tworzyć jednocześnie więcej niż jedno okno klasy TForm3, nie możesz używać tego globalnego wskaźnika (za ten wskaźnik komuś w borlandzie powinni łeb urwać).
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne okno i odwolanie sie do komponetu

Nowy postprzez Cyfrowy Baron » środa, 9 marca 2011, 19:57

Jedno wyjaśnienie. Tworzysz dynamicznie obiekt wewnątrz zdarzenia:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   TForm2 *Form2 = new TForm2(Application);
   Form2->Show();


Cokolwiek deklarujesz i definiujesz wewnątrz zdarzenia nie jest dostępne poza tym zdarzeniem. Wyjaśniam chyba dokładnie to samo co polymorphism.
To oznacza, że jeżeli chcesz mieć dostęp do obiektu zdefiniowanego wewnątrz zdarzenia poza tym zdarzeniem, to powinieneś zadeklarować go jako obiekt prywatny lub publiczny w pliku nagłówkowym w sekcji private lub public.

Plik nagłówkowy np. Unit1.h
KOD cpp:     UKRYJ  
private:
        TForm3 *Form3;


Plik źródłowy np. Unit1.cpp
KOD cpp:     UKRYJ  
void __fastcall TForm2::Button2Click(TObject *Sender)
{
    Form3 = new TForm3(Application);
    Form3->Show();
}
//----------------------------------------------------------------------
void __fastcall TForm2::fun(AnsiString a)
{
   Edit1->Text = Form3->Edit1->Text;
}
Teraz Form3 jest obiektem prywatnym i jest dostępny dla każdego zdarzenia w Form2.
Pamiętaj, że to co utworzysz trzeba zniszczyć. Jeżeli to porzucisz będziesz miał wyciek pamięci. Zakładam również iż wiesz, że nie możesz utworzyć więcej niż jednego obiektu o tej samej nazwie, czyli jeżeli raz utworzysz Form3 to nie możesz go utworzyć ponownie używając nazwy Form3. Jeżeli to zrobisz a nie zniszczysz wcześniej utworzonego Form3 to ten wcześniejszy zostanie porzucony i już nie będziesz miał do niego dostępu, ale będzie wciąż istniał poza stosem pamięci. Jego miejsce zajmie nowo utworzony obiekt o tej samej nazwie.
Zalecam Tobie zapoznać się z tym wątkiem: Tworzenie dynamiczne komponentów o nieznanej jeszcze liczbie. Nie dotyczy on co prawda formularzy, ale da Tobie wyobrażenie o tym jak zarządzać obiektami tworzonymi dyunamicznie.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne okno i odwolanie sie do komponetu

Nowy postprzez piotr.kwlk » czwartek, 10 marca 2011, 22:40

Spróbowałem taj jak napisał cyfrowy baron, ale nadal mam ten sam błąd, może coś jeszcze muszę zrobić?
Zadeklarowałem:
Unit2.h
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "Unit3.h"
//---------------------------------------------------------------------------
class TForm2 : public TForm
{
__published:    // IDE-managed Components
   TButton *Button1;
   TButton *Button2;
   TEdit *Edit1;
   void __fastcall Button2Click(TObject *Sender);
private:        // User declarations

public:         // User declarations
   TForm3 *Form3;
   void __fastcall fun(AnsiString a);
   __fastcall TForm2(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm2 *Form2;
//---------------------------------------------------------------------------
#endif
 


Unit2.cpp
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include "Unit1.h"
#include "Unit3.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
   : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm2::Button2Click(TObject *Sender)
{
    Form3 = new TForm3(Application);
    Form3->Show();
}
//---------------------------------------------------------------------------
void __fastcall TForm2::fun(AnsiString a)
{
   Edit1->Text=a;
   Edit1->Text = Form3->Edit1->Text;
}


Unit3.cpp
KOD cpp:     UKRYJ  
#include <vcl.h>
#pragma hdrstop

#include "Unit3.h"
#include "Unit2.h"
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm3 *Form3;
//---------------------------------------------------------------------------
__fastcall TForm3::TForm3(TComponent* Owner)
   : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm3::Button1Click(TObject *Sender)
{
   Form2->fun("uwaga");
}
//---------------------------------------------------------------------------

Jeśli chodzi o niszczenie obiektów to akurat wiem, ale dokładnie mam problem z przedstawionym przykładem.
Piotr
Avatar użytkownika
piotr.kwlk
Bladawiec
Bladawiec
 
Posty: 25
Dołączył(a): środa, 9 marca 2011, 17:34
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP
Kompilator: Builder 6
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne okno i odwolanie sie do komponetu

Nowy postprzez polymorphism » czwartek, 10 marca 2011, 22:58

Zrób to samo z TForm2.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne okno i odwolanie sie do komponetu

Nowy postprzez Cyfrowy Baron » piątek, 11 marca 2011, 09:44

piotr.kwlk napisał(a):Spróbowałem taj jak napisał cyfrowy baron, ale nadal mam ten sam błąd, może coś jeszcze muszę zrobić?


Jaki błąd? Jaka jest treść błędu? Której linii kodu dotyczy?

Wrzuć ten projekt do załącznika.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne okno i odwołanie się do komponentu

Nowy postprzez piotr.kwlk » piątek, 11 marca 2011, 13:49

Nadal mam problem.
Tu jest komunikat i program do ściągnięcia.
http://www.pbm.cba.pl/blad.htm
Piotr
Avatar użytkownika
piotr.kwlk
Bladawiec
Bladawiec
 
Posty: 25
Dołączył(a): środa, 9 marca 2011, 17:34
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP
Kompilator: Builder 6
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne okno i odwołanie się do komponentu

Nowy postprzez Cyfrowy Baron » piątek, 11 marca 2011, 14:30

Zataiłeś istotne informacje.

Po pierwsze jeżeli zarówno Form2 jak i Form3 tworzone są dynamicznie to w opcjach projektu, w Available forms umieszczasz jedno i drugie, a nie jak u to jest u Ciebie, gdzie umieściłeś tam tylko Form2.

Po drugie to kwestia prawidłowego adresowania. W pliku nagłówkowym Unit1.h deklarację Form2 musisz umieścić w sekcji public, a nie private, by ten formularz był dostępny również dla innych okien aplikacji. Ponieważ Form2 jest tworzony przez Form1 to musi być adresowany przez Form1 w przeciwnym razie Form3 nie odnajdzie adresu dynamicznie utworzonego okna Form2.

Tak to powinno wyglądać:

Plik nagłówkowy Unit1.h:
KOD cpp:     UKRYJ  
public:
   __fastcall TForm1(TComponent* Owner);

   TForm2 *Form2;


Plik źródłowy Unit1.cpp:
KOD cpp:     UKRYJ  
#include "Unit1.h"
#include "Unit2.h"

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   Form2 = new TForm2(this);
   Form2->Show();
}
Plik nagłówkowy Unit2.h:
KOD cpp:     UKRYJ  
public:
   __fastcall TForm2(TComponent* Owner);
   TForm3 *Form3;
   void __fastcall fun(AnsiString a);


Plik źródłowy Unit2.cpp:
KOD cpp:     UKRYJ  
#include "Unit2.h"
#include "Unit1.h"
#include "Unit3.h"

void __fastcall TForm2::Button2Click(TObject *Sender)
{
    Form3 = new TForm3(this);
    Form3->Show();
}
//---------------------------------------------------------------------------
void __fastcall TForm2::fun(AnsiString a)
{
   Edit1->Text = a;
}


Plik źródłowy Unit3.cpp:
KOD cpp:     UKRYJ  
#include "Unit3.h"
#include "Unit2.h"
#include "Unit1.h"

void __fastcall TForm3::Button1Click(TObject *Sender)
{
   /* Form1->Form2->fun("uwaga"); */
   Form1->Form2->Edit1->Text = "uwaga";
}



Z takiego adresowania formularza można zrezygnować (Form1->Form2->...) jeżeli zrezygnujesz z deklaracji Form2 w pliku nagłówkowym Form1, czyli nic tam nie umieszczasz - pozostaje to puste:

Plik nagłówkowy Unit1.h:
KOD cpp:     UKRYJ  
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "Unit2.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
   TButton *Button1;
   TEdit *Edit1;
   void __fastcall Button1Click(TObject *Sender);
private:        // User declarations

public:         // User declarations
   __fastcall TForm1(TComponent* Owner);

};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


W pliku źródłowym Unit1.cpp umieszczasz tylko definicję:
KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   Form2 = new TForm2(Application);
   Form2->Show();
}
Teraz w Unit3.cpp można już zrobić tak:
KOD cpp:     UKRYJ  
void __fastcall TForm3::Button1Click(TObject *Sender)
{
   Form2->Edit1->Text = "uwaga";
}


Wygląda to niesamowicie dziwacznie i mam poważne wątpliwości czy to jest poprawnie, ale działa... :o
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne okno i odwołanie się do komponentu

Nowy postprzez piotr.kwlk » czwartek, 17 marca 2011, 00:32

Rzeczywiście działa. Jeżeli chodzi o wrzucenie Form3 do Available forms to rzeczywiście przy kombinowaniu, ono mi się tam zabłąkało.
Dla mnie jest zagadką drugi przypadek, gdzie nie deklarujemy zmiennej Form2, a w zdarzeniu tworzymy obiekt, jakby się wydawało do zmiennej wskaźnikowej której niema. Jak to możliwe ?
Piotr
Avatar użytkownika
piotr.kwlk
Bladawiec
Bladawiec
 
Posty: 25
Dołączył(a): środa, 9 marca 2011, 17:34
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP
Kompilator: Builder 6
Gadu Gadu: 0
    Windows XPChrome

Re: Dynamiczne okno i odwołanie się do komponentu

Nowy postprzez Cyfrowy Baron » czwartek, 17 marca 2011, 10:26

piotr.kwlk napisał(a):Dla mnie jest zagadką drugi przypadek, gdzie nie deklarujemy zmiennej Form2, a w zdarzeniu tworzymy obiekt, jakby się wydawało do zmiennej wskaźnikowej której niema.


Jak najbardziej jest w pliku Unit2.cpp:

KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2; // <-- jest tutaj
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Dynamiczne okno i odwołanie się do komponentu

Nowy postprzez piotr.kwlk » czwartek, 17 marca 2011, 10:55

A no tak, teraz to ja już jestem w domu. Dziękuje za udzieloną pomoc.
Piotr
Avatar użytkownika
piotr.kwlk
Bladawiec
Bladawiec
 
Posty: 25
Dołączył(a): środa, 9 marca 2011, 17:34
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP
Kompilator: Builder 6
Gadu Gadu: 0
    Windows XPChrome


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 18 gości

cron