Dynamiczne TForm i ich zwalnianie

0

Witam,
od paru dni męczę się z pewnym problemem dotyczącym usuwania/niszczenia/zwaniania (jak zwał tak zwał) TFormy, zwanej w moim projekcie TPanelForm. Tworzę ją w MainForm w ten sposób:

 
var
 List:TList;
 
 List.Add(TPanelForm.Create(Self));
 Sleep(100);
 Clnts[StrToInt(ListView[1,ListView.Selection.Top])].ID:=List.Count-1;
 with TPanelForm(List[List.Count-1]).Clnts do begin
  _Clnts:=Clnts[StrToInt(ListView[1,ListView.Selection.Top])]._Clnts;
  [...]
  ID:=List.Count-1;
  Show;
 end;

Przypisuje jej kilka wartości itd, niby wszystko działa. Jednak problem się pojawia, gdy daną formę chcę zwolnić. Robiłem to na wiele sposobów. Przede wszystkim gdy chcę się danej formy pozbyć odpalam daną procedurę w MainForm. Zwalniałem ją używając TPanelForm(List[ID]).Free;, TPanelForm(List[ID]).Realese problem jednak jest taki, iż forma jedynie się kryje, dane procedury funkcje dalej się odpalają. No i jakby było tego mało podczas gdy chciałem użyć Free wywalało błąd: "System Error. Code: 5. Odmowa dostępu". Jak zrobić by taką formę zniszczyć raz, ale na dobre?

0

TPanelForm.Create(Self)

Tak się raczej nie tworzy form. Spróbuj Application.CreateForm();

1

TPanelForm.Create(nil); a potem Free jak próbowałeś. Pamiętaj jednak, że po zwolnieniu formy musisz usunąć ją z listy aby się już do niej nie odwoływać. Innym wyjściem jest użycie TObjectList z ustawionym OwnsObject na true z modułu contnrs. Wtedy wystarczy po prostu List.Delete(10); i forma o indeksie 10 zostanie usunięta z listy i zwolniona. Jednak pamiętaj aby do konstruktora przekazać nil bo inaczej będą problemy

0

Dzięki wielkie :) Pokombinuję

0
-123oho napisał(a):

TPanelForm.Create(Self)

Tak się raczej nie tworzy form. Spróbuj Application.CreateForm();

Fragment RTL z Delphi 7:

procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
var
  Instance: TComponent;
begin
  Instance := TComponent(InstanceClass.NewInstance);
  TComponent(Reference) := Instance;
  try
    Instance.Create(Self);
  except
    TComponent(Reference) := nil;
    raise;
  end;
  if (FMainForm = nil) and (Instance is TForm) then
  begin
    TForm(Instance).HandleNeeded;
    FMainForm := TForm(Instance);
  end;
end;

Czyli w uproszczeniu, to samo, co zwykłe utworzenie poprzez konstruktor.

0

forma jest normalnym obiektem i nic nie stoi na przeszkodzie aby tak ją tworzyć

Z tego co pamiętam jakiś czas temu był problem z tworzeniem form taką metodą kiedy podana przeze mnie działała ok.
No ale widzę że zaproponowane przeze mnie rozwiązane jest godne potępienia i zasługuję na -100. Pozdrawiam hejterów :> (i nie bierz tego do siebie @abrakadaber ).

0
  1. minusa ode mnie dostałeś za minięcie się z prawdą ponieważ "Tak się raczej nie tworzy form" właśnie tym było (jedynie mam nadzieję, że napisałeś to nieświadomie) a było to niejako sedno Twojej wypowiedzi.
  2. Pokaż mi taki przypadek a pokażę Ci gdzie jest błąd. Nie może się nie udać Form := TForm.Create(nil) i jednocześnie powieść się Application.CreateForm(TForm, Form); ponieważ CreateForm robi między innymi Create()
  3. Mogło być tak, że błąd powodowało coś co było tworzone w OnCreate Formy ale to wtedy jak czepiać się łysego, że grzebienie są drogie.
0
  1. minusa ode mnie dostałeś za minięcie się z prawdą ponieważ "Tak się raczej nie tworzy form" właśnie tym było (jedynie mam nadzieję, że napisałeś to nieświadomie) a było to niejako sedno Twojej wypowiedzi.

Ciekawe że inni minusów za błędy nie dostają & nie widzę nic złego w innej metodzie tworzenia form, nie wprowadzam w błąd.

  1. Pokaż mi taki przypadek a pokażę Ci gdzie jest błąd. Nie może się nie udać Form := TForm.Create(nil) i jednocześnie powieść się Application.CreateForm(TForm, Form); ponieważ CreateForm robi między innymi Create()

