Клубове Дир.бг
powered by diri.bg
търси в Клубове diri.bg Разширено търсене

Вход
Име
Парола

Клубове
Dir.bg
Взаимопомощ
Горещи теми
Компютри и Интернет
Контакти
Култура и изкуство
Мнения
Наука
Политика, Свят
Спорт
Техника
Градове
Религия и мистика
Фен клубове
Хоби, Развлечения
Общества
Я, архивите са живи
Клубове Дирене Регистрация Кой е тук Въпроси Списък Купувам / Продавам 20:53 28.06.24 
Компютри и Интернет
   >> Delphi
*Кратък преглед

Страници по тази тема: 1 | 2 | >> (покажи всички)
Тема Достигане до всички форми във DesignTimeнови  
АвторLSS (Нерегистриран)
Публикувано16.09.05 14:57



Здравейте народе!

Слбъсках се с едно на пръв поглед нестрашно проблемче, но ето, че вече камара часове ровя в помощната система на Delphi-то и в нета и не намирам нищо по въпроса.

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

Ето и какъв е проблема. Във връзка с изискванията на една компонента над която се мъча в момента се наложи, да се сдобия с референции на всички обекти от тип TForm, TDataModule, TFrame и така нататък, в DesignTime времето . Разбира се логично е човек да се захване с приятеля Designer на TPropertyEditor или TComponentEditor. Логично но не върши работа. Успях да се сдобия със списък с имената на всички форми добавени в проекта, като използвам callback функция викана от Designer.GetProjectModules(Proc) и съответно се надявах да получа и референции към самите форми като да кажем обходя тоя списък и поискам Designer.GetComponent(ComponentName).
Оказа се, че последната функция ми връща валидна референция, само за тази форма, за която в момента се е Hook-нал IDesigner-а. За всички останали форми са Getcomponent(ComponentName) връща nil.

И така... реших, че валидно копие се потдържа само за текущо редактираната форма в Designer-а (вече не мисля така) и реших, че мога да си създавам сам референциите за формите които ме интересуват... За целта реших да използвам низовата променлива DesignClass на callback функцията дето я подавам на Designer.GetProjectModules(Proc) и после да направя нещо от рода:

Designer.CreateComponent(TForm(GetClass(DesignClass)), nil)

за да се с сдобия с така желаната референция, ама уви низа DesignClass се оказа празен за всяка една форма дето присъства в проекта. Дори и за Текущата...

Друго което ми хрумна, е по някакъв начин да сменям Root-а на Designer последнователно с всяка една форма (нали имам все пак списък с имената им), ама не намерих начин да го направя... Първо Root е само за четене и второ все още не съм намерил начин да разбера коя форма от кой клас е.

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

Ако трябва да го обобщим, проблема се свежда до намирането на refereances на всички обекти TPersistent и TComponent в текущо редактиран проект в Delphi IDE, кото ще рече че говорим за DesignTime.

Благодаря предварително.

ПП. Става дума за Delphi 6



Тема Явно няма интерес към тематанови [re: LSS]  
Автор simple_code (Правдоподобен)
Публикувано16.09.05 22:47



Здравейте отново.

Темата я постнах аз, но сега реших и да се регистрирам.

Ще продължа да пиша, защото съм сигурен, че темата съвсем не е тривиална и някога, някак, на някого вместо да му се вгорчи живота, ще влезне тук и може би ще намери това което му трябва.

Сега: имам малък напредък в издирването на валидни референции на формите принадлежащи на проект по време на разработка.

Първо ще поясня как седят нещата при мен, за да не ме разбират хората погрешно.

1. Имаме компонента наследник на TComponent (тя е именно и във фокуса на проблема)
2. Имаме дефиниран нейн редактор, който е наследник на TComponentEditor
3. Редактора е с override-нати методи: ExecuteVerb(), GetVerbCount(), GetVerb().

Сега ясно е, че когато получим инстанция на компонентния редактор, тя пристига направо с интерфейсно копие Designer от тип IDesigner, както и с копие на компонентата.

Толкова с обясненията.

