На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Обязательно выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.

Этот раздел предназначен для вопросов, посвященных разработке компонентов, а также для тестирования собственных бесплатных компонентов с открытым исходным кодом.

Здесь запрещается:
1. Размещать ссылки на какие-либо коммерческие компоненты, реализующие требуемую функциональность.
2. Обсуждать и тестировать коммерческие компоненты или компоненты с закрытым кодом.
3. Давать ссылки на сайты с исходным кодом компонентов. Все тестируемые исходные коды должы быть размещены на сайте ИСХОДНИКИ.RU.
Модераторы: Rouse_, DimaBr
  
> Создание свойств-множеств в компоненте , Создание свойств-множеств в компоненте
    Добрый день!

    Создаю свойства-множества в моем компоненте по такой схеме:

    Код:

    ExpandedWrap disabled
      unit MyComponent;
       
      interface
       
      uses
        SysUtils, Types, Classes;
       
      type
      TMyEnumType = (eFirst, eSecond, eThird);
      TMySetTypeFirst = (poFirst1, poSecond1, poThird1);
      TMySetTypeSecond = (poFirst2, poSecond2, poThird2);
      TMySetTypeThird = (poFirst3, poSecond3, poThird3);
       
      TMySetType = set of TMySetTypeFirst; // TMySetTypeSecond? TMySetTypeThird?
       
      type
      TMyComponent = class(TComponent)
      private
      { Private declarations }
      FMyEnum: TMyEnumType;
      FMyOptions: TMySetType;
      protected
      { Protected declarations }
      public
      { Public declarations }
      published
      { Published declarations }
      property MyEnumProp: TMyEnumType read FMyEnum write FMyEnum;
      property MyOptions: TMySetType read FMyOptions write FMyOptions;
      end;
       
      procedure Register;
       
      implementation
       
      procedure Register;
       
      begin
      RegisterComponents('Samples', [TMyComponent])
      end;
       
      end.


    С TMySetType все понятно, создается выбор из множества первого типа (TMySetTypeFirst) от TMyEnumType = eFirst, а как динамично подключать (или переключать) к TMySetType множества TMySetTypeSecond (если TMyEnumType = eSecond) и TMySetTypeThird (если TMyEnumType = eThird), чтобы MyOptions показывали нужные мне типы множеств (TMySetTypeFirst или TMySetTypeSecond или TMySetTypeThird)?

    Спасибо
    Сообщение отредактировано: SkAndriy -
      обычным способом никак. Так как с точки зрения компилятора это разные типы. Но можно подменять визуально (если я правильно понял и тебе это нужно выбирать через дизайнер)

      ExpandedWrap disabled
        uses DesignIntf, Classes, DesignEditors, TypInfo;
         
        type
          TMyEnumType = (eFirst, eSecond, eThird);
          TMySetTypeFirst = (poFirst1, poSecond1, poThird1);
          TMySetTypeSecond = (poFirst2, poSecond2, poThird2);
          TMySetTypeThird = (poFirst3, poSecond3, poThird3);
         
          TMyComponent = class(TComponent)
          private
          { Private declarations }
            FMyEnum: TMyEnumType;
            FMyOptions: Integer;
          published
            property MyEnumProp: TMyEnumType read FMyEnum write FMyEnum;
            property MyOptions: Integer read FMyOptions write FMyOptions;
          end;
         
          TMySetTypeProperty = class(TEnumProperty)
          private
            function GetTypeInfo: PTypeInfo;
          public
            function GetValue: string; override;
            procedure GetValues(Proc: TGetStrProc); override;
            procedure SetValue(const Value: string); override;
          end;
         
         
        procedure Register;
         
         
        implementation
         
        uses SysUtils;
         
        procedure Register;
        begin
          RegisterComponents('test', [TMyComponent]);
          RegisterPropertyEditor(TypeInfo(Integer), TMyComponent, 'MyOptions', TMySetTypeProperty);
        end;        
         
        function TMySetTypeProperty.GetTypeInfo: PTypeInfo;
        var
          Obj: TPersistent;
        begin
          Obj := GetComponent(0);
          if Assigned(Obj) and (Obj is TMyComponent) then
            with TMyComponent(Obj) do
            begin
              case MyEnumProp of
                eFirst:  Result := TypeInfo(TMySetTypeFirst);
                eSecond: Result := TypeInfo(TMySetTypeSecond);
                eThird:  Result := TypeInfo(TMySetTypeThird);
              end;    
            end
          else
            Result := GetPropType;
        end;
         
        function TMySetTypeProperty.GetValue: string;
        var
          L: Longint;
        begin
          L := GetOrdValue;
          with GetTypeData(GetTypeInfo)^ do
            if (L < MinValue) or (L > MaxValue) then L := MaxValue;
          Result := GetEnumName(GetTypeInfo, L);
        end;
         
        procedure TMySetTypeProperty.GetValues(Proc: TGetStrProc);
        var
          I: Integer;
          EnumType: PTypeInfo;
        begin
          EnumType := GetTypeInfo;
          with GetTypeData(EnumType)^ do
          begin
            for I := MinValue to MaxValue do Proc(GetEnumName(EnumType, I));
          end;
        end;
         
        procedure TMySetTypeProperty.SetValue(const Value: string);
        var
          I: Integer;
        begin
          I := GetEnumValue(GetTypeInfo, Value);
          with GetTypeData(GetPropType)^ do
            if (I < MinValue) or (I > MaxValue) then
              raise Exception.Create('');
          SetOrdValue(I);
        end;
      Но в рантайм режиме пройдется работать с свойством TMySetTypeXXXX(MyComponent.MyOptions)
        два вопроса:

        1. delphi 2010 не находит DesignIntf и DesignEditors. как быть?
        2. где прописан тип TEnumProperty?

        спасибо
        Сообщение отредактировано: SkAndriy -
          Код компонента и код редактора свойств нужно разделить на два модуля. А в инсталяционный пакет добавить DesignIde
            офтоп:
            SkAndriy, редактировать сообщение не есть гуд. ибо уведомление подписчикам на тему не приходит.
              спасибо. замечание учтено.
                при компилировании в функции:

                ExpandedWrap disabled
                  function TSetTypeProperty.GetTypeInfo: PTypeInfo;
                  var
                    Obj: TPersistent;
                  begin
                    Obj := GetComponent(0);
                    if Assigned(Obj) and (Obj is TEphemeridae) then
                      with TEphemeridae(Obj) do
                      begin
                        case CelestialObject of
                          oPlanets : Result := TypeInfo(TSetTypePlanets);
                          oAsteroids : Result := TypeInfo(TSetTypeAsteroids);
                         // oStars : Result := TypeInfo(TMySetTypeStars);
                         // oComets : Result := TypeInfo(TMySetTypeComets);
                        end;
                      end
                    else
                      Result := GetPropType;
                  end;


                выдается такое сообщение:

                [DCC Warning] MyComponent.pas(79): W1035 Return value of function 'TSetTypeProperty.GetTypeInfo' might be undefined

                как это можно исправить?

                спасибо
                  функция пдправил так:

                  ExpandedWrap disabled
                    function TSetTypeProperty.GetTypeInfo: PTypeInfo;
                    var
                      Obj: TPersistent;
                    begin
                      Obj := GetComponent(0);
                      if Assigned(Obj) and (Obj is TEphemeridae) then
                        with TEphemeridae(Obj) do
                        begin
                          case CelestialObject of
                            oPlanets : Result := TypeInfo(TSetTypePlanets);
                            oAsteroids : Result := TypeInfo(TSetTypeAsteroids);
                            oStars : Result := TypeInfo(TSetTypeStars);
                            oComets : Result := TypeInfo(TSetTypeComets);
                                 else Result := TypeInfo(TSetTypePlanets);
                          end;
                        end
                      else
                        Result := GetPropType;
                    end;


                  компонент компилируется и инсталируется.
                  но когда я кладу его на форму нового проекта и запускаю на компилирование, то получаю ошибку:

                  при компилировании проекта с этим тестируемым компонентом выдается ошибка: [DCC Fatal Error] Unit1.pas(7): F1026 File not found: 'DesignEditors.dcu',
                  у меня проект на делфи 2010 - как найти или включить DesignEditors.dcu.
                  В секцию Requires компонента я включил и скомпилировал уже ранее designide.dcp
                  Проблема остается.

                  В делфи статьях есть такой ответ:

                  Using the Delphi DesignIntf and DesignEditors Tools
                  If you are creating a C++ package that contains a Delphi unit that uses the DesignIntf and DesignEditors tools, you must choose Project > Options > Delphi Compiler > Other Options. In Use these packages when compiling, add DesignIDE in the combo box.

                  Но в Делфи 2010 Project > Options > Delphi Compiler > Other Options - отсуствет такой раздел, как и "Use these packages when compiling" или где их найти и установить нужные опции.

                  если можно подробный ответ как можно исправить это.

                  спасибо
                    В секцию Requires компонента я включил и скомпилировал уже ранее designide.dcp; прописал путь к папке ToolsAPI, где находятся искомые файлы (DesignIntf.pas и DesignEditors.pas); перекомпилировал и файлы DesignIntf.dcu и DesignEditors.dcu появились в папке ToolsAPI, но теперь при компилировании нового проекта с моим компонентом выдается ошибка:

                    [DCC Fatal Error] ToolsAPI.pas(17): F1026 File not found: 'DockForm.dcu'

                    что еще надо внести в секцию Requires, чтобы скомпилировать все модули в папке ToolsAPI?

                    Спасибо.
                      Цитата SkAndriy @
                      если можно подробный ответ как можно исправить это.
                      Это легко исправляется способом который описал DimaBr
                        1. в инсталяционный пакет уже добавил DesignIde

                        2. модули разделил, модуль редактора свойств выглядит так:

                        ExpandedWrap disabled
                          unit PropertyEditor;
                           
                          interface
                           
                          uses
                            Windows, Messages, SysUtils, Variants, Classes, DesignIntf, DesignEditors, TypInfo;
                           
                          type
                            TMySetTypeProperty = class(TEnumProperty)
                            private
                              function GetTypeInfo: PTypeInfo;
                            public
                              function GetValue: string; override;
                              procedure GetValues(Proc: TGetStrProc); override;
                              procedure SetValue(const Value: string); override;
                            end;
                           
                            procedure Register;
                           
                          implementation
                           
                          uses UnitMyComponent;
                           
                          function TMySetTypeProperty.GetTypeInfo: PTypeInfo;
                          var
                            Obj: TPersistent;
                          begin
                            Obj := GetComponent(0);
                            if Assigned(Obj) and (Obj is TMyComponent) then
                              with TMyComponent(Obj) do
                              begin
                                case MyEnumProp of
                                  eFirst:  Result := TypeInfo(TMySetTypeFirst);
                                  eSecond: Result := TypeInfo(TMySetTypeSecond);
                                  eThird:  Result := TypeInfo(TMySetTypeThird);
                                end;    
                              end
                            else
                              Result := GetPropType;
                          end;
                           
                          function TMySetTypeProperty.GetValue: string;
                          var
                            L: Longint;
                          begin
                            L := GetOrdValue;
                            with GetTypeData(GetTypeInfo)^ do
                              if (L < MinValue) or (L > MaxValue) then L := MaxValue;
                            Result := GetEnumName(GetTypeInfo, L);
                          end;
                           
                          procedure TMySetTypeProperty.GetValues(Proc: TGetStrProc);
                          var
                            I: Integer;
                            EnumType: PTypeInfo;
                          begin
                            EnumType := GetTypeInfo;
                            with GetTypeData(EnumType)^ do
                            begin
                              for I := MinValue to MaxValue do Proc(GetEnumName(EnumType, I));
                            end;
                          end;
                           
                          procedure TMySetTypeProperty.SetValue(const Value: string);
                          var
                            I: Integer;
                          begin
                            I := GetEnumValue(GetTypeInfo, Value);
                            with GetTypeData(GetPropType)^ do
                              if (I < MinValue) or (I > MaxValue) then
                                raise Exception.Create('');
                            SetOrdValue(I);
                          end;
                           
                          procedure Register;
                          begin
                            RegisterPropertyEditor(TypeInfo(Integer), TMyComponent, 'MyOptions', TMySetTypeProperty)
                          end;
                           
                          end.


                        Результат прежний, при компилировании нового проекта с этим компонентом все время ошибки с разными dcu

                        спасибо.
                        Сообщение отредактировано: SkAndriy -
                          ну не знаю. только что набросал проектПрикреплённый файлddddd.rar (8,35 Кбайт, скачиваний: 209) и все отработало как часики.
                            Спасибо все компилируется, а что действительно другого пути чем в райнтайм обращаться к свойствам только так: TMySetTypeXXXX(MyComponent.MyOptions) или можно как-то иначе, прописав в самом компоненте. спасибо за помощь.
                              Без явного приведения типа ты с им работать не сможешь. или же работай с цифровым типом. разница от этого не поменяется.
                                например,

                                private
                                FTypeFirst : TMySetTypeFirst;

                                строка в тестовом приложении :

                                в процедуре FormCreate, например,

                                if FTypeFirst = TMySetTypeFirst(MyComponent1.MyOptions).poSecond1 then
                                Caption := 'It is Second1';

                                не компилирется, а выскакивает ошибка.

                                Почему?

                                Спасибо.
                                  ExpandedWrap disabled
                                    if FTypeFirst = TMySetTypeFirst(MyComponent1.MyOptions) then
                                    Caption := 'It is Second1';
                                    Мне необходимо во-первых установить одно из значений множества TMyEnumType затем выбирая из множества TMySetTypeFirst или TMySetTypeSecond или TMySetTypeThird получать свойства соотвествующие этим значениям, например,

                                    TMyEnumType = eThird;
                                    MyOptions = poSecond3;

                                    например, в компонент добавлены несколько изменяющихся свойств (полей)
                                    Property1 = "aaaaaa"
                                    Property2 = "bbbbbb"
                                    Property3 = "cccccc"

                                    далее я изменяю

                                    TMyEnumType = eFirs;
                                    MyOptions = poThird1;

                                    и свойства должны также измениться на другие значения (они вычисляюся ранее):
                                    Property1 = "dddddd"
                                    Property2 = "eeeeee"
                                    Property3 = "xxxxxx"

                                    как этого можно достичь?

                                    годится ли вот такая конструкция?
                                    вот такая конструкция сложная, но работает, а есть более простой способ?

                                    procedure TForm3.FormCreate(Sender: TObject);
                                    begin
                                    FTypeFirst := TMySetTypeFirst(MyComponent1.MyOptions);
                                    if Integer(FTypeFirst) = 1 then
                                    Caption := 'It is Second1';
                                    end;

                                    Спасибо.
                                      ExpandedWrap disabled
                                        if MyComponent1.MyOptions = 1 then
                                          Caption := 'It is Second1';

                                      у меня такое чувство что ты куда то идешь не туда куда нужно, и что самое странное что я тебе в этом помогаю.

                                      Опиши полную ситуацию что ты этим всем хотиш сделать. Может тебе будет проще разделить компоненты на части. первый главный, а второй с нужными свойствами (и логикой под их). и ты просто подключаешь их по очереди к главному. Одним словом опиши ситуину. (пс. я спать если что застра отвечу)
                                        Задача:

                                        Есть главное множество (A,B,C,D,E), каждое значение его имеет свое собственное подмножество (неодинаковые подмножества)

                                        A = (a, b, c, d, e, f)
                                        B = (q, w, g, r, y)
                                        и так далее
                                        E = (l, k, z, x)

                                        Выбирая из главного множества значение, например "B" или "E", оно определит в свойстве MyOptions подмножество выбора, например, B = (q, w, g, r, y) или E = (l, k, z, x). А каждому значению этого подмножества, например (q, w, g, r, y) или (l, k, z, x), соответствуют значения свойств, например свойство1, свойство2 и свойство3. Свойства "свойство1, свойство2 и свойство3" только для чтения и это должны быть расчетные величины в самом компоненте, значения которых зависят от измения свойства "Дата" (число, месяц, год) и соответствуют одному из значений подмножества, например (q, w, g, r, y) или (l, k, z, x), главного множества B или E.

                                        ==============================================================================
                                        В программе, использующей этот компонент будут использоваться элементы :

                                        1. свойство дающее значение главного множества, например B или E или A
                                        2. свойство дающее значение подмножеств, например (q, w, g, r, y) или (l, k, z, x)
                                        3. расчетная дата (число, месяц, год) для свойств (свойство1, свойство2 и свойство3)
                                        4. расчетные свойства (свойство1, свойство2 и свойство3) для конкретного значения(например, "q") подмножества (например, подмножества "B")
                                        ================================================================================

                                        Например,

                                        1. выбрали в главном множестве = E
                                        2. в подмножестве E = z
                                        3. свойство1 = 5, свойство2 =10 и свойство3=4

                                        1. выбрали в главном множестве = E
                                        2. в подмножестве E = l
                                        3. свойство1 = 0, свойство2 =9 и свойство3=2

                                        1. выбрали в главном множестве = A
                                        2. в подмножестве A = d
                                        3. свойство1 = 15, свойство2 =7 и свойство3=3

                                        1. выбрали в главном множестве = B
                                        2. в подмножестве E = y
                                        3. свойство1 = 1, свойство2 =98 и свойство3=43

                                        и так далее.

                                        очень желательно не разбивать компонент на части. первая часть уже получилась вроде, теперь как управлять ею задача?
                                        а если разбивать, то как соединить или подключать каждый из компонентов, соответствующий разным множествам или подмножествам?
                                        мне кажется, что один компонет все же проще и логичней.

                                        спасибо за помощь. это мой первый компонент, но срочно нужен для своей научной работы.
                                        Сообщение отредактировано: SkAndriy -
                                          1. Сделайте ОЧЕНЬ главное множество a..x: TMain = (a, b, c, d, e, f, .... l, k, z, x)
                                          2. Выделите из него подмножества (a..f)(q..y): TA = a..f; TE=l..x;
                                          3. Присвойте каждому элементу ОЧЕНЬ главного множества число: const Value: array[TMain] of integer = (1,2,3,4,5....);
                                          4. Немного видоизменив редактор свойств для MyOptions получите требуемый результат, где возвращаемый тип будет TMain
                                            спасибо за ответ, как изменить? это мой первый компонент. нужен исключительно для своей научной работы.
                                              Я же говорю, сначала отработайте всё в RunTime, а потом поговорим про дизайнер. Создавайте компонент динамически, что бы поупражняться с ним в работе.
                                              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                              0 пользователей:


                                              Рейтинг@Mail.ru
                                              [ Script execution time: 0,0620 ]   [ 18 queries used ]   [ Generated: 1.05.24, 21:09 GMT ]