Gdyby to był mój problem. Ja sobie ze swoimi problemami daję radę i bez pomocy osób które minusują za podanie innej (być może nieskutecznej) metody.

  1. Mogło być tak, że błąd powodowało coś co było tworzone w OnCreate Formy ale to wtedy jak czepiać się łysego, że grzebienie są drogie.

Nie znam przyczyn, pamiętam raz podobną sytuację gdzie pytacz używał Create i też mu bodaj na Free crashowało. Wtedy właśnie użycie tego pomogło. Detali nie pamiętam, chcesz to sobie poszukaj.

0

ty nie podałeś innej - zanegowałeś coś co jest podstawą delphi - podstawowy sposób tworzenia instancji obiektu

1.Nie obiektu tylko TForm (to że TForm jest obiektem nie zmienia tutaj niczego).
2.Podałem inną metodę na osiągnięcie coś takiego (zauważ że taka metoda jest używana np. w application main), która jest podobna.
3.Obie metody są poprawne, jednak jakieś zmiany robią. I to zmiany które nie powodują że moja nie będzie działać.
4.Jedynym moim potencjalnym błędem było zasugerowanie tworzenia form zawsze przez tą metodą co nie jest potrzebne (nie będzie na dobrą sprawę zmieniało działania). Napisałem też 'raczej', gdyż nie byłem absolutnie przekonany. Czy błędem jest tworzenie form tą metodą (co jak zauważyliście jest bardzo podobne)? Nie.
5.Nadal chodziło mi o to że ktoś zmieniając sposób tworzenia formy obszedł/rozwiązał ten problem (nigdy nie wnikałem). Więc również główny sens mojego zdania nie jest błędny.
Czy nadal Twoim zdaniem zasługuję na minusa? Jeżeli tak to nie mamy o czym rozmawiać.

0
-123oho napisał(a):

1.Nie obiektu tylko TForm (to że TForm jest obiektem nie zmienia tutaj niczego).

nosz kura jak niczego nie zmienia???? Skoro TForm JEST OBIEKTEM to go dotyczą DOKŁADNIE TAKIE SAME ZASADY JAK KAŻDY OBIEKT!

2.Podałem inną metodę na osiągnięcie coś takiego (zauważ że taka metoda jest używana np. w application main), która jest podobna.

Jednocześnie bardzo wyraźnie stwierdzając, że Create() JEST ZŁA

3.Obie metody są poprawne, jednak jakieś zmiany robią. I to zmiany które nie powodują że moja nie będzie działać.

Nie do końca. Jedna z niepisanych zasad programowania w Delphi (i pewnie wszystkich językach bez odśmiecacza) jest co sam stworzyłeś, sam zwolnij. Tworzenie dynamiczne komponentów (w tym i form) z podawaniem właściciela prędzej czy później się zemści. Niestety ale żeby się tak bawić trzeba mieć trochę większą wiedzę jak to działa (nie mówię, że Ty nie masz ale na pewno nie ma jej pytacz) albo po prostu uwierzyć na słowo i stosować się do tej zasady. Oszczędzi to programiście sporo problemów i dziwnych błędów (np. AV) przy zwalnianiu ręcznym komponentów (i form też) lub wycieków pamięci.

4.Jedynym moim potencjalnym błędem było zasugerowanie tworzenia form zawsze przez tą metodą co nie jest potrzebne (nie będzie na dobrą sprawę zmieniało działania). Napisałem też 'raczej', gdyż nie byłem absolutnie przekonany. Czy błędem jest tworzenie form tą metodą (co jak zauważyliście jest bardzo podobne)? Nie.

nie - musisz zdać sobie sprawę, że jednak ludzie zwracają uwagę na to co piszesz bo jesteś tu jakiś czas i jakąś tam wiedzę masz.

5.Nadal chodziło mi o to że ktoś zmieniając sposób tworzenia formy obszedł/rozwiązał ten problem (nigdy nie wnikałem). Więc również główny sens mojego zdania nie jest błędny.

Bardzo dobrze to ująłeś - jeśli już to jest to OBEJŚCIE problemu a nie jego naprawa. Sprawia, że teraz działa ale czy zawsze? W innym wątku rzucasz się jak pchła na psie o 6 (słownie SZEŚĆ) linijek banalnego (żeby nie napisać prostackiego) kodu a tutaj nie przeszkadza Ci podanie obejścia? Dziwne i niekonsekwentne wg mnie.

Czy nadal Twoim zdaniem zasługuję na minusa?

i tak Ci się nie liczy...

Jeżeli tak to nie mamy o czym rozmawiać.

Ja dochodzę do wniosku, że w większości przypadków nie mamy o czym rozmawiać... A to nie jest pierwszy taki raz.

