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

Вниз

Tools API, написание эксперта   Найти похожие ветки 

 
Meson ©   (2004-12-27 17:01) [0]

Мне необходимо изменить значение свойства у компонента
(пишется эксперт для 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");
  // тоже не работает

А как правильно?


 
Petr V. Abramov ©   (2004-12-27 21:49) [1]

Зачем устанавливать св-во через IOTA? Ну, допустим, просто нужно.
 Что такое GxOtaGetFormEditorFromModule?


 
Meson ©   (2004-12-27 22:33) [2]

to Petr V. Abramov

Вы совершенно правы, я не дал достаточных пояснений.

1. не просто нужно. Пишется эксперт на базе GExperts
  (www.gexprts.net).

2. GxOtaGetCurrentModule - Функция, возвращающая интерфейс
  актульного модуля

3. Мой вопрос адресован к тем, кто знаком с проектом
  www.gexprts.net


 
Meson ©   (2004-12-28 00:21) [3]

Вопрос снят, спасибо


 
Юрий Зотов ©   (2004-12-28 08:22) [4]

> 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-29 16:36) [5]

> Юрий Зотов

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-29 17:29) [6]

> 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;


 
Юрий Зотов ©   (2004-12-30 01:07) [7]

Сорри, описка вышла. Конечно же, надо так:
procedure SetSession(Target, Value: TComponent);
или так:
procedure SetSession(Target, Value: TObject);


 
Meson ©   (2005-01-02 19:14) [8]

> Юрий Зотов ©   (30.12.04 01:07) [7]

Спасибо огромное за помощь, разобрался.

Всего Вам доброго, Юрий!
Успехов в Новом году.



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

Форум: "Компоненты";
Текущий архив: 2005.10.23;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.035 c
14-1128185779
BerkeleyMan
2005-10-01 20:56
2005.10.23
Полезная программа (информация о классе)


3-1126155558
Ol
2005-09-08 08:59
2005.10.23
MSSQL+ADO+TQuery+TDBEdit


14-1128424032
syte_ser78
2005-10-04 15:07
2005.10.23
avi в vob


14-1128271384
Piter
2005-10-02 20:43
2005.10.23
Прикольно блин :)


3-1126680925
erika
2005-09-14 10:55
2005.10.23
Обработка матрицы (матрица представлена в виде расчетной View)





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский