![]() |
|
|
#1
|
||||
|
||||
|
Создавал не так давно тему по поводу передачи значения переменной в нужный TEdit.Text при ее (переменной) изменении.
Пришла мне в голову некоторая идея по этому поводу. А именно использовать не переменную, а экземпляр некоего класса. В это класс я закину компоненты, которые должны следить за нужной мне переменной (экземпляром класса). То есть не сами компоненты будут следить, а класс, при вызове метода Value будет изменять нужные компоненты. Код:
TMyClass = class private FValue:string function GetStr(index: string): string; procedure SetStr(index: string; const Value: string); public property Value:string read GetVal write SetVal; //кстати, хотелось бы сделать это свойство дефолтным, но // компилятор требует, чтобы оно было массивом, типа property Value[index:DataType]....... end; function TStr.GetStr: string; begin result:=FValue; end; procedure TStr.SetStr(const Value: string); begin FValue := Value; // Далее идет цикл, который перебирает выбранные мною компоненты и меняет нужное свойство на FValue // Но есть проблема. У TEdit'a это свойство Text, у TLabel - Caption и тд // А может, мне вообще потребуется менять свойство Hint или любое другое end; Вот теперь вопрос. Как мне оформить функцию для передачи компонента и record, хранящий информацию о компоненте так, чтобы вместе с самим компонентом программист так же передал нужное свойство для изменения? Код:
TComp = record
Component:TComponent;
Value:{здесь должно быть что то, ссылающееся на нужное свойство компонента}
end;
TComps = array of TComp;
TMyClass = class
private
*****
FComps:TComps;
public
****
procedure AddComponent(C: TComponent;Prop: {должно передаться нужное свойство});
end;
***
procedure AddComponent(C: TComponent;Prop:???);
begin
SetLength(FComps,Length(fcomps)+1);
FComps[High(FComps)].Component := C;
FComps[High(FComps)].Value := Prop; {тут должна передаться ссылка (или что там) на нужное свойство компонента}
end; |
|
#2
|
|||
|
|||
|
Почти такое можно организовать только для Published свойств.
Смотреть в сторону PropInfo |
| Этот пользователь сказал Спасибо icWasya за это полезное сообщение: | ||
morebeauty (14.03.2013)
| ||
|
#3
|
||||
|
||||
|
Если кому интересно, вот такой получился класс. Правда не все методы еще реализовал, но основа готова.
Код:
type
TComp = record
Component:TComponent;
P:String;
Enabled:Boolean;
Link:Boolean;
Variable:string;
end;
TComps = array of TComp;
TLinking = class
private
FSL:TStringList;
FComponents:TComps;
function GetVal(name: string): string;
procedure SetVal(name: string; const Value: string);
function GetCCount: Integer;
function GetProperty(AControl: TPersistent; AProperty: string): PPropInfo;
public
property Value[name:string]:string read GetVal write SetVal; default;
property CCount:Integer read GetCCount;
function AddComponent(const C:TComponent;P,V:String):Boolean;
constructor Create;
destructor Destroy;
end;
implementation
function TLinking.AddComponent(const C: TComponent; P, V: String): Boolean;
begin
SetLength(FComponents,Length(FComponents)+1);
FComponents[High(FComponents)].Component:=c;
FComponents[High(FComponents)].P:=p;
FComponents[High(FComponents)].Enabled:=True;
FComponents[High(FComponents)].Link:=False;
FComponents[High(FComponents)].Variable:=v;
end;
constructor TLinking.Create;
begin
inherited;
FSL:=TStringList.Create;
end;
destructor TLinking.Destroy;
begin
FSL.Free;
inherited;
end;
function TLinking.GetCCount: Integer;
begin
result:=Length(FComponents);
end;
function TLinking.GetProperty(AControl: TPersistent;
AProperty: string): PPropInfo;
var
i: Integer;
props: PPropList;
typeData: PTypeData;
begin
Result := nil;
if (AControl = nil) or (AControl.ClassInfo = nil) then
Exit;
typeData := GetTypeData(AControl.ClassInfo);
if (typeData = nil) or (typeData^.PropCount = 0) then
Exit;
GetMem(props, typeData^.PropCount * SizeOf(Pointer));
try
GetPropInfos(AControl.ClassInfo, props);
for i := 0 to typeData^.PropCount - 1 do
begin
with Props^[i]^ do
if (Name = AProperty) then
result := Props^[i];
end;
finally
FreeMem(props);
end;
end;
function TLinking.GetVal(name: string): string;
begin
Result:=FSL.Values[name];
end;
procedure TLinking.SetVal(name: string; const Value: string);
var
i:Integer;
PropInfo:PPropInfo;
begin
FSL.Values[name]:=Value;
for i:=0 to CCount-1 do
begin
if LowerCase(FComponents[i].Variable)=LowerCase(name) then
begin
PropInfo := GetProperty(FComponents[i].Component, FComponents[i].P);
if PropInfo <> nil then
SetStrProp(FComponents[i].Component, PropInfo, Value);
end;
end;
end;Ну и работает как то так: Код:
procedure TForm1.FormShow(Sender: TObject); begin Linking:=TLinking.Create; //Далее Edit1.Text и Label1.Caption связываются с некоторой переменной Var1 Linking.AddComponent(Edit1,'Text','Var1'); Linking.AddComponent(Label1,'Caption','Var1'); end; procedure TForm1.btn1Click(Sender: TObject); begin Linking['Var1']:='123'; //Меняется переменная Var1 - меняются привязанные к ней свойства компонентов end; На этом сайте так же нашел способы изменения свойств разного типа (не только string) http://www.delphisources.ru/pages/fa...ps_values.html Последний раз редактировалось morebeauty, 14.03.2013 в 12:27. |
|
#4
|
||||
|
||||
|
Хрень это все........
Код:
type
TForm1 = class(TForm)
btn1: TButton;
txt1: TEdit;
lbl1: TLabel;
lbl2: TLabel;
lbl3: TLabel;
procedure btn1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure txt1Change(Sender: TObject);
private
FMyVar: string;
function GetMyVar: string;
procedure SetMyVar(const Value: string);
{ Private declarations }
public
property MyVar:string read GetMyVar write SetMyVar;
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btn1Click(Sender: TObject);
begin
MyVar:='123';
end;
function TForm1.GetMyVar: string;
begin
result:=FMyVar;
end;
procedure TForm1.SetMyVar(const Value: string);
begin
FMyVar:=Value;
if txt1.text<>Fmyvar then
txt1.Text:=FMyVar;
lbl1.Caption:=FMyVar;
lbl2.Caption:=FMyVar;
lbl3.Caption:=FMyVar;
end;
procedure TForm1.txt1Change(Sender: TObject);
begin
MyVar:=txt1.Text;
end; |
|
#5
|
||||
|
||||
|
Цитата:
|