Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.224.214.215] |
|
Сообщ.
#1
,
|
|
|
Добрый день!
Создаю свойства-множества в моем компоненте по такой схеме: Код: unit MyComponent; interface uses SysUtils, Types, Classes; type TMyEnumType = (eFirst, eSecond, eThird); TMySetTypeFirst = (poFirst1, poSecond1, poThird1); TMySetTypeSecond = (poFirst2, poSecond2, poThird2); TMySetTypeThird = (poFirst3, poSecond3, poThird3); TMySetType = set of TMySetTypeFirst; // TMySetTypeSecond? TMySetTypeThird? type TMyComponent = class(TComponent) private { Private declarations } FMyEnum: TMyEnumType; FMyOptions: TMySetType; protected { Protected declarations } public { Public declarations } published { Published declarations } property MyEnumProp: TMyEnumType read FMyEnum write FMyEnum; property MyOptions: TMySetType read FMyOptions write FMyOptions; end; procedure Register; implementation procedure Register; begin RegisterComponents('Samples', [TMyComponent]) end; end. С TMySetType все понятно, создается выбор из множества первого типа (TMySetTypeFirst) от TMyEnumType = eFirst, а как динамично подключать (или переключать) к TMySetType множества TMySetTypeSecond (если TMyEnumType = eSecond) и TMySetTypeThird (если TMyEnumType = eThird), чтобы MyOptions показывали нужные мне типы множеств (TMySetTypeFirst или TMySetTypeSecond или TMySetTypeThird)? Спасибо |
Сообщ.
#2
,
|
|
|
обычным способом никак. Так как с точки зрения компилятора это разные типы. Но можно подменять визуально (если я правильно понял и тебе это нужно выбирать через дизайнер)
uses DesignIntf, Classes, DesignEditors, TypInfo; type TMyEnumType = (eFirst, eSecond, eThird); TMySetTypeFirst = (poFirst1, poSecond1, poThird1); TMySetTypeSecond = (poFirst2, poSecond2, poThird2); TMySetTypeThird = (poFirst3, poSecond3, poThird3); TMyComponent = class(TComponent) private { Private declarations } FMyEnum: TMyEnumType; FMyOptions: Integer; published property MyEnumProp: TMyEnumType read FMyEnum write FMyEnum; property MyOptions: Integer read FMyOptions write FMyOptions; end; TMySetTypeProperty = class(TEnumProperty) private function GetTypeInfo: PTypeInfo; public function GetValue: string; override; procedure GetValues(Proc: TGetStrProc); override; procedure SetValue(const Value: string); override; end; procedure Register; implementation uses SysUtils; procedure Register; begin RegisterComponents('test', [TMyComponent]); RegisterPropertyEditor(TypeInfo(Integer), TMyComponent, 'MyOptions', TMySetTypeProperty); end; function TMySetTypeProperty.GetTypeInfo: PTypeInfo; var Obj: TPersistent; begin Obj := GetComponent(0); if Assigned(Obj) and (Obj is TMyComponent) then with TMyComponent(Obj) do begin case MyEnumProp of eFirst: Result := TypeInfo(TMySetTypeFirst); eSecond: Result := TypeInfo(TMySetTypeSecond); eThird: Result := TypeInfo(TMySetTypeThird); end; end else Result := GetPropType; end; function TMySetTypeProperty.GetValue: string; var L: Longint; begin L := GetOrdValue; with GetTypeData(GetTypeInfo)^ do if (L < MinValue) or (L > MaxValue) then L := MaxValue; Result := GetEnumName(GetTypeInfo, L); end; procedure TMySetTypeProperty.GetValues(Proc: TGetStrProc); var I: Integer; EnumType: PTypeInfo; begin EnumType := GetTypeInfo; with GetTypeData(EnumType)^ do begin for I := MinValue to MaxValue do Proc(GetEnumName(EnumType, I)); end; end; procedure TMySetTypeProperty.SetValue(const Value: string); var I: Integer; begin I := GetEnumValue(GetTypeInfo, Value); with GetTypeData(GetPropType)^ do if (I < MinValue) or (I > MaxValue) then raise Exception.Create(''); SetOrdValue(I); end; |
Сообщ.
#3
,
|
|
|
два вопроса:
1. delphi 2010 не находит DesignIntf и DesignEditors. как быть? 2. где прописан тип TEnumProperty? спасибо |
Сообщ.
#4
,
|
|
|
Код компонента и код редактора свойств нужно разделить на два модуля. А в инсталяционный пакет добавить DesignIde
|
Сообщ.
#5
,
|
|
|
офтоп:
SkAndriy, редактировать сообщение не есть гуд. ибо уведомление подписчикам на тему не приходит. |
Сообщ.
#6
,
|
|
|
спасибо. замечание учтено.
|
Сообщ.
#7
,
|
|
|
при компилировании в функции:
function TSetTypeProperty.GetTypeInfo: PTypeInfo; var Obj: TPersistent; begin Obj := GetComponent(0); if Assigned(Obj) and (Obj is TEphemeridae) then with TEphemeridae(Obj) do begin case CelestialObject of oPlanets : Result := TypeInfo(TSetTypePlanets); oAsteroids : Result := TypeInfo(TSetTypeAsteroids); // oStars : Result := TypeInfo(TMySetTypeStars); // oComets : Result := TypeInfo(TMySetTypeComets); end; end else Result := GetPropType; end; выдается такое сообщение: [DCC Warning] MyComponent.pas(79): W1035 Return value of function 'TSetTypeProperty.GetTypeInfo' might be undefined как это можно исправить? спасибо |
Сообщ.
#8
,
|
|
|
функция пдправил так:
function TSetTypeProperty.GetTypeInfo: PTypeInfo; var Obj: TPersistent; begin Obj := GetComponent(0); if Assigned(Obj) and (Obj is TEphemeridae) then with TEphemeridae(Obj) do begin case CelestialObject of oPlanets : Result := TypeInfo(TSetTypePlanets); oAsteroids : Result := TypeInfo(TSetTypeAsteroids); oStars : Result := TypeInfo(TSetTypeStars); oComets : Result := TypeInfo(TSetTypeComets); else Result := TypeInfo(TSetTypePlanets); end; end else Result := GetPropType; end; компонент компилируется и инсталируется. но когда я кладу его на форму нового проекта и запускаю на компилирование, то получаю ошибку: при компилировании проекта с этим тестируемым компонентом выдается ошибка: [DCC Fatal Error] Unit1.pas(7): F1026 File not found: 'DesignEditors.dcu', у меня проект на делфи 2010 - как найти или включить DesignEditors.dcu. В секцию Requires компонента я включил и скомпилировал уже ранее designide.dcp Проблема остается. В делфи статьях есть такой ответ: Using the Delphi DesignIntf and DesignEditors Tools If you are creating a C++ package that contains a Delphi unit that uses the DesignIntf and DesignEditors tools, you must choose Project > Options > Delphi Compiler > Other Options. In Use these packages when compiling, add DesignIDE in the combo box. Но в Делфи 2010 Project > Options > Delphi Compiler > Other Options - отсуствет такой раздел, как и "Use these packages when compiling" или где их найти и установить нужные опции. если можно подробный ответ как можно исправить это. спасибо |
Сообщ.
#9
,
|
|
|
В секцию Requires компонента я включил и скомпилировал уже ранее designide.dcp; прописал путь к папке ToolsAPI, где находятся искомые файлы (DesignIntf.pas и DesignEditors.pas); перекомпилировал и файлы DesignIntf.dcu и DesignEditors.dcu появились в папке ToolsAPI, но теперь при компилировании нового проекта с моим компонентом выдается ошибка:
[DCC Fatal Error] ToolsAPI.pas(17): F1026 File not found: 'DockForm.dcu' что еще надо внести в секцию Requires, чтобы скомпилировать все модули в папке ToolsAPI? Спасибо. |
Сообщ.
#10
,
|
|
|
Цитата SkAndriy @ Это легко исправляется способом который описал DimaBr если можно подробный ответ как можно исправить это. |
Сообщ.
#11
,
|
|
|
1. в инсталяционный пакет уже добавил DesignIde
2. модули разделил, модуль редактора свойств выглядит так: unit PropertyEditor; interface uses Windows, Messages, SysUtils, Variants, Classes, DesignIntf, DesignEditors, TypInfo; type TMySetTypeProperty = class(TEnumProperty) private function GetTypeInfo: PTypeInfo; public function GetValue: string; override; procedure GetValues(Proc: TGetStrProc); override; procedure SetValue(const Value: string); override; end; procedure Register; implementation uses UnitMyComponent; function TMySetTypeProperty.GetTypeInfo: PTypeInfo; var Obj: TPersistent; begin Obj := GetComponent(0); if Assigned(Obj) and (Obj is TMyComponent) then with TMyComponent(Obj) do begin case MyEnumProp of eFirst: Result := TypeInfo(TMySetTypeFirst); eSecond: Result := TypeInfo(TMySetTypeSecond); eThird: Result := TypeInfo(TMySetTypeThird); end; end else Result := GetPropType; end; function TMySetTypeProperty.GetValue: string; var L: Longint; begin L := GetOrdValue; with GetTypeData(GetTypeInfo)^ do if (L < MinValue) or (L > MaxValue) then L := MaxValue; Result := GetEnumName(GetTypeInfo, L); end; procedure TMySetTypeProperty.GetValues(Proc: TGetStrProc); var I: Integer; EnumType: PTypeInfo; begin EnumType := GetTypeInfo; with GetTypeData(EnumType)^ do begin for I := MinValue to MaxValue do Proc(GetEnumName(EnumType, I)); end; end; procedure TMySetTypeProperty.SetValue(const Value: string); var I: Integer; begin I := GetEnumValue(GetTypeInfo, Value); with GetTypeData(GetPropType)^ do if (I < MinValue) or (I > MaxValue) then raise Exception.Create(''); SetOrdValue(I); end; procedure Register; begin RegisterPropertyEditor(TypeInfo(Integer), TMyComponent, 'MyOptions', TMySetTypeProperty) end; end. Результат прежний, при компилировании нового проекта с этим компонентом все время ошибки с разными dcu спасибо. |
Сообщ.
#12
,
|
|
|
ну не знаю. только что набросал
проектddddd.rar (8,35 Кбайт, скачиваний: 209)
и все отработало как часики.
|
Сообщ.
#13
,
|
|
|
Спасибо все компилируется, а что действительно другого пути чем в райнтайм обращаться к свойствам только так: TMySetTypeXXXX(MyComponent.MyOptions) или можно как-то иначе, прописав в самом компоненте. спасибо за помощь.
|
Сообщ.
#14
,
|
|
|
Без явного приведения типа ты с им работать не сможешь. или же работай с цифровым типом. разница от этого не поменяется.
|
Сообщ.
#15
,
|
|
|
например,
private FTypeFirst : TMySetTypeFirst; строка в тестовом приложении : в процедуре FormCreate, например, if FTypeFirst = TMySetTypeFirst(MyComponent1.MyOptions).poSecond1 then Caption := 'It is Second1'; не компилирется, а выскакивает ошибка. Почему? Спасибо. |
Сообщ.
#16
,
|
|
|
if FTypeFirst = TMySetTypeFirst(MyComponent1.MyOptions) then Caption := 'It is Second1'; |
Сообщ.
#17
,
|
|
|
Мне необходимо во-первых установить одно из значений множества TMyEnumType затем выбирая из множества TMySetTypeFirst или TMySetTypeSecond или TMySetTypeThird получать свойства соотвествующие этим значениям, например,
TMyEnumType = eThird; MyOptions = poSecond3; например, в компонент добавлены несколько изменяющихся свойств (полей) Property1 = "aaaaaa" Property2 = "bbbbbb" Property3 = "cccccc" далее я изменяю TMyEnumType = eFirs; MyOptions = poThird1; и свойства должны также измениться на другие значения (они вычисляюся ранее): Property1 = "dddddd" Property2 = "eeeeee" Property3 = "xxxxxx" как этого можно достичь? годится ли вот такая конструкция? вот такая конструкция сложная, но работает, а есть более простой способ? procedure TForm3.FormCreate(Sender: TObject); begin FTypeFirst := TMySetTypeFirst(MyComponent1.MyOptions); if Integer(FTypeFirst) = 1 then Caption := 'It is Second1'; end; Спасибо. |
Сообщ.
#18
,
|
|
|
if MyComponent1.MyOptions = 1 then Caption := 'It is Second1'; у меня такое чувство что ты куда то идешь не туда куда нужно, и что самое странное что я тебе в этом помогаю. Опиши полную ситуацию что ты этим всем хотиш сделать. Может тебе будет проще разделить компоненты на части. первый главный, а второй с нужными свойствами (и логикой под их). и ты просто подключаешь их по очереди к главному. Одним словом опиши ситуину. (пс. я спать если что застра отвечу) |
Сообщ.
#19
,
|
|
|
Задача:
Есть главное множество (A,B,C,D,E), каждое значение его имеет свое собственное подмножество (неодинаковые подмножества) A = (a, b, c, d, e, f) B = (q, w, g, r, y) и так далее E = (l, k, z, x) Выбирая из главного множества значение, например "B" или "E", оно определит в свойстве MyOptions подмножество выбора, например, B = (q, w, g, r, y) или E = (l, k, z, x). А каждому значению этого подмножества, например (q, w, g, r, y) или (l, k, z, x), соответствуют значения свойств, например свойство1, свойство2 и свойство3. Свойства "свойство1, свойство2 и свойство3" только для чтения и это должны быть расчетные величины в самом компоненте, значения которых зависят от измения свойства "Дата" (число, месяц, год) и соответствуют одному из значений подмножества, например (q, w, g, r, y) или (l, k, z, x), главного множества B или E. ============================================================================== В программе, использующей этот компонент будут использоваться элементы : 1. свойство дающее значение главного множества, например B или E или A 2. свойство дающее значение подмножеств, например (q, w, g, r, y) или (l, k, z, x) 3. расчетная дата (число, месяц, год) для свойств (свойство1, свойство2 и свойство3) 4. расчетные свойства (свойство1, свойство2 и свойство3) для конкретного значения(например, "q") подмножества (например, подмножества "B") ================================================================================ Например, 1. выбрали в главном множестве = E 2. в подмножестве E = z 3. свойство1 = 5, свойство2 =10 и свойство3=4 1. выбрали в главном множестве = E 2. в подмножестве E = l 3. свойство1 = 0, свойство2 =9 и свойство3=2 1. выбрали в главном множестве = A 2. в подмножестве A = d 3. свойство1 = 15, свойство2 =7 и свойство3=3 1. выбрали в главном множестве = B 2. в подмножестве E = y 3. свойство1 = 1, свойство2 =98 и свойство3=43 и так далее. очень желательно не разбивать компонент на части. первая часть уже получилась вроде, теперь как управлять ею задача? а если разбивать, то как соединить или подключать каждый из компонентов, соответствующий разным множествам или подмножествам? мне кажется, что один компонет все же проще и логичней. спасибо за помощь. это мой первый компонент, но срочно нужен для своей научной работы. |
Сообщ.
#20
,
|
|
|
1. Сделайте ОЧЕНЬ главное множество a..x: TMain = (a, b, c, d, e, f, .... l, k, z, x)
2. Выделите из него подмножества (a..f)(q..y): TA = a..f; TE=l..x; 3. Присвойте каждому элементу ОЧЕНЬ главного множества число: const Value: array[TMain] of integer = (1,2,3,4,5....); 4. Немного видоизменив редактор свойств для MyOptions получите требуемый результат, где возвращаемый тип будет TMain |
Сообщ.
#21
,
|
|
|
спасибо за ответ, как изменить? это мой первый компонент. нужен исключительно для своей научной работы.
|
Сообщ.
#22
,
|
|
|
Я же говорю, сначала отработайте всё в RunTime, а потом поговорим про дизайнер. Создавайте компонент динамически, что бы поупражняться с ним в работе.
|