Проблем с Create на TForm наследник

11 отговора 208 прегледа
#1

Проблем с Create на TForm наследник

Значи имам един обект за визуализиране на форми. Той държи лист с формите и коя как трябва да се показва :

TShow = record
Form: TForm;
FormClass: TFormClass;
Position: TWinPos;
end;

Има метод за добавяне на форми както и един за паказването им. Проблема възниква, когато си пускам една вътрешна процедура за създаване на формата, ако не е създадена (CreatIfNil) (все едно се пуска Application.CreateForm).

Ето каква е последователността...

Значи трябва ми при добавяне на форма да задавам и променливата за достъп до формата. Пример:
AddForm(Form1, TForm1, wpTop);

Тъй като имам няколко форми, с които се занимава обекта за визуализация, ми трябва да ги съхранявам и аз го правя с масив от TShow записи. Но тук явно си изгубвам Form1 като променлива. А на мен ми трябва да мога да си променям от обекта за визуализация. Затова като извикам процедурата CreatIfNil, дава грешка (access violation).

Въпроса ми е как да си държа Form1, Form2 и т.н , така че да мога да ги подавам на CreatIfNil и всичко да работи ок.

ПП Цялата работа е малко замотана и незнам дали успях да опиша добре проблема. Надявам се, че ще има идеи...

by Waz Gaa
[email protected]
Отговор
в отговор на Waz Gaa #2

Re: Проблем с Create на TForm наследник

значи нещо не те разбирам - хем имаш масив, хем имаш и известен брой скалари, като един елемент на масива и един скалар сочат към един и същ обект?

нещо не ми се връзва...

нещото което е удобно за пазене на "масив" от обекти е TObjectList.
обектите който ще пазиш вътре може да са наследници на TForm с едно допълнително поле, TWinPos, което да си ползваш както и където ти трябва. Обръщението към форма е TMyForm(MyObjectList[j]).ShowForm, даречем
Полето TFormClass е излишно, обекта може да си каже всичко по въпроса, без много бой :-)

--------------------------------------
Започва Път от моят праг...
Отговор
в отговор на Hateras #3

Re: Проблем с Create на TForm наследник

Мда, ще се опитам да се изясня малко.
Значи, трябва ми да държа списък с обектите (променливите) или може би пък указатели към тях, които са от тип там някаква форма. Искам да си създам форма от тяхния тим и след това да им я assign-а.

TFormClass не е излишно защо в началото е сигурно, че променливите ми са nil и ще сбозяса

Да ви питам, може ли да си държа по някакъв начин лист с указатели към променливите (има си по една FormX за всеки TFormX), за да мога по късно да си assign-вам към тях. Пробвах с указатели, но нещо не ми се получи. Ако някой ги разбира, моля да ми обясни как ще стане.

Проблема е, че минавам през много обекти и тяхни методи, та не мога направо да си дам FormX от тип TFormX на някой от тях и да си създам обекта за нея.

Може би така ще прозвучи по-добре: Не искам да работя с нов указател към обект, ами с вече съществуващ (декларираната в unit-а на самия клас променлива), защото всички достъпват до обекта чрез него.

> обектите който ще пазиш вътре може да са наследници на TForm с едно допълнително поле, TWinPos

Не ми е удобно да добавям нови полета. Не ми пречи обаче да си държа един лист (TObjectList) с формите и един масив (елементите си отговарят по индекс) с TWinPos стойностите.

by Waz Gaa
[email protected]
Отговор
в отговор на Waz Gaa #4

Re: Проблем с Create на TForm наследник

жега е, та не вдявам... ама сепак май почвам да... стоплям /на къде повече?!? :-)/

май проблема е от сорта:
имаш декларирани променливи, по обичайния начин, и искаш да ги създаваш динамично, ама мноо динамично...

мхм

--------------------------------------
Започва Път от моят праг...
Отговор
в отговор на Hateras #5

Re: Проблем с Create на TForm наследник

Ахъм, и така може да се каже.

Искам да ги подам (променливите) на един клас и той да се грижи, кога да ги създава. А иначе останалия код си ги ползва без да се интересува дали са създадени.

