Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.224.37.68] |
|
Сообщ.
#1
,
|
|
|
Добрый день!
Создаю компонент со свойствами-множествами (unit MyComponent) и редактором свойств (unit PropertyEditor) по такой схеме: 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? Подскажите правильно ли я составил код компонента. Где ощибки в коде и как их исправить? Спасибо. |
Сообщ.
#2
,
|
|
|
Потому что нужно читать внимательно книги о том что ты делаешь (в данном случае OOП)
вот твое свойство которое ты меняешь property MyOptions : Integer read FMyOptions write FMyOptions; |
Сообщ.
#3
,
|
|
|
спасибо за ответ, читаю и пробую разобраться.
и все же как поправить код, чтобы он заработал? спасибо |
Сообщ.
#4
,
|
|
|
Цитата SkAndriy @ и все же как поправить код, чтобы он заработал? сохранять не в переменную а через процедуру. то есть сделать событие ) |
Сообщ.
#5
,
|
|
|
так?
property MyOptions : Integer read FMyOptions write SetMyOptions; procedure TMyComponent.SetMyOptions(Value : Integer); begin if FMyOptions <> Value then FMyOptions := Value; end; И все? Спасибо |
Сообщ.
#6
,
|
|
|
Сделал как описал выше - ничего не работает. Что опять не так в прведенных кодах?
Спасибо. |
Сообщ.
#7
,
|
|
|
блин. я не туда посмотрел. посути тебе событие сейчас не нужно
ошибка твоя в куске with TMyComponent(self) do case Index of 0 : Result := CalculateSomeData.MyData1; 1 : Result := CalculateSomeData.MyData2; 2 : Result := CalculateSomeData.MyData3; end; что бы увидеть в чем тут ошибка замени строчку with TMyComponent(self) do на равноправную ей, но с проверкой на на тип with self as TMyComponent do Добавлено Цитата ViktorXP @ блин. я не туда посмотрел. посути тебе событие сейчас не нужно Хотя смотря как ты решишь выйти из ситауции. |
Сообщ.
#8
,
|
|
|
Спасибо, я применил и компилятор выдал несовместимость тиов, а как тогда передать эти параметры в данную функцию?
|
Сообщ.
#9
,
|
|
|
либо тыкай овнера в MyObject (или замени класс на тот у которого уже есть овнер) или по событию передавай туда данные
|
Сообщ.
#10
,
|
|
|
прописать еще одно свойство в класс TMyObject?
TMyObject = class (TPersistent) private FMyOwner : TMyComponent; property MyOwner : TMyComponent read FMyOwner write FMyOwner; end; или как-то иначе, можно простой пример? событие для меня еще очень сложно написать. |
Сообщ.
#11
,
|
|
|
НО если прописать Owner выше его класса, то это ошибка компилятора, если расположить весь класс TMyObject ниже класса компонента (TMyComponent), то тогда компилятор выдает что не видит класс моего объекта. Замкнутый круг просто. Есть реальное решение как выйти из данной ситуации. Можно небольшой пример. спасибо.
|
Сообщ.
#12
,
|
|
|
для этого есть возможность в делфи
type TTest2 = class; TTest1 = class(TObject) Test2: TTest2; end; TTest2 = class(TObject) Test1: TTest1; end; |
Сообщ.
#13
,
|
|
|
при приведенной выше конструкции выдается множество ошибок несоотвествия типов, например constructor Create(AOwner : TComponent); override;
и destructor. А как можно еще передать с помощью события? Можно небольшой пример. спасибо |
Сообщ.
#14
,
|
|
|
Цитата SkAndriy @ при приведенной выше конструкции выдается множество ошибок несоотвествия типов, например constructor Create(AOwner : TComponent); override; Ну наверное потому что ты предка взял без виртуального конструктор constructor Create(AOwner : TComponent); |
Сообщ.
#15
,
|
|
|
В моеже показать как с помощью события, без модификаци классов, оставляя код как есть реализовать данную задачу? спасибо
|
Сообщ.
#16
,
|
|
|
нее. ты уже копай в одну сторону. это не сложно. ты дошол до виртуальный методов. примени то что учил на практике (я надеюсь что ты хоть мельком читал про ооп)
|
Сообщ.
#17
,
|
|
|
а может классы разделить в разные модули и подключить друг к другу? это будет работать в данном примере. спасибо
|
Сообщ.
#18
,
|
|
|
извините, я не программист, а компонент нужен для собственной научной работы. поэтому я и попросил помощи здесь на форум, чтобы опытные программисты поправили приведеднный код выше. я медик, а не программист. разбираться конечно буду, но это по опыту займет много времени, а компонент мне нужен сейчас. спасибо за помощь.
|
Сообщ.
#19
,
|
|
|
Цитата SkAndriy @ а может классы разделить в разные модули и подключить друг к другу? это будет работать в данном примере. спасибо если ты имеешь ввиду работу вообще то да. А вот скомпилирует ли это делфя зависит от того как ты напишешь. Коль ты не программист то даю подсказку: перегрузить ты сможешь только виртуальный метод и оба они должны быть одинаково объявлены. в TObject не то что параметров нет в конструкторе. он даже объявлен не виртуальным. Посему создавай свой виртуальный (или простой) конструктор |
Сообщ.
#20
,
|
|
|
в отдельных модулях пробовал - не работает. спасибо за помощь
|
Сообщ.
#21
,
|
|
|
Вы могли бы мне дать ссылку на реальный примерв интернете или на модуль готового компонента как решить мою задачу. пересмотрел наверное море информации, но только запутался в этом. спасибо.
|
Сообщ.
#22
,
|
|
|
Да тут нет ничего сложного.
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-фничка лежит. очень хорошая информация. |
Сообщ.
#23
,
|
|
|
Да, но я уже пробовал, если поставить TFOwner: TMyComponent; до объявления класса TMyComponent, то компилятор выдает ошибку или я ничего не понимаю. А если поставить впереди TMyComponent = class, то снова масса ошибок. Спасибо за ответ
|
Сообщ.
#24
,
|
|
|
Я исправил вроде как мы дискутировали, компонент компилируется,но свойств TMyObject вообще нет. В общем снова не работает. Что в этот раз не так в этом коде. Спасибо
Прикреплённый файлMyComponent.zip (1,66 Кбайт, скачиваний: 162) |
Сообщ.
#25
,
|
|
|
А подробнее что за ошибки. Хотя подозреваю что AV вываливается. Так как ты вообще закомментировал строку создания объекта. Только вот интересно зачем? ты ведь не думаешь что объект сам собой создастся.
|
Сообщ.
#26
,
|
|
|
я приложил файлы pas. У меня делфи 2010. Ошибка - компонент не работает - даже свойств нового объекта нет.
Там где закомментировал и ошибка при компилировании компонента. |
Сообщ.
#27
,
|
|
|
Цитата SkAndriy @ я приложил файлы pas. Я видел. ибо откуда я сделал вывод от строке конструирования Цитата SkAndriy @ У меня делфи 2010. У меня тоже 14 версия. но это сути дела не меняет. Никогда не было авто создания объекта. Цитата SkAndriy @ Ошибка - компонент не работает - даже свойств нового объекта нет. А откуда они возьмутся если объект nil Добавлено Цитата SkAndriy @ Там где закомментировал и ошибка при компилировании компонента. А тебя не настораживает что в конструкторе есть параметр. а ты пытаешься его вызвать без параметра. О чем и предупреждает тебя компилятор (посмотри внимательно на текст ошибки). |
Сообщ.
#28
,
|
|
|
Этот вариант компилируется, поля есть нового объекта, но они почему-то не заполнются случайными значениями от функции function TMyComponent.CalculateSomeData : TMyDataRecord; Почему? Что опять не так? И еще компилятор при компилировании компонета выдает сообщение :
[DCC Warning] Unit2.pas(34): W1010 Method 'Assign' hides virtual method of base type 'TPersistent' Как это исправить? Спасибо Прикреплённый файлMyComponent.zip (1,72 Кбайт, скачиваний: 137) |
Сообщ.
#29
,
|
|
|
Цитата SkAndriy @ Это компилятор предупреждает что в TPersistent есть виртуальный метод Assign а ты его перекрываешь своей одноименной процедурой.[DCC Warning] Unit2.pas(34): W1010 Method 'Assign' hides virtual method of base type 'TPersistent' Цитата SkAndriy @ Как это исправить? добавить override; Цитата SkAndriy @ Что опять не так? Все те же старые ошибки with TMyComponent(self) do |
Сообщ.
#30
,
|
|
|
Спасибо за учебу и помощь.
1. Справка делфи рекомендует прописывать так: procedure Assign(Source: TPersistent); reintroduce; https://forums.embarcadero.com/thread.jspa?threadID=35796&tstart=0 2. строку "with TMyComponent(self) do" исправил. Спасибо еще раз. |
Сообщ.
#31
,
|
|
|
reintroduce это заглушка на то что бы компилятор не ругался на перекрытие одноименных процедур функций.
он применяется к GetOwner для того что бы можно было объявить свою функцию с овнером (ибо не интересно постоянно овнера приводить к нужному типу. проще что бы функция возвращала нужный тип сразу). Assign есть в базовом классе. при этом он является виртуальным. и это не с проста. ты допустил логическую ошибку не перегрузив его. а потом еще сказал компилятору что ты так и хотишь. но логику ты прибил. Так как теперь AssingTo вызовет старый обработчик к которому твой не привязан и он отработает в пустую. пс. посему reintroduce тут не приемлем. Добавлено С таким успехом ты мог оставить предка TObject и не парится с TPersistent |
Сообщ.
#32
,
|
|
|
Цитата SkAndriy @ извините, я не программист, а компонент нужен для собственной научной работы... разбираться конечно буду, но это по опыту займет много времени, а компонент мне нужен сейчас Почему тогда именно компонент, да еще и с редактором свойств-множеств ? Если пишешь для себя, а не для "дяди", то проще не возится с созданием полноценного компонента с заданием св-в в инспекторе, а создавать объект и задавать его св-ва динамически в FormCreate |
Сообщ.
#33
,
|
|
|
доброе утро.
для leo потому что задача требует однотипных решений для нескольких приложений и так с моей точки зрения рациональнее. надеюсь, что ответ удовлетворит Вас. спасибо. для ViktorXP 1. Понял, спасибо и исправил в procedure Assign(Source: TPersistent); override; 2. Так лучше использовать метод Assign или все же AssignTo? Если AssignTo, то что надо исправить в процедуре, кроме самого названия метода: 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; Очень рад знакомству с настоящим мастером, если это для Вас было не слишком обременительным. Еще раз спасибо за терпение, учебу и помощь. |
Сообщ.
#34
,
|
|
|
различия между Assign и AssignTo в направлении "переноса" данных
Приемник.Assing(Источник); Источник.AssingTo(Приемник); Цитата SkAndriy @ Очень рад знакомству с настоящим мастером Самое сложное в программировании это понять логику всего этого. А все остальное это опыт. Добавлено Цитата SkAndriy @ Так лучше использовать метод Assign или все же AssignTo? Будет достаточно того что ты наделил его override |
Сообщ.
#35
,
|
|
|
Как видно из предыдущего сообщения я использовал метод Assign.
Я прописал его исходя из общего кода правильно? Спасибо |
Сообщ.
#36
,
|
|
|
сам метод написан правильно.
|
Сообщ.
#37
,
|
|
|
Спасибо
|
Сообщ.
#38
,
|
|
|
Попутно возник еще вопрос - как при изменении параметра-свойства MyOptions в классе TMyComponent с помощью Редактора Свойств каждый раз обнулить (т.е. устанавливать их к 0) значения свойств Property1, Property2, Property3 класса TMyObject перед занесением в них предвычисленных величин. Пробовал дописать к этим свойствам default или store ничего не происходит. Может есть какой-то специальный синтаксис? Мне необходимо обнулять каждый раз при обновлении MyOptions, так что просто прописать все свойства в конструкторе к нулю не проходит. Спасибо.
|
Сообщ.
#39
,
|
|
|
а тут уже событие нужно.
Добавлено вот то что ты тогда писал + обнуление параметров. |
Сообщ.
#40
,
|
|
|
Событие в классе в классе TMyComponent?
Так правильно: 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? Или можно небольшой пример, мне так проще понять задачу в целом. Спасибо |
Сообщ.
#41
,
|
|
|
Цитата SkAndriy @ Как видно из предыдущего сообщения я использовал метод Assign. Я прописал его исходя из общего кода правильно? Нет, не правильно, т.к. если TMyObject является прямым наследником TPersistent, то inherited Assign вызовет AssignTo, который в свою очередь вызовет исключение EConvertError. Поэтому для прямых наследников нужно вызывать inherited только в части else: procedure TMyObject.Assign(Source: TPersistent); begin if Source is TMyObject then begin ... end else //<---- !!! inherited Assign (Source); end; |
Сообщ.
#42
,
|
|
|
Цитата SkAndriy @ Так правильно: Я не это имел ввиду сообщение под номером пять + в нем же и меняешь значения своего объекта. Цитата leo @ Нет, не правильно, т.к. если TMyObject является прямым наследником TPersistent, то inherited Assign вызовет AssignTo, который в свою очередь вызовет исключение EConvertError. Поэтому для прямых наследников нужно вызывать inherited только в части else Это да. я что то на это не обратил внимание. |
Сообщ.
#43
,
|
|
|
Т.е. в коде просто обнулить все свойства (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. 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; Как привести это код к нужному событию? Спасибо. |
Сообщ.
#44
,
|
|
|
Цитата SkAndriy @ Ты не сможеш найменовать метод такимже именем как и свойство. Если взять негласное правило то имя ему нарекаем DoChange procedure TMyComponent.OnChange; пс. и не забудь его объявить в классе. а дальше немного дописываешь код procedure TMyComponent.SetMyOptions(Value : Integer); begin if FMyOptions = Value then Exit; FMyOptions := Value; Property1 := 0; Property2 := 0; Property3 := 0; DoChange; end; |
Сообщ.
#45
,
|
|
|
Немного подправил код:
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." к свойствам компилятор выдавал ошибку или как-то иначе необходимо. Но есть одно но - не все поля почемуто обнуляются. Что в этом коде еще не соответствует? Так верно? 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; procedure SetMyEnum(Value : TMyEnumType); begin if Assigned(Value) then ???????????????? end; Спасибо |
Сообщ.
#46
,
|
|
|
Цитата SkAndriy @ Но есть одно но - не все поля почемуто обнуляются. Что в этом коде еще не соответствует? если выходить из того что у тебя идет обявления property Property3: Double index 2 read GetDataElement write FProperty3; То результатом выхода данных является то что возвращает GetDataElement а что ты там пересчитываешь это уже только ты знаешь. посмотри логику. в большей степени вероятности там и кроется то что параметры не обнуляется. Цитата SkAndriy @ property DoChange : TNotifyEvent read FOnDoChange write FOnDoChange; И что ты этим написал? зачем ты переименовал свойство? разве я об этом писал? И где метод о котором я писал? Цитата SkAndriy @ И еще вопрос нужен ли в коде компонента код: Assigned(Value) применяется к ссылкам. ты не сможешь его применить к простому типу. У простых типов можно только сравнивать на значение. например в этом случае можно написать procedure SetMyEnum(Value : TMyEnumType); begin if Value <> FMyEnum then |
Сообщ.
#47
,
|
|
|
Цитата ViktorXP @ И что ты этим написал? зачем ты переименовал свойство? разве я об этом писал? И где метод о котором я писал? Я не понял этого. Можно конкретнее. Спасибо |
Сообщ.
#48
,
|
|
|
Если так, например для FMyOptions:
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 по аналогии. Или как то иначе. будет верно? Спасибо |
Сообщ.
#49
,
|
|
|
уже лучше только расстановка негласных правил не верна. да и секции размещения перепутаны.
Цитата SkAndriy @ переименовываем обратно в Onproperty DoChangeMyOptions : TDoChangeMyOptionsEvent read FOnDoChangeMyOptions write FOnDoChangeMyOptions; property OnChangeMyOptions : TOnChangeMyOptionsEvent read FOnChangeMyOptions write FOnChangeMyOptions; тогда метод Цитата SkAndriy @ соответственно в Doprocedure OnDoChangeMyOptions(Sender : Tobject; Index : Integer) procedure DoChangeMyOptions(Sender : Tobject; Index : Integer); для метода DoChangeMyOptions не нужен первый параметр Sender. он его и так знает. посему обявление можно подправить как: procedure DoChangeMyOptions(Index : Integer); а вот в теле метода у тебя ошибка FOnDoChangeMyOptions(Self); сама переменная FOnDoChangeMyOptions является типом TDoChangeMyOptionsEvent у которого два параметра. так почему ты передаеш только одно? посему дописываем второй параметр (+ предшествующие изминения) procedure TMyComponent.DoChangeMyOptions(Index : Integer); begin if Assigned (FDoChangeMyOptions) then FOnDoChangeMyOptions(Self, Index); end; также у тебя синтаксическая ошибка publishin. правильнее published а теперь о секциях размещения: само свойство ты спрятал в протекции. посему никто этого свойства не увидет кроме компонента который будет наследоватся от этого. А вот реакцию (DoChangeMyOptions) ты на оборот показал всем (даже дизайнеру свойств. хотя он этого и не оценит. так как он показывает только свойства) вывод: меняй местами. |
Сообщ.
#50
,
|
|
|
Вот код, но где-то ошибка, а где не могу понять.
Спасибо |
Сообщ.
#51
,
|
|
|
Вот код, но где-то ошибка, а где не могу понять.
Спасибо Прикреплённый файлUnit2.zip (1,15 Кбайт, скачиваний: 132) |
Сообщ.
#52
,
|
|
|
Цитата Но если мне не изменяет память то в 33 сообщении говорится об обратномprocedure Assign(Source: TPersistent); reintroduce; насчет Цитата leo говорил в 41 посте.inherited Assign (Source); ну и ошибка логическая procedure TMyComponent.SetMyOptions(Value : Integer); begin .... OnChangeMyOptions(Self, Value); end; посему вызов nil(self, value) приведет к ошибке. |
Сообщ.
#53
,
|
|
|
Спасибо. все предыдущие ошибки исправил, процедуру события тоже. Все вызывается. А если просто применить стандартное событие OnChange на что в этом компоненте оно будет реагировать?
|
Сообщ.
#54
,
|
|
|
И например, его прописать так:
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? Спасибо |
Сообщ.
#55
,
|
|
|
А что ты имеешь ввиду под словом стандартное? OnChange это просто название. тип TNotifeEvent это просто тип. это все ни к чему не привязано. а реагировать оно будет так как ты это напишешь.
пс. логика событий не зависит от имени. Добавлено Цитата SkAndriy @ На какие изменения или какие события я в таком случае могу обработать в realtime? так ты ведь сам написал if(FMyEnum <> Value) then begin FMyEnum:=Value; Changed; end; |
Сообщ.
#56
,
|
|
|
Тогда по логикне вещей получается если прописать процедуру onChanged в процедуре procedure TMyComponent.SetMyEnum(Value: TMyEnumType) в realtime она будет реагировать на изменения свойства MyEnumProp класса TMyEnumType? А как она должна быть и в каих секциях прописана в самом TMyComponent = class(TComponent)? Спасибо
|
Сообщ.
#57
,
|
|
|
Цитата SkAndriy @ private - доступны переменные/методы/свойства только самому компоненту и ни кому более. (для свойств не используется)в каих секциях прописана protected - доступны переменные/методы/свойства только компоненту и его потомкам public - достопны переменные/методы/свойства всем желающим. published - тоже что и public + свойства видимы в инспекторе (используется исключительно для свойств. на все другое компилятор выдает предупреждение) тебе определенно нужно книжку взять и почитать насчет ООП. |
Сообщ.
#58
,
|
|
|
Я это знаю, я имел ввиду иное:
достаточно прописать просто в published OnChange, а если ему дописать параметры, например OnChange(Sender:Objects; Index:Integer)? тогда надо объявлять как в предыдущем рассматриваемом случае? Спасибо |
Сообщ.
#59
,
|
|
|
Цитата SkAndriy @ тогда надо объявлять как в предыдущем рассматриваемом случае? Что ты под этом имеешь ввиду? если нужнен ли в таком случае метод Do..xxx.. то да. он нужен в любом случаи. |
Сообщ.
#60
,
|
|
|
Спасибо. Вроде понял.
|