Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2003.09.15;
Скачать: [xml.tar.bz2];

Вниз

Задачка для component writer-ов. :o)   Найти похожие ветки 

 
Vuk   (2003-08-25 15:09) [0]

Версия Delphi - 6 и выше. Сделать так, чтобы в список uses модуля формы, где находится какой-то компонент добавлялись разные модули в зависимости от значения свойства этого компонента.


 
Skier   (2003-08-25 15:16) [1]

Хм...
1) А это реально ? :)
2) Зачем сие ? (или это просто ребус ? :) )


 
Юрий Федоров   (2003-08-25 15:17) [2]

А если в ран-тайме св-ва меняются, то тоже чтобы менялся uses и перекомпиляция автоматически происходила :-)


 
vuk   (2003-08-25 15:28) [3]

to Skier:
1. Угу. Я решил. Причем, решение довольно простое оказалось.
2. Предположим, что есть компонент, который, в зависимости от значения одного своего свойства, создает компонент, который не находится на форме, но при этом доступен программисту как вложенный. Эти внутренние классы могут быть самыми разными, они реализованы в отдельных модулях, и могут очень сильно отличаться по реализации. Так вот, при обычном порядке действий, когда создается такой внутренний компонент, среда не знает, в каком модуле он описан и, естественно, не прописывает этот модуль. В принципе можно зарегистрировать где-то все эти классы, но это может потянуть за собой много лишнего кода. А если решить задачу, то будет использоваться только тот модуль, где описан нужный класс.

to Юрий Федоров:
>А если в ран-тайме св-ва меняются, то тоже чтобы менялся uses и
>перекомпиляция автоматически происходила :-)
Не, я понимаю, то, что я написал может и звучит странно, но задача-то вполне реальная.


 
Skier   (2003-08-25 15:30) [4]

>vuk © (25.08.03 15:28) [3]

> Я решил. Причем, решение довольно простое оказалось.

Ну дык...не томи общественность ! Рассказывай ! :)


 
vuk   (2003-08-25 15:31) [5]

Ну... Если никто сам не докопается - расскажу. :o)


 
Skier   (2003-08-25 15:34) [6]

Злой ты ! :)
У меня, к сожалению, сейчас работы много, а то я бы подумал...

> Если никто сам не докопается - расскажу.

Можно даже небольшую статью написать.
Думаю что многим сгодится.


 
vuk   (2003-08-25 15:37) [7]

>Можно даже небольшую статью написать.
Да можно, только где ж время-то взять?


 
Skier   (2003-08-25 15:39) [8]

Что правда, то правда...


 
Юрий Федоров   (2003-08-25 15:52) [9]

>>Предположим, что есть компонент...
Поскольку такое св-во в принципе может меняться только во время дизайна, думаю, что правильное решение другое (более простое):
Компонент, которые могут быть созданы, в любом случае должны иметь какого-то общего предка с определенными св-вами (методами), иначе это действие не имеет смысла. (в любом случае общий предок есть - TComponent).
Так вот, у нашего компонента должно быть св-во, которое ссылается на другой компонент формы типа TОбщийПредок. А программист кидает на форму компонент типа TПотомокОбщегоПредка,
секция uses формы регулируется автоматически...
Вроде так


 
vuk   (2003-08-25 16:03) [10]

to Юрий Федоров:
>Поскольку такое св-во в принципе может меняться только
>во время дизайна
Неверная предпосылка. Но она здесь ни при чем. :o)

>Так вот, у нашего компонента должно быть св-во, которое
>ссылается на другой компонент формы типа TОбщийПредок
Ну, вообще говоря ссылка существует, но она ссылается не на внешний, а на внутренний компонент. В моем случае он вообще является субкомпонентом (как Label у TLabeledEdit).

>А программист кидает на форму компонент типа
>TПотомокОбщегоПредка
Напоминаю, компонент создается не пользователем и не средой, а другим компонентом и не находится непосредственно на форме.


 
Ketmar   (2003-08-25 16:10) [11]

с ходу ничего, кроме ToolAPI и ручек не придумывается.


 
vuk   (2003-08-25 16:14) [12]

to Ketmar:
>c ходу ничего, кроме ToolAPI и ручек не придумывается.
Мысль правильная, но можно и без ручек. :o)


 
Ketmar   (2003-08-25 16:17) [13]

это как "без ручек"?! а чем печатать-то?!

зыж
ну не томи, понедельник же, думать тяжко! рассказывай! %-))


 
vuk   (2003-08-25 16:21) [14]