0

nosz kura jak niczego nie zmienia???? Skoro TForm JEST OBIEKTEM to go dotyczą DOKŁADNIE TAKIE SAME ZASADY JAK KAŻDY OBIEKT!

Tak, ale nie zmienia to faktu że ktoś może sobie zaplanować żeby nie tworzyć go po prostu gdyż np. trzeba go zarejesterować w aplikacji albo jest to zalecane ETC. . Dokonujesz nadinterpretacji tego co piszę.

Jednocześnie bardzo wyraźnie stwierdzając, że Create() JEST ZŁA

Tak, nazywajmy konstruktory Init bo mi się Create nie podoba. Raz jeszcze nadinterpretacja.

Nie do końca. Jedna z niepisanych zasad programowania w Delphi (i pewnie wszystkich językach bez odśmiecacza) jest co sam stworzyłeś, sam zwolnij. Tworzenie dynamiczne komponentów (w tym i form) z podawaniem właściciela prędzej czy później się zemści. Niestety ale żeby się tak bawić trzeba mieć trochę większą wiedzę jak to działa (nie mówię, że Ty nie masz ale na pewno nie ma jej pytacz) albo po prostu uwierzyć na słowo i stosować się do tej zasady. Oszczędzi to programiście sporo problemów i dziwnych błędów (np. AV) przy zwalnianiu ręcznym komponentów (i form też) lub wycieków pamięci.

Chodzi ci o niepodawanie parenta (nil jako parametr Create)? Wiesz, jest jeszcze inna szkoła która zaleca robienie wszystko z parentem żeby się samo zwalniało. Ja robię zazwyczaj też bez parenta, ale tutaj myślałem że VCL wymaga tworzenia z parentem żeby nie było właśnie dziwnych crashów.

nie - musisz zdać sobie sprawę, że jednak ludzie zwracają uwagę na to co piszesz bo jesteś tu jakiś czas i jakąś tam wiedzę masz.

To że jakąś wiedzę mam nie zależy od tego że jakiś czas tu jestem. Nie wydaje mi się żebym cieszył się tutaj jakąś specjalną renomą. Ale załóżmy że tak, jestem tutaj megagwiazdą... To jeszcze nie powód żeby mnie bezgranicznie słuchać ale tak, załóżmy że mnie bezgranicznie słuchają. Na szczęście są osoby które naprostują to co mówię bo i znają się bardziej na danej technologii. I o to chyba chodzi w forum? Bardzo mi miło że mi powiedziałeś jaka jest różnica, bo nie wiedziałem. Tylko nie widzę jeszcze w tym strasznego powodu żeby mnie od razu minusować, zwłaszcza że wytłumaczyłem że chodziło mi o coś innego niż się tobie wydaje.

Bardzo dobrze to ująłeś - jeśli już to jest to OBEJŚCIE problemu a nie jego naprawa. Sprawia, że teraz działa ale czy zawsze? W innym wątku rzucasz się jak pchła na psie o 6 (słownie SZEŚĆ) linijek banalnego (żeby nie napisać prostackiego) kodu a tutaj nie przeszkadza Ci podanie obejścia? Dziwne i niekonsekwentne wg mnie.

Teraz właśnie zauważyłem że to było obejście. No i dobrze że się czepiasz, bo dzięki temu wiem więcej (i nie tylko ja).

i tak Ci się nie liczy...

Gdyby mi się liczyło to bym miał chyba najgorszy wynik na tym forum. I nie wynika to co najmniej z mojej głupoty ale z tego że mój styl wypowiedzi nie podoba się niektórym osobom. Problem polega na tym że zauważyłem że o ile kiedyś jeżeli rzeczywiście napisałem coś mądrego to otrzymywałem parę plusów a dzisiaj za podobnie mądrą wypowiedź nie otrzymuję ani jednego [cud że nie minusują]. Raz jeszcze widać że minusy niewiele mają wspólnego z techniczną jakością mojej wypowiedzi, natomiast mają wiele z tym za jakiego uchodzę na forum. Dlatego też walczę z minusowaniem przez hejtów, chociaż jak słusznie zauważyłeś większej różnicy mi to nie robi. A zwłaszcza uważam że lepiej niż się minusować jest wyjaśnić pewne kwestie.

Ja dochodzę do wniosku, że w większości przypadków nie mamy o czym rozmawiać... A to nie jest pierwszy taki raz.

Ja ciebie do niczego nie zmuszam, jeżeli uważasz że nie mamy o czym rozmawiać to nie musimy. Dochodzę do podobnego wniosku po twoich nadinterpretacjach tego co piszę.

1 użytkowników online, w tym zalogowanych: 0, gości: 1