![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
одинаковые значения свойств
Kerk © (2005-12-18 14:45:00)Есть несколько форм. Компонентам на этих формах необходимо задать одинаковые значения некоторых свойств (например шрифт). Компоненты разные, формы тоже. Значения "единых" свойств могут меняться в рантайм. Вот сижу, думаю. Можно конечно вручную все это контролировать, но криво. Хотелось бы маленький framework. Идеи?
sniknik (2005-12-21 08:59:00) [1]Юрий Зотов © (21.12.05 03:57) [5]
вот пример именно такой реализации 18-го вечером отправил ему по почте, но чегото молчит... не дошло чтоли.
кстати уточнение, пример конкретно для Font-а, неудачный... есть же свойство ParentFont, и у всех компонент по умолчанию оно true (ну почти у всех). достаточно следить чтобы оно таким (true) и оставалось, и менять фонт только у формы.
Джо (2005-12-21 04:55:00) [2]Cорри за форматирование, забыл тэг закрыть.
Джо (2005-12-21 04:54:00) [3]Ладно, может кому еще пригодится, забрасываю юнит из своих старых грехов, немного подправил :)
unit PropSync;
interface
uses SysUtils, Classes, TypInfo, Contnrs, Forms;
type
TPropertiesSynchronizer = class
private
FFormClasses: TClassList;
procedure SynchronizeForm (AForm: TForm; AClass: TClass;
APropName: string; AValue: Variant);
function Registered (AForm: TForm): boolean;
public
procedure RegisterFormClass (AFormClass: TFormClass);
procedure Synchronize (AClass: TClass; APropertyName: string;
AValue: Variant);
constructor Create;
destructor Destroy; override;
end;
implementation
uses Variants;
{ TPropertiesSynchronizer }
constructor TPropertiesSynchronizer.Create;
begin
inherited Create;
FFormClasses := TClassList.Create;
end;
destructor TPropertiesSynchronizer.Destroy;
begin
FFormClasses.Free;
inherited;
end;
function TPropertiesSynchronizer.Registered(AForm: TForm): boolean;
var
I: Integer;
begin
Result := False;
for I := 0 to FFormClasses.Count - 1 do
if FFormClasses[I] = AForm.ClassType then
begin
Result := True;
Break
end;
end;
procedure TPropertiesSynchronizer.RegisterFormClass(AFormClass: TFormClass);
begin
FFormClasses.Add(AFormClass)
end;
procedure TPropertiesSynchronizer.Synchronize (AClass: TClass;
APropertyName: string; AValue: Variant);
var
I: Integer;
begin
for I := 0 to Screen.FormCount - 1 do
if Registered(Screen.Forms[I]) then
begin
SynchronizeForm(Screen.Forms[I], AClass,
APropertyName, AValue);
end;
end;
procedure TPropertiesSynchronizer.SynchronizeForm(AForm: TForm;
AClass: TClass; APropName: string; AValue: Variant);
var
I: Integer;
Cmp: TComponent;
procedure _SetProp (AInstance: TObject);
var
PropInfo: PPropInfo;
begin
PropInfo := GetPropInfo (AInstance, APropName);
if PropInfo <> nil then
case PropInfo.PropType^^.Kind of
tkClass:
SetObjectProp(AInstance,APropName,TObject(Integer(AValue)));
else
SetPropValue(AInstance,APropName,AValue);
end;
end;
begin
if AForm is AClass then
begin
_SetProp(AForm);
end;
for I := 0 to AForm.ComponentCount - 1 do
begin
Cmp := AForm.Components[I];
if Cmp is AClass then
_SetProp(Cmp);
end;
end;
end.
Пользование(предварительно создаем экз. объекта TPropertiesSynchronizer, разумеется).
МетодомRegisterFormClassрегистрирум КЛАССЫ форм, которые будем использовать:
FPropSync.RegisterFormClass(TForm1);
FPropSync.RegisterFormClass(TForm2);
// etc...
</CODE
Затем используем методSynchronize. Например:
a)FPropSync.Synchronize(TEdit,'Text','The same text');
Одинаковый текст для всех наследников TEdit
b)FPropSync.Synchronize(TWinControl,'Color',clRed);
изменяет свойство Color := clRed для всех наследников TWinControl на всех существующих формах, чей класс был предварительно зарегистрирован при вызове RegisterFormClass.
c)FPropSync.Synchronize(TComponent,'Caption','The same caption');
Меняем Caption для всех наследников TComponent
d)FPropSync.Synchronize(TComponent,'Font',Integer(Label2.Font));
Делаем шрифт для всех наследников TComponent как у Label2
И так далее в таком духе.
Юрий Зотов (2005-12-21 03:57:00) [4]Код [1] решает задачу, но если на каждой форме лежат штук хотя бы по 20 разных компонентов, то при таком подходе замучаешься писать код - этих IS и AS окажется слишком много. А между тем задачу можно решить в общем виде, без всяких IS и AS.
Делаем единую форму-предок, прочие наследуются от нее. На этой форме может вообще не лежать ни одного компонента, а могут и лежать - не важно. Важно лишь то, что у нее есть public-методы под названиями типа SetCommonFont. В методе SetCommonFont идет проход по компонентам формы, у каждого проверяется наличие свойства Font (через RTTI) и если оно есть, то ему ассигнуется нужное значение.
Все. Теперь можем в любой момент вызывать эти методы - свойства получат одинаковое значение.
Германн (2005-12-21 02:13:00) [5]
> Kerk © (18.12.05 15:01) [2]
>
> Карелин Артем © (18.12.05 14:58) [1]
>
> > Можно конечно вручную все это контролировать, но криво.
>
>
> Хотя, наверно, можно написать наследника TForm, где производить
> такое изменение, при изменении "единого" свойства формы.
>
>
Можно, конечно и наследника. Но ты упомянул
> Значения "единых" свойств могут меняться в рантайм.
. А в рантайм, имхо, сойдет и процедура а-ля Карелин Артем © (18.12.05 14:58) [1] с параметромs: TForm
Джо (2005-12-20 18:35:00) [6]
> [2] Kerk © (18.12.05 15:01)
Посмотри почту.
Kerk (2005-12-18 15:01:00) [7]Карелин Артем © (18.12.05 14:58) [1]
> Можно конечно вручную все это контролировать, но криво.
Хотя, наверно, можно написать наследника TForm, где производить такое изменение, при изменении "единого" свойства формы.
Карелин Артем (2005-12-18 14:58:00) [8]
for i := 0 to s.ComponentCount - 1 do
begin
if s.Components[i] is TSplitter then
begin
(s.Components[i] as TSplitter).Color := clBlack;
(s.Components[i] as TSplitter).Beveled := False;
end;
if s.Components[i] is TLabel then
begin
(s.Components[i] as TLabel).Transparent := true;
end;
end;