Текущий архив: 2002.08.29;
Скачать: CL | DM;
ВнизПомогите разобраться Найти похожие ветки
← →
Андрусь (2002-08-13 20:34) [0]Привет всем ещё раз!Такая вот непонятка:есть 2 переменные
var1,var2:TMyObject;Нужно сделать так,чтобы можно было работать с var1, выделяя память var2.Когда мы работаем с var1 о var2 не знаем. При работе с var2 нам известен указатель на var1. Может немного путано,сейчас поясню как делал я - может чего прояснится. Я рассуждал так:переменная var1 есть указатель на адрес А1,я пихаю эту переменную в List:TList - массив указателей;Затем читаю из List - var2:=List[0];Сейчас я думаю,что var1 и var2 казывают на А1,выделяю память var2:=MyObject.Create; Далее хочу обратиться к var1,думая что адрес,на который он указывает проинициализирован....
Что я делаю неправильнобо не работает).Зараннее всем благодарен.
← →
TTCustomDelphiMaster (2002-08-13 20:59) [1]Андрусь © (13.08.02 20:34)
Все работает без проблем. Скорее всего ты так упростил описание проблеммы, что ошибка то сюда и не попала.
← →
Юрий Зотов (2002-08-13 21:48) [2]После
var2 := TMyObject.Create // именно TMyObject
переменная var2 меняет свое значение - теперь она указывает на адрес в динамической памяти, по которому разместился только что созданный объект. А переменная var1 и элемент массива List[0] остались прежними. Вы же их не меняли? Нет. А сами меняться они не могут, они не волшебные.
Вообще, зачем такие накрутки? Какие-то var1, var2 - зачем они нужны? Почему не написать просто List[0] := TMyObject.Create и спокойно работать с массивом, без всяких лишних переменных. В чем изначальная задача?
← →
Андрусь (2002-08-14 11:03) [3]Как это говорится - хочешь как проще,а получается как всегда :-{
Чего я хотел сделать - есть МДИ с подгружаемыми пакетами(я уже не раз про эту штуку спрашивал). Переменная MyForm(var1) - переменная, объявленная в модуле,который в пакете,BaseForm(var2(TMyForm=class(TBaseForm)) ) - переменная, объявленная в главном модуле(делаю всё по примеру со статьи про подгружаемые пакеты из "Королевства Дельфи"). При подгрузке пакета(секция initialization) в манагер классов(TList)загоняю класс и переменную MyForm:
initialization
Begin
ClassManager.Add(MyForm);
ClassManager.Add(TMyForm);
End;
В главном модуле хочу проинициализировать переменную MyForm через BaseForm.
Procedure TMainForm.MakeFormFromPackage(PackageName:string);
var BaseFormClass: TComponentClass;
BaseForm: TBaseForm;
PackageHandle : HMODULE;
begin
PackageHandle := LoadPackage(PackageName);
BaseFormClass := ClassManager[ClassManager.Count-1];
BaseForm := ClassManager[ClassManager.Count-2];
Application.CreateForm(BaseFormClass,BaseForm);
end;
В самом подгружаемом пакете есть ещё модули,в которых идёт обращение к MyForm. При просмотре под дебагером - там nil. Так вот чё я делаю не так и как исправить ситуацию.Зараннее всем балгодарен.
← →
Андрусь (2002-08-14 13:36) [4]Товарищи,что сразу в кусты...
← →
Андрусь (2002-08-14 20:44) [5]Алё...
← →
Андрусь (2002-08-14 21:13) [6]Тут ошибку просёк - у меня var1 указывает в никуда. Я его в List, затем присваиваю пустой var2,инициализирую var2. И пытаюсь обратиться к var1,которая в nil.
← →
Юрий Зотов (2002-08-15 01:17) [7]Насколько я понял, ClassManager - это TList. То есть, при подгрузке пакета фактически выполняется TList.Add(MyForm).
Хорошо, а чему же в этот момент равна переменная MyForm? Она глобальная, поэтому компилятор проинициализировал ее nil"ом и после этого ее никто не менял. В итоге - при подгрузке пакета мы добавили в список указатель с номером Count-2 и со значением nil. Сама переменная MyForm тоже осталась равной nil. ОК, запомним это и пойдем дальше.
А дальше непонятно зачем идет строка
BaseForm := ClassManager[ClassManager.Count-2];
Почему "непонятно зачем"? Потому что сразу за ней идет строка
Application.CreateForm(BaseFormClass,BaseForm);
которая, если сработает нормально, должна создать форму и поместить ее адрес в BaseForm. Тогда зачем нужна предыдущая строка? А ни зачем, ее можно просто убрать, и ничего не изменится. ОК, идем еще дальше.
Предположим, что все прошло нормально, форма создалась и в локальной переменной BaseForm теперь сидит ее адрес. А изменилась ли при этом переменная MyForm?
Нет. С какой такой радости она должна была измениться? Как там был nil, так он и остался. Что и показывает дебаггер.
Хорошо, а изменился ли элемент списка под номером Count-2?
Тоже нет. С какой такой радости он должен был измениться? Как там был все тот же nil, так он же и остался.
ОК, идем дальше.
А дальше мы выходим из процедуры MakeFormFromPackage и переменная BaseForm исчезает. Вместе с ней исчезает и единственная имеющаяся у нас ссылка на созданную форму (если не считать списка Application.Components). Почти приплыли - теперь, чтобы работать с этой формой надо снова искать ссылку на нее.
Разве этого Вы хотели? Думаю, что нет.
Вот пример.
var
A, B, C: integer;
begin
A := 0;
B := A; // Теперь B=0
C := A; // Теперь C=0
A := 5; // Чему теперь равны B и C?
end;
И Вы скажете: "Как были равны 0, так и остались, их же никто не менял, а сами они меняться не умеют, они не волшебные".
Хорошо, теперь представьте, что A, B и С имеют тип Pointer, а 0 и 5 - это адреса в памяти (причем 0=nil). Разве от этого что-то изменилось?
Ничего. Переменные не умеют меняться сами по себе, хоть они integer, хоть pointer. Изменив A, мы меняем только A, а B и C остаются прежними. Так почему же Вы, получив адрес формы в переменной BaseForm считаете, что он теперь должен содержаться и в переменной MyForm, и в элементе списка Count-2? Откуда он там возьмется?
> чё я делаю не так
Увы, практически все (см. выше).
> и как исправить ситуацию
Самое лучшее - на время забыть о классах и объектах и написать несколько учебных программ на тему "указатели и динамическая память". Нужно досконально разобраться с New и Dispose, GetMem и FreeMem, с типизированными и нетипизированными указателях.
А потом вернуться к объектам и понять, что работа с ними - это, по сути, та же самая работа с типизированными указателями и динамической памятью. Что MyForm - это аналог pointer, Create - аналог New/GetMem, а Free - аналог Dispose/FreeMem.
И исчезнут все вопросы. Кстати, и насчет PChar тоже, если они были.
← →
Андрусь (2002-08-15 12:58) [8]>Юрий Зотов!
Спасибо за лекцию,но это я и сам понял,я просил помочь с решением, а не читать нотации....
Извините,если слишком резко.
← →
Юрий Зотов (2002-08-15 15:03) [9]> я просил помочь с решением
С решением ЧЕГО? Чтобы предложить решение, надо знать задачу.
С самого начала я именно это и спрашивал - В ЧЕМ ИСХОДНАЯ ЗАДАЧА? Простыми русскими словами - ЧТО ВЫ ХОТИТЕ СДЕЛАТЬ
Только не надо про пакеты и переменные. Они относятся уже не к задаче, а к ее реализации.
> а не читать нотации....
Где Вы нашли нотации? Вы просили указать (цитирую) "чё я делаю не так". Я указал, конкретно и подробно. Между прочим, потратив на это совсем не 3 минуты своего времени. И что получил в ответ? Хорошо хоть, что извинились, и на том спасибо.
← →
Андрусь (2002-08-15 17:44) [10]Извините,мастер,ещё раз,но то о чём вы писали я понял сам,а если насчет исходной задачи - чё хочу сделать:
нужно сделать приложение,ипользуя интерфейс МДИ. Далее желательно,чтобы приложение,будучи установлено у заказчика могло легко переживать небольшие апгрейды на уровне дочерних форм(логично использовать пакеты).Далее переходим уже к реализации.
← →
Игорь Шевченко (2002-08-15 17:53) [11]http://www.delphikingdom.com/mastering/plugins.htm
← →
Андрусь (2002-08-15 18:01) [12]>Игорь Шевченко ©
CСпасибо,большое. Внимательнее читайте,изложенное выше(Андрусь © (14.08.02 11:03),3-я строка).Извините,если нагрубил опять.
← →
Игорь Шевченко (2002-08-15 18:12) [13]Мы же вроде раньше долго и плодотворно беседовали на эту тему...?
← →
Юрий Зотов (2002-08-15 19:37) [14]Вот это другое дело, в ближайшие дни попробую набросать простой пример (простой - это чтобы не маскировать суть деталями). Только нужно еще немного информации.
1. Я правильно понял, что главная проблема - создание, показ и работа с дочерними формами, хранящимися в BPL?
2. Все дочерние формы - одного класса, или разных? Если второе, то допустима ли иерархия классов дочерних форм (когда все они разные, но все - потомки одного базового класса)?
← →
Андрусь (2002-08-15 20:07) [15]Юрий,большое вам спасибо,что на меня не обижаетесь.
1 - да.
2 - все формы в пакетах идут от TBaseForm,о котором знает главная форма.
P.S. Может не стоит засорять "эфир",а по мылу.
Всё равно пасибо. Приятно иметь дело с понимающим человеком.
← →
IronHawk (2002-08-15 22:32) [16]
> Андрусь © (15.08.02 20:07)
Узнаю стиль .....
← →
Андрусь (2002-08-16 11:18) [17]А в чём проблемы то...
← →
Юрий Зотов (2002-08-16 19:12) [18]Еще несколько уточняющих вопросов.
1. Как планируется осуществлять эти "небольшие апгрейды на уровне дочерних форм"? Допускается ли такой вариант - старый файл BPL просто заменяется новым, в котором зашита форма того же самого класса, что и в старом, но уже с обновленной функциональностью. Если планируется иной вариант апгрейда, то какой именно?
2. MDI-форма знает только класс TBaseForm, или ей известен ВЕСЬ набор классов дочерних форм (и имен их пакетов). Если весь набор классов и весь состав пакетов заранее неизвестен, то допускается ли их формирование, скажем, по составу BPL, лежащих в заранее определенном каталоге?
3. Предположим, в какой-то момент работы MDI-форме потребовалось создать дочернюю форму. Ее класс заранее известен? Если нет, то по каким признакам может быть определен этот нужный в данный момент класс?
← →
Юрий Зотов (2002-08-18 15:03) [19]Обещанный пример лежит в кладовке.
http://delphi.mastak.ru/download/other.html
На последние три уточняющих вопроса пришлось отвечать самому себе. Я сделал это так.
1. Да, такой вариант допускается.
2. MDI-форма знает только класс TBaseForm. Все плагины лежат в отдельном и заранее известном подкаталоге.
3. Класс создаваемой формы выбирается юзером в диалоговом окошке (поскольку для примера сгодится и такой вариант).
Страницы: 1 вся ветка
Текущий архив: 2002.08.29;
Скачать: CL | DM;
Память: 0.51 MB
Время: 0.006 c