by Waz Gaa
[email protected]
Отговор
в отговор на Waz Gaa #6

Re: Проблем с Create на TForm наследник

Така значи.
Да видим дали съм те разбрал.

1. Ти имаш декларирани променливи в унита на всяка форма. (Всъщност декларацията и се записва автоматично в дизайнтиме при File|New|Form)
2. Формите си ги креатваш динамично, когато ти потрябват. Приемам, че не ги създаваш в *.dpr-а (т.е. в Project|Options|Forms си ги прехвърлил от AutoCreate в Available Forms)
3. При креатването на екземпляр (instance) от някаква форма, ти записваш този екземпляр (м/у нас казано това си е указател) в някаква структура. Такива екземпляри от всеки клас (напр. TForm1) можеш да си създадеш колкото си искаш.
Питам те тогава:
Към кой от екземплярите ти сочи автоматично декларираната променлива (напр. Form1)
Можеш да ми/си отговориш на този въпрос само, ако намериш къде в кода си извършваш присвояване на Form1.
И ако съм те разбрал правилно, това май не става никъде

Извода: Тази автоматична променлива (Form1), не е инициализирана и можеш да я използваш само за класс функции

Дано да сме се разбрали

Отговор
в отговор на NDeu #7

Вместо да гадаем...

Waz публикувай малко код - едва ли е пове4е от 50-60 реда (?)
Другия вариант е да кажеш не решението на проблема ами самия проблем (т.е. това което като цяло искаш да постигнеш) - може да изникнат и други варианти.

---
Е т'ва е живот!
Отговор
в отговор на NDeu #8

Re: Проблем с Create на TForm наследник

>3. При креатването на екземпляр (instance) от някаква форма, ти записваш
>този екземпляр (м/у нас казано това си е указател) в някаква структура.
>Такива екземпляри от всеки клас (напр. TForm1) можеш да си създадеш
>колкото си искаш.

Не, имам само един екземпляр от всяка форма. И не ми трябва да записвам екземпляра в някаква структура, ами в някаква структура да си държа указатели към Form1, Form2 и т.н така че напрамо да си записвам в тях. Това, последното нещо не става.

ОК. Ще пусна и малко код, ако мислите, че ще помогне (Phantom, целия код си е към 200-300 реда , но така става като приложиш някой и друг pattern + допълнителни обекти.


procedure TWinMan.CreateIfNil(var AForm; AFormClass: TFormClass);
var
bError: Boolean;
Instance: TComponent;
begin
bError := false;

if not Assigned(TComponent(AForm)) then
try
Instance := TComponent(AFormClass.NewInstance);
TComponent(AForm) := Instance;

Instance.Create(FParentForm);
except
if Assigned(TComponent(AForm)) then
try
TComponent(AForm).Free;
except
bError := true;
end;

TComponent(AForm) := nil;

if bError then
raise ECreateError.Create(Err301)
else
raise ECreateError.Create(Err302);
end;
end;//CreateIfNil

Това е нещо като смесица между
стар код от програмата + Application.CreateForm = това което ми трябва.
Целта e да се създаде форма от даден клас и да се assign-не към подадената променлива.

Как се работи класа с TWinMan. Добавяш му layout-и :
procedure TWinMan.AddLayout(var AForm; AFormClass: TFormClass;
APosition: TWinPos; ADoBeforeShow: TBeforeShowProc);

Пример :
WinMan.AddLayout(frmMyClientForm, TfrmMyClientForm, wpClient, nil);

Като свършиш ги визуализираш :
procedure TWinMan.ShowLayouts;

Именно тук трябва да се извика CreateIfNil на всяка форма.

E, как според вас може да се осъществи това? Декларацията на AddLayout
може би ще претърпи промени. Най-важното е да се подаде променливата за
тази форма и после като се пусне ShowLayouts, WinMan да може да си я
създаде и аssign-не, ако трябва.


by Waz Gaa
[email protected]
Отговор
в отговор на Waz Gaa #9

Re: Проблем с Create на TForm наследник

Здравей , незнам дали съм те разбрал правилно но все пак ще искажа мнение :)
Според мен кода ти трябжа да изглежда така :