to Ketmar:
> а чем печатать-то?!
А печатать и не надо. :o)

>ну не томи, понедельник же
Да расскажу, расскажу. Я просто пока еще надеюсь, что кто-то заинтересуется и сам раскопает. :o)


 
Ketmar   (2003-08-25 16:32) [15]

нет. я сегодня торможу (день независаемости, однако, намедни был %-). буду ждать, пока раскроют страшный секрет... %-)


 
Morrowind   (2003-08-25 18:27) [16]

Я чего-то не втыкаю. Есть компонент, он создает другой компонент, верно? Где создает? В своем конструкторе или где? И как он может создавать компонент, если не знает его? (то есть в Uses не прописан юнит, где находится вложенный компонент)

Не понимаю


 
vuk   (2003-08-25 18:36) [17]

to Morrowind:
>В своем конструкторе или где?
При присвоении значения свойству.

>И как он может создавать компонент, если не знает его?
Класс зарегистрирован в специальном списке(наподобие того, как это происходит при вызове RegisterClass). Регистрация делается в секции initialization соответствующего модуля. При присвоении значения свойству по каким-то критериям ищется нужный класс и создается его экземпляр. При этом не важно, в каком модуле находится класс. При работе в IDE никаких проблем нет, т.к. там можно себе позволить держать все классы зарегистрированными, на то это и среда разработки. Но в исполняемом модуле такая схема не недопустима т.к. это приведет к включению в .exe коде ненужных классов.


 
Fantasist   (2003-08-25 19:06) [18]

Да, в принципе, понятно, что в ToolsAPI можно раскопать чего-нибудь подходящее. Даже из того маленького кусочка с которым я работал можно написать эксперт, справляющийся с этой работой, хоть и не очень красиво. Если задача стоит, то можно копнуть и по глубже, а так лень.


 
Morrowind   (2003-08-25 19:32) [19]

Если раньше я недопонимал, то теперь ты вообще с толку сбил. Противоречишь сам себе.

Сначало было

>Сделать так, чтобы в список uses модуля формы, где находится
>какой-то компонент добавлялись разные модули

А теперь ты говоришь об exe"шнике... ты ведь не нашел способа подключать модули к уже откомпилированному exe файлу? По любому в exe"шник должны быть откомпилированы все классы, которые ты можешь потенциально использовать. О каком ненужном коде идет речь, если ты не знаешь какое свойство выставит программист в ран тайм.

Еще один пункт. Компонент создает вложенный компонент. Этот вложенный доступен как свойство первого? Но почему ты говоришь про класс:

>При присвоении значения свойству по каким-то критериям ищется
>нужный класс и создается его экземпляр

То есть, этому вложенному компоненту зачем-то передается ссылка на этот созданный класс? Вряд ли. Причем здесь тогда вложенный компонент, как он связан с этим классом?

Насчет самого этого класса. Он что, имеет одно название, но кучу реализаций в разных модулях, и в зависимости от чего-то надо подключать эти модули?

бр-р-р. В общем, опять не понял


 
vuk   (2003-08-25 20:26) [20]

to Morrowind:
>А теперь ты говоришь об exe"шнике...
Естественно. Именно заботой об отсутствии лишнего кода в .exe и определяется постановка задачи.

>По любому в exe"шник должны быть откомпилированы все классы,
>которые ты можешь потенциально использовать.
Именно так. Но если делать "в лоб", то туда попадают классы, которые не будут использованы даже потенциально.

>О каком ненужном коде идет речь, если ты не знаешь какое
>свойство выставит программист в ран тайм.
В runtime корректным присваиванием будет только то, для которого критерий соответствует классам которые оказались зарегистрированы в результате включения в проект. Если нужны класы сверх этого - модули можно подключить и вручную. Но зато не будет неявного включения кода.

>Но почему ты говоришь про класс
Потому, что компонент - это класс? :o)

>бр-р-р. В общем, опять не понял

Попытаюсь более подробно решенную задачу объяснить. Есть компонент-навигатор (похожий на TDBNavigator, но с функциональностью поболее). Он может управлять текущей позицией в БД и в нескольких различных видах визуальных компонентов. Для каждого типа реализован отдельный класс. Эти классы предоставляют методы для выполнения функций навигатора, задают количество кнопок, возвращают хинты и картинки к ним, могут определять свои типы обработчиков сообщений и т.п. А сам навигатор занимается только управлением кнопками и их отображением в нужном виде.

Существуют следующие классы:
TDBNavigatorController - для управления набором данных
TCxNavigatorController - для управления позицией в QuantumGrid 4.x
TDxNavigatorController - для управления позицией в QuantumGrid 3.x

В принципе, их может быть и больше.

У навигатора есть свойство Controller, которое хранит созданный экземпляр одного из вышеуказанных классов (это как раз и есть тот субкомпонент). Есть у навигатора также свойства, ControllerClassName(строка) и ControllerClass (ссылка на класс). Единственное, что происходит при присвоении значения свойству ControllerClassName - поиск класса по имени и присвоение найденного значения свойству ControllerClass. В SetControllerClass происходит уничтожение экземпляра, хранящегося в свойстве Controller и создание экземпляра нового класса. Сделать редактор компонента, присваивающий свойству значение ссылки на класс - не проблема. Хранить имя класса и создавать его при загрузке - тоже не проблема. Проблема в том, что при этом автоматически не подключается модуль, где класс описан. С одной стороны, можно создать модуль, где будут зарегистрированы все нужные классы, но с другой стороны, не хочется тянуть в проект, где нужно только управление позицией в наборе данных еще и код двух версий QuantumGrid. Или наоборот - туда, где нужно управлять QGrid 4 в режиме, не связанном с данными тянуть код, работающий с БД и QGrid 3.

Вот примерно и все...


 
Vuk   (2003-08-26 11:16) [21]

Ладно. Раскалываюсь.

Есть в D6 и выше такая штука - SelectionEditor. Это что-то типа ComponentEditor, только может работать с несколькими типами компонентов.
В DesignEditors описан интерфейс


ISelectionEditor = interface
["{B91F7A78-BB2C-45D9-957A-8A45A2D30435}"]
procedure ExecuteVerb(Index: Integer; const List: IDesignerSelections);
function GetVerb(Index: Integer): string;
function GetVerbCount: Integer;
procedure PrepareItem(Index: Integer; const AItem: IMenuItem);
procedure RequiresUnits(Proc: TGetStrProc);
end;


И процедура регистрации


procedure RegisterSelectionEditor(AClass: TClass; AEditor: TSelectionEditorClass);


Из всех Методов SelectionEditor интересует только RequiresUnits. он вызывается перед сохранением модуля для выбранного в дизайнере компонента и позволяет перечислить дополнительные модули, требующиеся для работы компонента. Но поскольку наш компонент может не быть выбран в дизайнере при сохранении, нужен SelectionEditor, который в любом случае переберет все компоненты на форме, найдет требуемые и перечислит нужные модули. Такой SelectionEditor нужно потом зарегистрировать для класса TComponent. Имя модуля можно получить через RTTI.


type
TMyComponentSelectionEditor = class(TSelectionEditor)
procedure RequiresUnits(Proc: TGetStrProc); override;
end;

procedure TMyComponentSelectionEditor.RequiresUnits(Proc: TGetStrProc);
procedure ProcessComponent(Comp: TComponent);
var
i: integer;
Nav : TNavigator;
UnitName: string;
begin
for I := 0 to comp.ComponentCount -1 do
if Comp.Components[i] is TNavigator then
begin
Nav := TNavigator(Comp.Components[I]);
if Nav.Controller <> nil then
begin
UnitName := GetTypeData(PTypeinfo(Nav.Controller.ClassType.ClassInfo)).UnitName;
Proc(UnitName);
end;
end;
end;

var
Root: TComponent;
begin
//Designer.Root - корневой компонент
//(форма или фрейм)
Root := Designer.Root;
if Root <> nil then
ProcessComponent(Root);
end;

procedure Register;
begin

RegisterSelectionEditor(TComponent, TMyComponentSelectionEditor);

end;



Вот оно и все.


 
Skier   (2003-08-26 11:23) [22]

Запомним и, при наличии времени, попробуем...:)



Страницы: 1 вся ветка

Форум: "Потрепаться";
Текущий архив: 2003.09.15;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.016 c
1-48622
Hawk2
2003-09-02 19:43
2003.09.15
Что за ошибка: Invalid pointer operation.


14-48700
Knight
2003-08-27 19:47
2003.09.15
Как вам такое?


3-48465
napil
2003-08-22 12:09
2003.09.15
1С файлы dbf


4-48823
Orion2
2003-07-15 12:40
2003.09.15
Переопределение оконной процедуры нескольким TEdit


1-48548
cancel
2003-09-02 08:43
2003.09.15
IBX частичный Fetch





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский