Форум: "Потрепаться";
Текущий архив: 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.01 c