С много мъки успях да изнамеря валидни копия на обектите от типа TForm, TFrame, TDataModule и така натък, чиито модули обаче са включени в uses клаузата на Designer.Root обекта. :(

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

Използвам процедурата Designer.GetComponentNames(TypeData: PTypeData; Proc: TGetStrProc) за да докопам всички обекти от специфицирания от TypeData клас (вмоя код викам тази функция за TComponent). Proc е callback функция която третира името на намерената компонента:

type TGetStrProc = procedure(const S: string) of object

е в тялото на callback функцията правя нещо от тоя род:



var
cmpnt: TComponent;
cmpntOwner: TComponent;
begin
cmpnt := Designer.GetComponent(s);
if cmpnt <> nil then
begin
cmpntOwner := GetTopOwner(cmpnt);
if FFormsList.IndexOf(cmpntOwner.Name) = -1 then
FFormsList.AddObject(cmpntOwner.Name, cmpntOwner);
end;



т.е. попълвам списъка FFormsList с намерените от GetTopOwner() референции
GetTopOwner() не прави нищо друго освен да изнамери cmpntOwner.Owner.Owner.Owner..... докато е различен от nil

та... това което не ми харесва е че за всички компоненти трябва първо да изнамирам TopOwner-а им, после да проверявам дали "случайно" той вече не фигурира в списък и евентуално след това да го добавя... Според мен това е абсолютна глупост, ама за сега само това успях да направя. Да не говорим, че това не решава проблема напълно. Както казах и преди функцията Designer.GetComponentNames() минава през компонентите на модулите които са включени в uses клаузата на Designer.Root. Ами като нищо мога да имам форми и то достатъчен брой, които да не се използват от притежателя на компонентата ми...

Е... Чакам мненията ви...


[Fatal Error] UniverseLoader.god(666): Devision by cucumber. Please reinstall the Universe.

Редактирано от simple_code на 17.09.05 00:45.



Тема Re: Явно няма интерес към тематанови [re: simple_code]  
Автор Dark_Dirk (:-))
Публикувано18.09.05 21:44



Много съм любопитен какво искаш да прави този компонент та ти трябва списък с всички форми ?



Тема е...нови [re: Dark_Dirk]  
Автор simple_code (Правдоподобен)
Публикувано18.09.05 23:55



Сигурен съм, че не само на теб ти е любопитно за какво се мъча над това, но да кажем, че за сега това е търговска тайна. Още не съм решил дали компонентата ще е безплатна или напротив. Пък не ми се ще да се появи преди да съм я завършил (ако не се е появила вече де).

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

Всъщност вече успях да разреша проблема в голяма степен и въпреки това не изцяло...

Успях да се сдобия с референции на всички форми, рамки и модули с данни които са добавени в проекта и по един или друг начи се свързват помежду си чрез uses клаузите си. Т.е. вече не съм зависим само от uses клаузата на притежателя на компонентата ми. Интересното е, че ако да кажем добавим една нова форма в проекта, която обче не се използва от никоя друга част на приложението, все още не мога да я достигна. Това всъщност е проблем, защото формата може да се извика индиректно от някой модул, в които не е дефинирана друга форма и в крайна сметка, ще се окаже, че отново не върша работата на 100%. Все пак ако всички форми се използват по един или друг начин от други форми, компонентата ми успява да изнамери пълния списък. Ето и как стана това:

Като начало използвам онази методика, която я показах във втория постинг, за да събера всички модули в които има дефинирани форми които са свързани чрез uses клаузата на Designer.Root (няма значение дали това е направено в interface или implementation частта). Все още не съм изнамерил по икономичен метод, но за сега и това върши работа.

След като се сдобия с референциите на всички използвани от Designer.Root-а форми, създавам интерфейсно копие от типа IDesigner за всяка една от тях. Това става така:


var
dsgnr: IDesigner;
index: integer;
begin

for index := 0 to FFormsList.Count - 1 do
begin
TForm(FFormsList.Objects[index]).Designer.QueryInterface(IDesigner, dsgnr);
GetUsedFormsFromDesigner(dsgnr);
end;

end;


Ключовите моменти тук са два. Първо TForm.Designer не е от типа IDesigner,
а от тип IDesignerHook. Това е нещо като орязана версия на интерфейса IDesigner. За мое щастие, се оказа, че чрез него мога да създам валидно копие на IDesigner отнасящ се до същата форма, използвайки вродената за интерфейсите функционалност QueryInteface().
От тук нататък всичко се повтаря за създадения dsgnr по същия начин, като се съблюдава да няма повторения във FFormsList... Всъщност структурата на всички приложения които пишем може да се представи като ориентиран граф и процедурата GetUsedFormsFromDesigner() се грижи да обходи възлите на графа (или поне докъдето стигне) започвайки от върха dsgnr. Разбира се, също така трябва и да внимаваме, да не попаднем в някой цикъл от графа, но цялата логика за това е реализирана в GetUsedFormsFromDesigner().

