![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Tools API, написание эксперта
Meson © (2004-12-27 17:01:00)Мне необходимо изменить значение свойства у компонента
(пишется эксперт для Delphi6)
Component: IOTAComponent;
Например, установить свойство DataSet у DataSource.
Я делаю так:
var
CurrentForm: IOTAFormEditor;
DataSetComponent: IOTAComponent;
DataSourceComponent: IOTAComponent;
begin
CurrentForm := GxOtaGetFormEditorFromModule(GxOtaGetCurrentModule);
DataSetComponent := CurrentForm.FindComponent('MyDataSet');
Assert(Assigned(DataSetComponent));
DataSourceComponent := CurrentForm.FindComponent('MyDataSource');
Assert(Assigned(DataSourceComponent));
ComponentDataSource.SetPropByName('DataSet',
DataSetComponent);
// Не работает
ComponentDataSource.SetPropByName('DataSet',
'MyDataSet');
// тоже не работает
А как правильно?
Meson (2005-01-02 19:14:00) [1]> Юрий Зотов © (30.12.04 01:07) [7]
Спасибо огромное за помощь, разобрался.
Всего Вам доброго, Юрий!
Успехов в Новом году.
Юрий Зотов (2004-12-30 01:07:00) [2]Сорри, описка вышла. Конечно же, надо так:
procedure SetSession(Target, Value: TComponent);
или так:
procedure SetSession(Target, Value: TObject);
Юрий Зотов (2004-12-29 17:29:00) [3]> Meson © (29.12.04 16:36) [5]
> 2. Уточните, пожалуйста, как нужно вызывать функцию
> EnumComponents.
Вызывать - как Вы и вызываете, просто передав ей callback в параметре. Конечно, только в design-time (переменная BorlandIDEServices инициализируется самой IDE, а в run-time она остается nil - отсюда и Access Violation).
> 3. По существу моего вопроса.
Изменение свойства делается средствами RTTI, а не ToolsAPI. (посмотрите IsPublishedProp и SetObjectProp в модуле TypInfo). Причем делается вполне универсально, никакой собственный перечислимый тип для этого не нужен.
А ToolsAPI здесь требуется только для того, чтобы отловить добавление dbSession на форму. Как это сделать - навскидку не скажу, надо копаться в ToolsAPI. Но есть и гораздо более простой способ, без всяких ToolAPI - объявить свой класс формы, перекрыть у него Notification, поместить в пакет и наследовать рабочие формы от него. Вот в этом Notification все и делается, и даже очень просто.
procedure TMyForm.Notification(AComponent: TComponent; Operation: TOperation);
procedure SetSession(Target, Value: TOracleSession);
var
P: PPropInfo;
begin
P := GetPropInfo(Target.ClassInfo, 'Session', [tkClass]);
if P <> nil then
SetObjectProp(Target, P, Value, True)
end;
var
i: integer;
begin
inherited;
if Operation = opInsert then
begin
if AComponent is TOracleDataSet then
for i := 0 to ComponentCount - 1 do
SetSession(Components[i], AComponent)
else
for i := 0 to ComponentCount - 1 do
if Components[i] is TOracleDataSet then
begin
SetSession(AComponent, Components[i]);
Break
end
end
end;
Meson (2004-12-29 16:36:00) [4]> Юрий Зотов
1. Я очень расчитывал на Ваш ответ. Спасибо.
2. Уточните, пожалуйста, как нужно вызывать функцию EnumComponents.
И в каком режиме (RunTime или Design)?
- В RunTime это, по-моему, не имеет смысла (или я ошибаюсь?).
Однако я попробовал так:
uses ToolsAPI;
procedure proc(Component: TComponent);
begin
MessageDlg(Component.Name, mtInformation, [mbOK], 0);
end;
procedure TForm1.btn1Click(Sender: TObject);
begin
EnumComponents(proc);
end;
Возникает AccessViolation уже при выполнении
Module := (BorlandIDEServices as IOTAModuleServices).CurrentModule;
- В Design mode (в моем случае предполагалось именно расширение IDE)?
Как это сделать без использования эксперта?
3. По существу моего вопроса.
Я делаю три вещи. (Используется библиотека DOA – www.allroundautomations.com)
- Добавляю в активную форму компонент dbSession: TOracleSession,
- настраиваю его на нужную базу данных и
- всем компонентам формы, имеющим свойство Session,
устанавливаю значение Session := dbSession.
Т.е. необходимо изменить свойство, имеющее тип Class.
Как это делается средствами ToolsAPI?
Я перечисляю компоненты TComponent.
Проверяю, не является ли текущий компонент одним из тех, которые я ищу, и
case ComponentKind of
сkOracleDataSet:
TOracleDataSet(Comp).Session := TOracleSession(PropertyComp);
Это решение исправно работает. Мне в нем не нравится то, что
- приходится выходить за рамки ToolsAPI и
- использовать перечисляемый тип (сейчас ComponentKind содержит 8 типов,
а что будет в следующей версии библиотеки - не известно.)
Иначе говоря – решение является не достаточно общим.
Юрий Зотов (2004-12-28 08:22:00) [5]> Meson
Хотел ответить еще вчера, но не было возможности. Но, как говорится, лучше поздно, чем никогда.
Для этой задачи вовсе не требуется использование расширений IDE типа GExperts и других, все можно сделать стандартными средствами ToolsAPI. Вот пример, перечисляющий компоненты на текущей редактируемой форме, модуле данных или фрейме.
type
TEnumComponentProc = procedure(AComponent: TComponent);
procedure EnumComponents(Proc: TEnumComponentProc);
var
Module: IOTAModule;
FormEditor: IOTAFormEditor;
Root: INTAComponent;
i: integer;
begin
// 1. Получаем текущий модуль
Module := (BorlandIDEServices as IOTAModuleServices).CurrentModule;
// 2. Если он содержит форму, модуль данных или фрейм, то
// получаем ссылку на нее (него) и перечисляем компоненты.
if (Module <> nil) and
(Module.CurrentEditor.QueryInterface(IOTAFormEditor, FormEditor) = S_OK) and
(FormEditor.GetRootComponent.QueryInterface(INTAComponent, Root) = S_OK) then
with Root.GetComponent do
for i := 0 to ComponentCount - 1 do
Proc(Components[i])
end;
Как видим, для каждого компонента вызывается callback-функция. Ну а в ней уже можно хоть свойства менять, хоть что угодно еще делать, это не проблема.
Meson (2004-12-28 00:21:00) [6]Вопрос снят, спасибо
Meson (2004-12-27 22:33:00) [7]to Petr V. Abramov
Вы совершенно правы, я не дал достаточных пояснений.
1. не просто нужно. Пишется эксперт на базе GExperts
(www.gexprts.net).
2. GxOtaGetCurrentModule - Функция, возвращающая интерфейс
актульного модуля
3. Мой вопрос адресован к тем, кто знаком с проектом
www.gexprts.net
Petr V. Abramov (2004-12-27 21:49:00) [8]Зачем устанавливать св-во через IOTA? Ну, допустим, просто нужно.
Что такое GxOtaGetFormEditorFromModule?