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

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

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

    Создаю компонент со свойствами-множествами (unit MyComponent) и редактором свойств (unit PropertyEditor) по такой схеме:

    ExpandedWrap disabled
      unit MyComponent;
       
      interface
       
      uses
        SysUtils, Types, Classes;
       
      type
        TMyDataRecord = record
          MyData1 : Double;
          MyData2 : Double2;
        end;
       
        TMyEnumType = (eFirst, eSecond, eThird);
        TMySetTypeFirst = (poFirst1, poSecond1, poThird1);
        TMySetTypeSecond = (poFirst2, poSecond2, poThird2);
        TMySetTypeThird = (poFirst3, poSecond3, poThird3);
       
      TMyObject = class (TPersistent)
        private
          { Private declarations }
          FProperty1: Double;
          FProperty2: Double;
          FProperty3: Double;
          function GetDataElement(Index : Integer): Double;
          // procedure SetDataElement(Index : Integer; Value : Double);
        protected
          { Protected declarations }
        public
          { Public declarations }
        procedure Assign (Source: TPersistent);
        published
          { Published declarations }
          property Property1: Double index 0 read GetDataElement write FProperty1;
          property Property2: Double index 1 read GetDataElement write FProperty2;
          property Property3: Double index 2 read GetDataElement write FProperty3;
        end;
       
      type
        TMyComponent = class(TButton)
        private
          { Private declarations }
          FMyObject: TMyObject;
          FMyEnum: TMyEnumType;
          FMyOptions: Integer;
          procedure SetMyObject(Value: TMyObject);
        protected
          { Protected declarations }
        public
          { Public declarations }
          constructor Create(AOwner: TComponent); override;
          destructor Destroy; override;
          function calculatesomedata : TMyDataRecord;
        published
          { Published declarations }
          property MyObject : TMyObject read FMyObject write SetMyObject;
          property MyEnumProp : TMyEnumType read FMyEnum write FMyEnum;
          property MyOptions : Integer read FMyOptions write FMyOptions;
        end;
       
        procedure Register;
       
      implementation
       
      procedure TMyComponent.SetMyObject(Value: TMyObject);
      begin
        if Assigned (Value) then FMyObject.Assign(Value);
      end;
       
      constructor TMyComponent.Create (AOwner; TComponent);
      begin
        inherited Create (AOwner);
        FMyObject := TMyObject.Create;
      end;
       
      destructor TMyComponent.Destroy;
      begin
        FMyObject.Free;
        inherited Destroy;
      end;
       
      function TMyComponent.CalculateSomeData : TMyDataRecord;
      begin
        if если выбрано одно из подмноджеств TMySetTypeFirst или TMySetTypeSecond или TMySetTypeThird в редакторе свойств then
          Result := здесь расчет и присваивание некого результата от TMyDataRecord в зависимости от значения FOptions;
      end;
       
      procedure TMyObject.Assign (Source: TPersistent);
      begin
      if Source is TMyObject then
      begin
        FProperty1 := TmyObject(Source).Property1;
        FProperty2 := TmyObject(Source).Property2;
        FProperty3 := TmyObject(Source).Property3;
        inherited Assign (Source);
      end;
       
      function TMyObject.GetDataElement(Index : Integer): Double;
      begin
        Result := 0;
        with TMyComponent(self) do
          case Index of
             0 : Result := CalculateSomeData.MyData1;
             1 : Result := CalculateSomeData.MyData2;
             2 : Result := CalculateSomeData.MyData3;
          end;
      end;
       
      end.
       
      ============================================================
       
      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.


    Вопрос:
    Почему компонент не реагирует на переключение множеств в редакторе свойств (GetTypeInfo)?
    Почему результаты вычислений функции CalculateSomeData не присваиваются полям FProperty1, FProperty2, FProperty3 моего компонента MyComponent?
    Подскажите правильно ли я составил код компонента. Где ощибки в коде и как их исправить?

    Спасибо.
    Сообщение отредактировано: SkAndriy -
      Потому что нужно читать внимательно книги о том что ты делаешь (в данном случае OOП)

      вот твое свойство которое ты меняешь
      ExpandedWrap disabled
        property MyOptions : Integer read FMyOptions write FMyOptions;
      А кто событие будет вызывать? откуда компонент будет знать что нужно делать?
        спасибо за ответ, читаю и пробую разобраться.
        и все же как поправить код, чтобы он заработал?
        спасибо
          Цитата SkAndriy @
          и все же как поправить код, чтобы он заработал?

          сохранять не в переменную а через процедуру. то есть сделать событие )
            так?

            property MyOptions : Integer read FMyOptions write SetMyOptions;

            procedure TMyComponent.SetMyOptions(Value : Integer);
            begin
            if FMyOptions <> Value then
            FMyOptions := Value;
            end;

            И все?
            Спасибо
            Сообщение отредактировано: SkAndriy -
              Сделал как описал выше - ничего не работает. Что опять не так в прведенных кодах?

              Спасибо.
                блин. я не туда посмотрел. посути тебе событие сейчас не нужно

                ошибка твоя в куске
                ExpandedWrap disabled
                     with TMyComponent(self) do
                       case Index of
                          0 : Result := CalculateSomeData.MyData1;
                          1 : Result := CalculateSomeData.MyData2;
                          2 : Result := CalculateSomeData.MyData3;
                       end;
                я просто не сразу заметил что ты разделил код на два объекта.
                что бы увидеть в чем тут ошибка замени строчку
                ExpandedWrap disabled
                  with TMyComponent(self) do

                на равноправную ей, но с проверкой на на тип
                ExpandedWrap disabled
                  with self as TMyComponent do


                Добавлено
                Цитата ViktorXP @
                блин. я не туда посмотрел. посути тебе событие сейчас не нужно

                Хотя смотря как ты решишь выйти из ситауции.
                  Спасибо, я применил и компилятор выдал несовместимость тиов, а как тогда передать эти параметры в данную функцию?
                    либо тыкай овнера в MyObject (или замени класс на тот у которого уже есть овнер) или по событию передавай туда данные
                      прописать еще одно свойство в класс TMyObject?

                      TMyObject = class (TPersistent)
                      private
                      FMyOwner : TMyComponent;

                      property MyOwner : TMyComponent read FMyOwner write FMyOwner;
                      end;

                      или как-то иначе, можно простой пример? событие для меня еще очень сложно написать.
                        НО если прописать Owner выше его класса, то это ошибка компилятора, если расположить весь класс TMyObject ниже класса компонента (TMyComponent), то тогда компилятор выдает что не видит класс моего объекта. Замкнутый круг просто. Есть реальное решение как выйти из данной ситуации. Можно небольшой пример. спасибо.
                          для этого есть возможность в делфи
                          ExpandedWrap disabled
                            type
                              TTest2 = class;
                             
                              TTest1 = class(TObject)
                                 Test2: TTest2;
                              end;
                             
                              TTest2 = class(TObject)
                                  Test1: TTest1;
                              end;
                          и все всех видят
                            при приведенной выше конструкции выдается множество ошибок несоотвествия типов, например constructor Create(AOwner : TComponent); override;
                            и destructor. А как можно еще передать с помощью события? Можно небольшой пример. спасибо
                              Цитата SkAndriy @
                              при приведенной выше конструкции выдается множество ошибок несоотвествия типов, например constructor Create(AOwner : TComponent); override;

                              Ну наверное потому что ты предка взял без виртуального конструктор
                              ExpandedWrap disabled
                                 constructor Create(AOwner : TComponent);
                              и пытаешься его перегрузить.
                                В моеже показать как с помощью события, без модификаци классов, оставляя код как есть реализовать данную задачу? спасибо
                                  нее. ты уже копай в одну сторону. это не сложно. ты дошол до виртуальный методов. примени то что учил на практике (я надеюсь что ты хоть мельком читал про ооп)
                                    а может классы разделить в разные модули и подключить друг к другу? это будет работать в данном примере. спасибо
                                      извините, я не программист, а компонент нужен для собственной научной работы. поэтому я и попросил помощи здесь на форум, чтобы опытные программисты поправили приведеднный код выше. я медик, а не программист. разбираться конечно буду, но это по опыту займет много времени, а компонент мне нужен сейчас. спасибо за помощь.
                                        Цитата SkAndriy @
                                        а может классы разделить в разные модули и подключить друг к другу? это будет работать в данном примере. спасибо

                                        если ты имеешь ввиду работу вообще то да. А вот скомпилирует ли это делфя зависит от того как ты напишешь.

                                        Коль ты не программист то даю подсказку:
                                        перегрузить ты сможешь только виртуальный метод и оба они должны быть одинаково объявлены. в TObject не то что параметров нет в конструкторе. он даже объявлен не виртуальным. Посему создавай свой виртуальный (или простой) конструктор
                                          в отдельных модулях пробовал - не работает. спасибо за помощь
                                            Вы могли бы мне дать ссылку на реальный примерв интернете или на модуль готового компонента как решить мою задачу. пересмотрел наверное море информации, но только запутался в этом. спасибо.
                                              Да тут нет ничего сложного.



                                              ExpandedWrap disabled
                                                  TMyObject = class (TPersistent)
                                                  private
                                                    //переменная под главный объект
                                                    FOwner: TMyComponent;
                                                  public
                                                     // так как ни в TPersistent ни в его предка TObject нет конструктора с параметром TMyComponent то нам нужно создать свой конструктор.
                                                     //и я на всякий случай его сделал виртуальным
                                                     constructor Create(AOwner: TMyComponent); virtual;
                                                     //создал свойство
                                                     property Owner: TMyComponent read FOwner;
                                                  end;
                                                 
                                                constructor TMyObject.Create(AOwner: TMyComponent);
                                                begin
                                                   //inherited Create; // вызвать бессмысленно так как в TObject конструктор пуст. но в других случаях это необходимо делать.
                                                   FOwner := AOwner;
                                                end;
                                              А все остальное точно также как и раньше.
                                              пс. я ведь говорил - "ничего сложного"

                                              Добавлено
                                              Насчет литературы то рекомендую
                                              http://www.podgoretsky.com/ftp/Docs/Delphi/D5/
                                              пс. тут два pdf-фничка лежит. очень хорошая информация.
                                                Да, но я уже пробовал, если поставить TFOwner: TMyComponent; до объявления класса TMyComponent, то компилятор выдает ошибку или я ничего не понимаю. А если поставить впереди TMyComponent = class, то снова масса ошибок. Спасибо за ответ
                                                  Я исправил вроде как мы дискутировали, компонент компилируется,но свойств TMyObject вообще нет. В общем снова не работает. Что в этот раз не так в этом коде. Спасибо

                                                  Прикреплённый файлПрикреплённый файлMyComponent.zip (1,66 Кбайт, скачиваний: 162)
                                                    А подробнее что за ошибки. Хотя подозреваю что AV вываливается. Так как ты вообще закомментировал строку создания объекта. Только вот интересно зачем? ты ведь не думаешь что объект сам собой создастся.
                                                      я приложил файлы pas. У меня делфи 2010. Ошибка - компонент не работает - даже свойств нового объекта нет.
                                                      Там где закомментировал и ошибка при компилировании компонента.
                                                      Сообщение отредактировано: SkAndriy -
                                                        Цитата SkAndriy @
                                                        я приложил файлы pas.

                                                        Я видел. ибо откуда я сделал вывод от строке конструирования
                                                        Цитата SkAndriy @
                                                        У меня делфи 2010.

                                                        У меня тоже 14 версия. но это сути дела не меняет. Никогда не было авто создания объекта.
                                                        Цитата SkAndriy @
                                                        Ошибка - компонент не работает - даже свойств нового объекта нет.

                                                        А откуда они возьмутся если объект nil

                                                        Добавлено
                                                        Цитата SkAndriy @
                                                        Там где закомментировал и ошибка при компилировании компонента.

                                                        А тебя не настораживает что в конструкторе есть параметр. а ты пытаешься его вызвать без параметра. О чем и предупреждает тебя компилятор (посмотри внимательно на текст ошибки).
                                                        Сообщение отредактировано: ViktorXP -
                                                          Этот вариант компилируется, поля есть нового объекта, но они почему-то не заполнются случайными значениями от функции function TMyComponent.CalculateSomeData : TMyDataRecord; Почему? Что опять не так? И еще компилятор при компилировании компонета выдает сообщение :
                                                          [DCC Warning] Unit2.pas(34): W1010 Method 'Assign' hides virtual method of base type 'TPersistent'
                                                          Как это исправить? Спасибо

                                                          Прикреплённый файлПрикреплённый файлMyComponent.zip (1,72 Кбайт, скачиваний: 137)
                                                            Цитата SkAndriy @
                                                            [DCC Warning] Unit2.pas(34): W1010 Method 'Assign' hides virtual method of base type 'TPersistent'
                                                            Это компилятор предупреждает что в TPersistent есть виртуальный метод Assign а ты его перекрываешь своей одноименной процедурой.
                                                            Цитата SkAndriy @
                                                            Как это исправить?

                                                            добавить override;

                                                            Цитата SkAndriy @
                                                            Что опять не так?

                                                            Все те же старые ошибки
                                                            ExpandedWrap disabled
                                                              with TMyComponent(self) do
                                                              Спасибо за учебу и помощь.

                                                              1. Справка делфи рекомендует прописывать так:

                                                              procedure Assign(Source: TPersistent); reintroduce;

                                                              https://forums.embarcadero.com/thread.jspa?threadID=35796&tstart=0

                                                              2. строку "with TMyComponent(self) do" исправил.

                                                              Спасибо еще раз.
                                                              Сообщение отредактировано: SkAndriy -
                                                                reintroduce это заглушка на то что бы компилятор не ругался на перекрытие одноименных процедур функций.
                                                                он применяется к GetOwner для того что бы можно было объявить свою функцию с овнером (ибо не интересно постоянно овнера приводить к нужному типу. проще что бы функция возвращала нужный тип сразу).
                                                                Assign есть в базовом классе. при этом он является виртуальным. и это не с проста.
                                                                ты допустил логическую ошибку не перегрузив его. а потом еще сказал компилятору что ты так и хотишь.
                                                                но логику ты прибил.
                                                                Так как теперь AssingTo вызовет старый обработчик к которому твой не привязан и он отработает в пустую.

                                                                пс. посему reintroduce тут не приемлем.

                                                                Добавлено
                                                                С таким успехом ты мог оставить предка TObject и не парится с TPersistent
                                                                  Цитата SkAndriy @
                                                                  извините, я не программист, а компонент нужен для собственной научной работы... разбираться конечно буду, но это по опыту займет много времени, а компонент мне нужен сейчас

                                                                  Почему тогда именно компонент, да еще и с редактором свойств-множеств ? Если пишешь для себя, а не для "дяди", то проще не возится с созданием полноценного компонента с заданием св-в в инспекторе, а создавать объект и задавать его св-ва динамически в FormCreate
                                                                    доброе утро.

                                                                    для leo

                                                                    потому что задача требует однотипных решений для нескольких приложений и так с моей точки зрения рациональнее. надеюсь, что ответ удовлетворит Вас. спасибо.

                                                                    для ViktorXP

                                                                    1.
                                                                    Понял, спасибо и исправил в procedure Assign(Source: TPersistent); override;

                                                                    2.
                                                                    Так лучше использовать метод Assign или все же AssignTo?
                                                                    Если AssignTo, то что надо исправить в процедуре, кроме самого названия метода:

                                                                    ExpandedWrap disabled
                                                                      procedure TMyObject.Assign(Source: TPersistent);
                                                                      begin
                                                                        if Source is TMyObject then
                                                                        begin
                                                                          FProperty1 := TmyObject(Source).Property1;
                                                                          FProperty2 := TmyObject(Source).Property2;
                                                                          FProperty3 := TmyObject(Source).Property3;
                                                                        end;
                                                                        inherited Assign (Source);
                                                                      end;


                                                                    Очень рад знакомству с настоящим мастером, если это для Вас было не слишком обременительным.
                                                                    Еще раз спасибо за терпение, учебу и помощь.
                                                                    Сообщение отредактировано: SkAndriy -
                                                                      различия между Assign и AssignTo в направлении "переноса" данных

                                                                      Приемник.Assing(Источник);
                                                                      Источник.AssingTo(Приемник);

                                                                      Цитата SkAndriy @
                                                                      Очень рад знакомству с настоящим мастером

                                                                      Самое сложное в программировании это понять логику всего этого. А все остальное это опыт.

                                                                      Добавлено
                                                                      Цитата SkAndriy @
                                                                      Так лучше использовать метод Assign или все же AssignTo?

                                                                      Будет достаточно того что ты наделил его override
                                                                        Как видно из предыдущего сообщения я использовал метод Assign.
                                                                        Я прописал его исходя из общего кода правильно?
                                                                        Спасибо
                                                                          сам метод написан правильно.
                                                                            Спасибо
                                                                              Попутно возник еще вопрос - как при изменении параметра-свойства MyOptions в классе TMyComponent с помощью Редактора Свойств каждый раз обнулить (т.е. устанавливать их к 0) значения свойств Property1, Property2, Property3 класса TMyObject перед занесением в них предвычисленных величин. Пробовал дописать к этим свойствам default или store ничего не происходит. Может есть какой-то специальный синтаксис? Мне необходимо обнулять каждый раз при обновлении MyOptions, так что просто прописать все свойства в конструкторе к нулю не проходит. Спасибо.
                                                                              Сообщение отредактировано: SkAndriy -
                                                                                а тут уже событие нужно.

                                                                                Добавлено
                                                                                вот то что ты тогда писал + обнуление параметров.
                                                                                  Событие в классе в классе TMyComponent?

                                                                                  Так правильно:

                                                                                  ExpandedWrap disabled
                                                                                    TMyComponent = class(TComponent)
                                                                                     
                                                                                    private
                                                                                      FOnChange: TNotifyEvent;
                                                                                     
                                                                                    protected;
                                                                                      property OnChange : TNotifyEvent read FOnChange write FOnChange;
                                                                                    ............
                                                                                    end;
                                                                                     
                                                                                    implementation
                                                                                     
                                                                                    procedure TMyComponent.OnChange;
                                                                                    begin
                                                                                    if Assigned (FOnChange) then FOnChange(Self);
                                                                                    end;


                                                                                  А какие и где писать параметры, чтобы realtime я мог получать событие на изменение в компоненте MyOptions?

                                                                                  Или можно небольшой пример, мне так проще понять задачу в целом.
                                                                                  Спасибо
                                                                                  Сообщение отредактировано: SkAndriy -
                                                                                    Цитата SkAndriy @
                                                                                    Как видно из предыдущего сообщения я использовал метод Assign.
                                                                                    Я прописал его исходя из общего кода правильно?

                                                                                    Нет, не правильно, т.к. если TMyObject является прямым наследником TPersistent, то inherited Assign вызовет AssignTo, который в свою очередь вызовет исключение EConvertError. Поэтому для прямых наследников нужно вызывать inherited только в части else:
                                                                                    ExpandedWrap disabled
                                                                                      procedure TMyObject.Assign(Source: TPersistent);
                                                                                      begin
                                                                                       if Source is TMyObject then
                                                                                       begin
                                                                                         ...
                                                                                       end
                                                                                       else //<---- !!!
                                                                                         inherited Assign (Source);
                                                                                      end;
                                                                                      Цитата SkAndriy @
                                                                                      Так правильно:

                                                                                      Я не это имел ввиду
                                                                                      сообщение под номером пять + в нем же и меняешь значения своего объекта.

                                                                                      Цитата leo @
                                                                                      Нет, не правильно, т.к. если TMyObject является прямым наследником TPersistent, то inherited Assign вызовет AssignTo, который в свою очередь вызовет исключение EConvertError. Поэтому для прямых наследников нужно вызывать inherited только в части else

                                                                                      Это да. я что то на это не обратил внимание.
                                                                                        Т.е. в коде просто обнулить все свойства (Property1, Property2, Property3) класса:

                                                                                        property MyOptions : Integer read FMyOptions write SetMyOptions;

                                                                                        procedure TMyComponent.SetMyOptions(Value : Integer);
                                                                                        begin
                                                                                        Property1 := 0;
                                                                                        Property2 := 0;
                                                                                        Property3 := 0;
                                                                                        if FMyOptions <> Value then
                                                                                        FMyOptions := Value;
                                                                                        end;

                                                                                        Так?

                                                                                        И раз уж Вы затронули вопрос о событиях помогите мне на реальном примере создать событие, которое происходит, когда изменяется свойство MyEnumProp или MyOptions.

                                                                                        ExpandedWrap disabled
                                                                                          TMyComponent = class(TComponent)
                                                                                           
                                                                                          private
                                                                                            FOnChange: TNotifyEvent;
                                                                                           
                                                                                          protected;
                                                                                            property OnChange : TNotifyEvent read FOnChange write FOnChange;
                                                                                          ............
                                                                                          end;
                                                                                           
                                                                                          implementation
                                                                                           
                                                                                          procedure TMyComponent.OnChange;
                                                                                          begin
                                                                                          if Assigned (FOnChange) then FOnChange(Self);
                                                                                          end;


                                                                                        Как привести это код к нужному событию?

                                                                                        Спасибо.
                                                                                        Сообщение отредактировано: SkAndriy -
                                                                                          Цитата SkAndriy @
                                                                                          ExpandedWrap disabled
                                                                                            procedure TMyComponent.OnChange;
                                                                                          Ты не сможеш найменовать метод такимже именем как и свойство. Если взять негласное правило то имя ему нарекаем DoChange
                                                                                          пс. и не забудь его объявить в классе.
                                                                                          а дальше немного дописываешь код
                                                                                          ExpandedWrap disabled
                                                                                            procedure TMyComponent.SetMyOptions(Value : Integer);
                                                                                            begin
                                                                                              if FMyOptions = Value then Exit;
                                                                                              FMyOptions := Value;
                                                                                              Property1 := 0;
                                                                                              Property2 := 0;
                                                                                              Property3 := 0;
                                                                                              DoChange;
                                                                                            end;
                                                                                            Немного подправил код:

                                                                                            ExpandedWrap disabled
                                                                                              procedure TMyComponent.SetMyOptions(Value : Integer);
                                                                                              begin
                                                                                                if FMyOptions = Value then Exit;
                                                                                                FMyOptions := Value;
                                                                                                FMyObject.Property1 := 0;
                                                                                                FMyObject.Property2 := 0;
                                                                                                FMyObject.Property3 := 0;
                                                                                                OnDoChange;
                                                                                              end;


                                                                                            теперь верно? а то без "FMyObject." к свойствам компилятор выдавал ошибку или как-то иначе необходимо.
                                                                                            Но есть одно но - не все поля почемуто обнуляются. Что в этом коде еще не соответствует?


                                                                                            Так верно?

                                                                                            ExpandedWrap disabled
                                                                                              TMyComponent = class(TComponent)
                                                                                               
                                                                                              TDoChangeEvent = procedure(Sender : Tobject; Index : Integer) of Object;
                                                                                               
                                                                                              private
                                                                                                FOnDoChange: TDoChangeEvent;
                                                                                               
                                                                                              protected;
                                                                                                property DoChange : TDoChangeEvent read FOnDoChange write FOnDoChange;
                                                                                              ............
                                                                                              end;
                                                                                               
                                                                                              implementation
                                                                                               
                                                                                              procedure TMyComponent.OnDoChange;
                                                                                              begin
                                                                                              if Assigned (FOnDoChange) then FOnDoChange(Self);
                                                                                              end;
                                                                                               
                                                                                              procedure TMyComponent.SetMyOptions(Value : Integer);
                                                                                              begin
                                                                                                if FMyOptions = Value then Exit;
                                                                                                FMyOptions := Value;
                                                                                                Property1 := 0;
                                                                                                Property2 := 0;
                                                                                                Property3 := 0;
                                                                                                OnDoChange(FMyOptions или Value);
                                                                                              end;


                                                                                            Можно ли обработать в событии в качестве параметра индекс значения FMyOptions, например OnDoChange(Sender : Tobject; Index : Integer);

                                                                                            Немного не понятен сам код SetMyOptions. Можно его пояснить?

                                                                                            И еще вопрос нужен ли в коде компонента код:

                                                                                            property MyEnumProp : TMyEnumType read FMyEnum write SetMyEnum;

                                                                                            ExpandedWrap disabled
                                                                                              procedure SetMyEnum(Value : TMyEnumType);
                                                                                              begin
                                                                                                if Assigned(Value) then ????????????????
                                                                                              end;


                                                                                            Спасибо
                                                                                            Сообщение отредактировано: SkAndriy -
                                                                                              Цитата SkAndriy @
                                                                                              Но есть одно но - не все поля почемуто обнуляются. Что в этом коде еще не соответствует?

                                                                                              если выходить из того что у тебя идет обявления
                                                                                              property Property3: Double index 2 read GetDataElement write FProperty3;
                                                                                              То результатом выхода данных является то что возвращает GetDataElement а что ты там пересчитываешь это уже только ты знаешь. посмотри логику. в большей степени вероятности там и кроется то что параметры не обнуляется.


                                                                                              Цитата SkAndriy @
                                                                                              property DoChange : TNotifyEvent read FOnDoChange write FOnDoChange;

                                                                                              И что ты этим написал? зачем ты переименовал свойство? разве я об этом писал? И где метод о котором я писал?

                                                                                              Цитата SkAndriy @
                                                                                              И еще вопрос нужен ли в коде компонента код:

                                                                                              Assigned(Value) применяется к ссылкам. ты не сможешь его применить к простому типу. У простых типов можно только сравнивать на значение.
                                                                                              например в этом случае можно написать

                                                                                              ExpandedWrap disabled
                                                                                                procedure SetMyEnum(Value : TMyEnumType);
                                                                                                begin
                                                                                                  if Value <> FMyEnum then
                                                                                              А вот применять ли подобную конструкцию или нет решать тебе. Но таким образом можно отсечь нежелательные реакции компонента на ввод данных которые и так внесены в свойство
                                                                                                Цитата ViktorXP @
                                                                                                И что ты этим написал? зачем ты переименовал свойство? разве я об этом писал? И где метод о котором я писал?


                                                                                                Я не понял этого. Можно конкретнее. Спасибо
                                                                                                  Если так, например для FMyOptions:

                                                                                                  ExpandedWrap disabled
                                                                                                    TMyComponent = class(TComponent)
                                                                                                     
                                                                                                    TDoChangeMyOptionsEvent = procedure(Sender : Tobject; Index : Integer) of Object;
                                                                                                     
                                                                                                    private
                                                                                                      FOnDoChangeMyOptions: TDoChangeMyOptionsEvent;
                                                                                                    publishin
                                                                                                      procedure OnDoChangeMyOptions(Sender : Tobject; Index : Integer);
                                                                                                     
                                                                                                    protected;
                                                                                                      property DoChangeMyOptions : TDoChangeMyOptionsEvent read FOnDoChangeMyOptions write FOnDoChangeMyOptions;
                                                                                                    ............
                                                                                                    end;
                                                                                                     
                                                                                                    implementation
                                                                                                     
                                                                                                    procedure TMyComponent.OnDoChangeMyOptions(Sender : Tobject; Index : Integer);
                                                                                                    begin
                                                                                                    if Assigned (FOnDoChangeMyOptions) then FOnDoChangeMyOptions(Self);
                                                                                                    end;
                                                                                                     
                                                                                                    procedure TMyComponent.SetMyOptions(Value : Integer);
                                                                                                    begin
                                                                                                      if FMyOptions = Value then Exit;
                                                                                                      FMyOptions := Value;
                                                                                                      Property1 := 0;
                                                                                                      Property2 := 0;
                                                                                                      Property3 := 0;
                                                                                                      OnDoChangeMyOptions(Self, Value);
                                                                                                    end;


                                                                                                  А для TMyEnumType по аналогии. Или как то иначе.

                                                                                                  будет верно?

                                                                                                  Спасибо
                                                                                                    уже лучше только расстановка негласных правил не верна. да и секции размещения перепутаны.

                                                                                                    Цитата SkAndriy @
                                                                                                    property DoChangeMyOptions : TDoChangeMyOptionsEvent read FOnDoChangeMyOptions write FOnDoChangeMyOptions;
                                                                                                    переименовываем обратно в On
                                                                                                    ExpandedWrap disabled
                                                                                                      property OnChangeMyOptions : TOnChangeMyOptionsEvent read FOnChangeMyOptions write FOnChangeMyOptions;


                                                                                                    тогда метод
                                                                                                    Цитата SkAndriy @
                                                                                                    ExpandedWrap disabled
                                                                                                      procedure OnDoChangeMyOptions(Sender : Tobject; Index : Integer)
                                                                                                    соответственно в Do
                                                                                                    ExpandedWrap disabled
                                                                                                      procedure DoChangeMyOptions(Sender : Tobject; Index : Integer);


                                                                                                    для метода DoChangeMyOptions не нужен первый параметр Sender. он его и так знает.
                                                                                                    посему обявление можно подправить как:
                                                                                                    ExpandedWrap disabled
                                                                                                      procedure DoChangeMyOptions(Index : Integer);


                                                                                                    а вот в теле метода у тебя ошибка
                                                                                                    ExpandedWrap disabled
                                                                                                      FOnDoChangeMyOptions(Self);

                                                                                                    сама переменная FOnDoChangeMyOptions является типом TDoChangeMyOptionsEvent у которого два параметра. так почему ты передаеш только одно?

                                                                                                    посему дописываем второй параметр (+ предшествующие изминения)

                                                                                                    ExpandedWrap disabled
                                                                                                      procedure TMyComponent.DoChangeMyOptions(Index : Integer);
                                                                                                      begin
                                                                                                        if Assigned (FDoChangeMyOptions) then FOnDoChangeMyOptions(Self, Index);
                                                                                                      end;




                                                                                                    также у тебя синтаксическая ошибка publishin. правильнее published

                                                                                                    а теперь о секциях размещения:
                                                                                                    само свойство ты спрятал в протекции. посему никто этого свойства не увидет кроме компонента который будет наследоватся от этого. А вот реакцию (DoChangeMyOptions) ты на оборот показал всем (даже дизайнеру свойств. хотя он этого и не оценит. так как он показывает только свойства)
                                                                                                    вывод: меняй местами.
                                                                                                    Сообщение отредактировано: ViktorXP -
                                                                                                      Вот код, но где-то ошибка, а где не могу понять.

                                                                                                      Спасибо
                                                                                                      Сообщение отредактировано: SkAndriy -
                                                                                                        Вот код, но где-то ошибка, а где не могу понять.

                                                                                                        Спасибо

                                                                                                        Прикреплённый файлПрикреплённый файлUnit2.zip (1,15 Кбайт, скачиваний: 132)
                                                                                                          Цитата
                                                                                                          ExpandedWrap disabled
                                                                                                            procedure Assign(Source: TPersistent); reintroduce;
                                                                                                          Но если мне не изменяет память то в 33 сообщении говорится об обратном

                                                                                                          насчет
                                                                                                          Цитата
                                                                                                          inherited Assign (Source);
                                                                                                          leo говорил в 41 посте.

                                                                                                          ну и ошибка логическая
                                                                                                          ExpandedWrap disabled
                                                                                                            procedure TMyComponent.SetMyOptions(Value : Integer);
                                                                                                            begin
                                                                                                              ....
                                                                                                              OnChangeMyOptions(Self, Value);
                                                                                                            end;
                                                                                                          Метод DoChangeMyOptions не просто так создавался. Тут вызвать нужно именно его. потому что если свойство не присвоить то OnChangeMyOptions будет равна nil.
                                                                                                          посему вызов nil(self, value) приведет к ошибке.
                                                                                                            Спасибо. все предыдущие ошибки исправил, процедуру события тоже. Все вызывается. А если просто применить стандартное событие OnChange на что в этом компоненте оно будет реагировать?
                                                                                                              И например, его прописать так:

                                                                                                              ExpandedWrap disabled
                                                                                                                property MyEnumProp: TMyEnumType read FMyEnum write SetMyEnum;
                                                                                                                 
                                                                                                                procedure TMyComponent.SetMyEnum(Value: TMyEnumType);
                                                                                                                begin
                                                                                                                  if(FMyEnum <> Value) then begin
                                                                                                                    FMyEnum:=Value;
                                                                                                                    Changed;
                                                                                                                  end;
                                                                                                                end;
                                                                                                                 
                                                                                                                procedure TMyComponent.Changed;
                                                                                                                begin
                                                                                                                  if Assigned(FOnChange) then FOnChange(Self);
                                                                                                                end;


                                                                                                              На какие изменения или какие события я в таком случае могу обработать в realtime?
                                                                                                              Спасибо
                                                                                                              Сообщение отредактировано: SkAndriy -
                                                                                                                А что ты имеешь ввиду под словом стандартное? OnChange это просто название. тип TNotifeEvent это просто тип. это все ни к чему не привязано. а реагировать оно будет так как ты это напишешь.

                                                                                                                пс. логика событий не зависит от имени.

                                                                                                                Добавлено
                                                                                                                Цитата SkAndriy @
                                                                                                                На какие изменения или какие события я в таком случае могу обработать в realtime?

                                                                                                                так ты ведь сам написал
                                                                                                                ExpandedWrap disabled
                                                                                                                    if(FMyEnum <> Value) then begin
                                                                                                                      FMyEnum:=Value;
                                                                                                                      Changed;
                                                                                                                    end;
                                                                                                                Ответь на вопрос. при каких ситуациях будет вызвана процедура Changed? и ты получишь ответ на свой вопрос.
                                                                                                                  Тогда по логикне вещей получается если прописать процедуру onChanged в процедуре procedure TMyComponent.SetMyEnum(Value: TMyEnumType) в realtime она будет реагировать на изменения свойства MyEnumProp класса TMyEnumType? А как она должна быть и в каих секциях прописана в самом TMyComponent = class(TComponent)? Спасибо
                                                                                                                    Цитата SkAndriy @
                                                                                                                    в каих секциях прописана
                                                                                                                    private - доступны переменные/методы/свойства только самому компоненту и ни кому более. (для свойств не используется)
                                                                                                                    protected - доступны переменные/методы/свойства только компоненту и его потомкам
                                                                                                                    public - достопны переменные/методы/свойства всем желающим.
                                                                                                                    published - тоже что и public + свойства видимы в инспекторе (используется исключительно для свойств. на все другое компилятор выдает предупреждение)

                                                                                                                    тебе определенно нужно книжку взять и почитать насчет ООП.
                                                                                                                      Я это знаю, я имел ввиду иное:

                                                                                                                      достаточно прописать просто в published OnChange, а если ему дописать параметры, например OnChange(Sender:Objects; Index:Integer)? тогда надо объявлять как в предыдущем рассматриваемом случае?

                                                                                                                      Спасибо
                                                                                                                        Цитата SkAndriy @
                                                                                                                        тогда надо объявлять как в предыдущем рассматриваемом случае?

                                                                                                                        Что ты под этом имеешь ввиду? если нужнен ли в таком случае метод Do..xxx.. то да. он нужен в любом случаи.
                                                                                                                          Спасибо. Вроде понял.
                                                                                                                          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                                                                          0 пользователей:


                                                                                                                          Рейтинг@Mail.ru
                                                                                                                          [ Script execution time: 0,1249 ]   [ 22 queries used ]   [ Generated: 1.05.24, 20:26 GMT ]