Остават проблемите които дискутирах във втория постинг. Абсолютно безумие да превъртам всички възможни компоненти, за да се сдобия с техния собственик... За жалост за сега нещата са такива и в общи линии за сега ми вършат работа на 90%. Разбира се ще продължавам да се мъча докато не се сдобия с каквото ми тряба. Убеден съм, че има начин, щото така или иначе в IDE тази функционалност е реализирана някак. Освен това съм сигурен, че в момента в който IDE-то зареди някой проект, то създава копия на всики форми, рамки и модули с данни... Щом го прави, все ще има начин да се докопам до тях!

:))

Та за сега до тук съм стигнал...
Като успея да реша проблема изцяло, ще напиша един постинг с примерен сорс, как да се справяте с тази задача, ако ви дойде до главата. Разбира се, ако някой не ме изпревари и не покаже метод, който прави моя тотално безсмислен... Пак ви казвам... за мен това на което съм се спрял на момета саксва....

[Fatal Error] UniverseLoader.god(666): Devision by cucumber. Please reinstall the Universe.

Редактирано от simple_code на 19.09.05 00:03.



Тема Re: е...нови [re: simple_code]  
Автор Mixy (миксер)
Публикувано19.09.05 12:27



> Абсолютно безумие да превъртам всички възможни компоненти, за да се сдобия с техния собственик.

Май друг начин няма. Когато е в design time, това не е толкова страшно.

> Освен това съм сигурен, че в момента в който IDE-то зареди някой проект, то създава копия на всики форми, рамки и модули с данни... Щом го прави, все ще има начин да се докопам до тях!

Средата зарежда и парсва всички необходими файлове, започвайки от сорса на проекта. Ти също можеш да го направиш или поне в частта им uses. Това не е толкова бавно и тежко, колкото изглежда на пръв поглед, но все пак консумира време и ресурси и ще работи само в design time.

> Интересното е, че ако да кажем добавим една нова форма в проекта, която обче не се използва от никоя друга част на приложението, все още не мога да я достигна.

Ако имаш такъв unit, който не се вика никъде и не е описан в никой uses блок, той въобще не се компилира и не се свързва в EXE-то. Ако това е форма, тя задължително се описва в .pas файла (сорса на проекта), дори и да няма референции към нея. Можеш да я достигнеш по горния метод.

Mixy


Тема Re: е...нови [re: simple_code]  
Автор Dark_Dirk (:-))
Публикувано19.09.05 12:51



Незнам какво правиш, но нещо в това твое твърдение ми се струва нелогично:

> Освен това съм сигурен, че в момента в който IDE-то зареди някой проект,
> то създава копия на всики форми, рамки и модули с данни...

Аз пък съм 100% убеден, че като отворя един проект с над 300 форми, Delphi-то зарежда само отворените в редактора форми и то когато ги покажеш с F12 т.е. когато има нужда от тях. И затова ми се вижда нелогично да търсиш референции дето според мен ги няма.



Тема Re: е...нови [re: Dark_Dirk]  
Автор simple_code (Правдоподобен)
Публикувано19.09.05 14:18



Ами помисли малко.
Когато зареждаш проекта, IDE-то се бави занчително време за да зареди всички форми. После като показваш коя да е от тях с F12 времето за изваждането на формата е значително по-малко отколкото за началното и зареждане. Естествено, това е косвено доказателство на твърдението ми, но все пак е логично.

Освен това, както казах успях да намеря валидни копия на всички форми които са свързани, чрез uses клаузите си, така че имам и пряко доказателство на твърдението си.

След редакцията
Dark_Dirk и аз и ти сме прави на 50%.
Оказа се, че всички заредени форми от проекта имат валидно копие, независимо, дали са показани или не. Когато затвориш unita обаче, копието и се губи... :(

[Fatal Error] UniverseLoader.god(666): Devision by cucumber. Please reinstall the Universe.

Редактирано от simple_code на 19.09.05 17:46.



Тема Re: е...нови [re: Mixy]  
Автор simple_code (Правдоподобен)
Публикувано19.09.05 14:32



Ами бих бил благодарен, ако ми обясниш как да го направя.

Една от първите ми идеи беше да търся референциите именно там, но не мога да изнамеря валидни копия само по списъка на използваните unit-и и форми.

В първия постинг коментирах тази тема и по-точно използването на Designer.GetProjectModules(). Както казах и тогава callback процедурата дето ползвам там открива валидно копие само за Designer.Root формата (ако е форма, разбира се).

В предишния ми постинг съм се изразил малко неясно. Да, знам, че ако даден unit не се свърже с никои друг, той не се компилира. Имах предвид, че в сорса на проекта се добавят всички форми автоматично, че и по подразбиране те са AutoCreate. Какво става обаче, ако имам unit в които няма дефинирана форма, но чрез някоя функция или процедура се създава валидно копие на форма (в RunTime), която не се използва от никоя друга форма в проекта?

Това ми беше проблема и продължава да е...

Колкото до това, че има ограничения само за DesignTime, няма проблеми. Поведението на компонентата в RunTime е коренно различно и изобщо тогава не се нуждае от тази функционалност.

Благодаря все пак.

И още нещо. Имате ли представа, как мога да се сдобия с активните референции на даден интерфейс... Сега ми е хрумнало да търся такива за IDesigner.

[Fatal Error] UniverseLoader.god(666): Devision by cucumber. Please reinstall the Universe.

Редактирано от simple_code на 19.09.05 17:09.



Тема Re: е...нови [re: simple_code]  
Автор Mixy (миксер)
Публикувано19.09.05 21:54



Материята, която засягаш, е доста сложна и малко хора са достатъчно компетентни, за да я дискутират (аз не спадам към тях).

> Какво става обаче, ако имам unit в които няма дефинирана форма, но чрез някоя функция или процедура се създава валидно копие на форма (в RunTime), която не се използва от никоя друга форма в проекта?

При положение, че твоя компонент търси активните форми само в design time и има съвсем друго поведение в run-time, формите, създадени динамично в run-time не бива да те притесняват.

Относно парсването на файловете на проекта, това беше просто идея - ако намериш името на .pas файла на главната програма, би следвало да имаш достъп до всички останали файлове.

Виж също и обекта TScreen. Той поддържа списък с всички активни форми, data-модули и т.н., но само в run-time. Разгледай сорса му, както и целия модул Forms - със сигурност ще откриеш интересни неща.

Успех!

Mixy


Тема Re: е...нови [re: Mixy]  
Автор simple_code (Правдоподобен)
Публикувано20.09.05 01:18



Ами нямам друг избор като чели. Щом трябва ще чета (което обаче никак не ми харесва )...

>При положение, че твоя компонент търси активните форми само в design time и има съвсем друго поведение в run-time, формите, създадени динамично в run-time не бива да те притесняват.

Не е точно така, защо поведението на компонентата въпреки, че е различно в run time, зависи много от това което се е случило в design time, т.е. така или иначе тази форма ми трябва да я имам...

Всъщност в крайна сметка, като чели идеята с парсването не е лоша, макар че има някои недостатъци... Но... има начин да намеря всички DFM файлове и да кажем ако си напиша парсер за тях (примерно) все ще имам необходимата ми информация... Тук се появяват разни други проблеми, ама с това ще се захвана, ако скоро не успея начин да събера информацията по друг "по-лесен" начин.

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

Какво да ви кажа... разгледах някой модулчета които се намират в .../Borland/Delphi6/Source/ToolsAPI/ направо се хванах за главата... Ама подозирам, че там мернах нещо дето може да свърши някъква работа.... само преди това трябва да си изясня кое какво е.... Лошото е че няма хлп :)

[Fatal Error] UniverseLoader.god(666): Devision by cucumber. Please reinstall the Universe.



Страници по тази тема: 1 | 2 | >> (покажи всички)
*Кратък преглед
Клуб :  


Clubs.dir.bg е форум за дискусии. Dir.bg не носи отговорност за съдържанието и достоверността на публикуваните в дискусиите материали.

Никаква част от съдържанието на тази страница не може да бъде репродуцирана, записвана или предавана под каквато и да е форма или по какъвто и да е повод без писменото съгласие на Dir.bg
За Забележки, коментари и предложения ползвайте формата за Обратна връзка | Мобилна версия | Потребителско споразумение
© 2006-2024 Dir.bg Всички права запазени.