if not Assigned(TComponent(AForm)) then begin
Instance := TComponent(AFormClass.NewInstance);
TComponent(AForm) := Instance;
try
Instance.Create(FParentForm);
//FParentForm, дали си я инициализирал???????
except
// bError = ???? tova sam si go znae6

FreeAndNil(AForm);
if bError then
raise ECreateError.Create(Err301)
else
raise ECreateError.Create(Err302);
end;
end;//CreateIfNil


Освен това за запазжането ето един примерен код които не сам го проверил но би трябвало да работи

TShow = class(TObject)
Form: TForm;
FormClass: TFormClass;
Position: TWinPos;
DoBeforeShow: TBeforeShowProc; //това може да е тук
end;

var FormList : TObjectList;

constructor TWinMan.Create(??);
begin
FormList:=TFormList.Create;
//saotvetno free pri destroy
end;

procedure TWinMan.AddLayout(var AForm; AFormClass: TFormClass;
APosition: TWinPos; ADoBeforeShow: TBeforeShowProc);
var aShow:TShow;
begin
// според мен AForm e по-логично да е само Create а не CreateIfNil, ако ще
// има само по един обект. Но от друга страна ако ще ги създаваш и
//освобождаваш по няколко пъти, тогава си прав.
CreateIfNil(AForm, AformClass);
try
aShow := TShow.Create;
except
//ne6to si
raise
end;
With aShow do begin
Form:= AForm;
FormClass: AFormClass;
Position: APosition;
DoBeforeShow: ADoBeforeShow;
end;
FormList.Add(aShow);

end;


posle pri tarsene pravi6 slednoto

function GetForm(aFormClass:TFormClass):TForm;
var i:integer;
begin
result:=nil;
for i := 0 to FormList.Count -1 do
if TShow(FormList).FormClass = aFormClass then begin
result:=TForm(FormList);
break;
end;
Assert(result <> nil,'Проверката е майка на доверието :)');
end;


//за запазването става и TList но там има повече хамалогия, плюс това TObjectList при Free сам освобождава всички елемнти. От друга страна ще трябва да включиш още един unit , от което програмата ти ще стане малко по-голяма.

Надявам се че сам ти помогнал

Отговор
в отговор на mf2hd #10

Re: Проблем с Create на TForm наследник

Ами при пробването на няколко варианти и аз стигнах да изваждането на Creat-а в AddLayout (имам направо достъп до променливата, която накрая трябва да е assign-ната). Видях, че пак излиза грешка.

Тогава изкарах един Application.CreateForm(frmMyForm, TfrmMyForm) и направо премахнах употребата на допълнителния обект. Видях , че пак дава грешка. Еми значи проблема е другаде.

Направих си нов и всичко вървеше нормално.

Въпроса е интересен : лист с променливите на формите, които се създават по някое време и се assign-ват, но незнам дали реално ще възникне проблем. Най-вероятно има нещо друго, което се опитва да вземе достъп до променливата, която още не съм прикачил и затова излиза грешката.

Благодаря ви за коментарите. Извинявам се, че съм изгубил част от времето ви, но се видях в чудо с тази грешка.

Поздрави

by Waz Gaa
[email protected]
Отговор
в отговор на Waz Gaa #11

Re: Проблем с Create на TForm наследник

Това което ме съмнява е, точно този списък с променливите - не видях явно как го правиш в кода , но имам чуството че бъркаш някъде там - реално те са указатели към обекти - и ти трябва да пазиш не самата променлива ами указател към нея за да я промениш - ако съм разбрал правилно. Това май е най голямата ти разлика от стандартния метод - CreateForm - той си създава формата и assign -ва директно на подадената променлива - докато при теб минаваш през междинна такава - което предизвиква гршката - пробвай да трасираш добре като следиш точно Form1 променливите - декларирани в модулите с формите - за да си сигурен, че не подаваш грешен указател.

---
Е т'ва е живот!
Отговор