![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
DBAware Controls [D5]
Val © (2003-10-14 14:17:00)
Коллеги, подскажите пожалуйста, как из множества контролов, находящихся, на форме, в контейнере, т.д., определить DBAware Controls и изменить у них всех одно и то же свойство?
Приведение типов при переборе вроде бы не подходит, поскольку это может быть любой DBAware Control?
Val (2003-10-16 11:06:00) [1]
Тем кому интересно: вопрос решался довольно просто с помошью RTTI. Думаю, писателям компонентов не составило бы никакого труда на него ответить.
Вот код из 2-го тома Пачеки,Тейксейры:
Определяем, что компонент имеет свойство "DataSource", на основании чего сходимся на том, что это DBAware Component.
function IsDBAware(AComp: TComponent): Boolean;
var
PropInfo: PPropInfo;
begin
PropInfo := GetPropInfo(AComp.ClassInfo, "DataSource");
Result := PropInfo <> nil;
if Result then
if not ((PropInfo^.Proptype^.Kind = tkClass) and
(GetTypeData(PropInfo^.PropType^).ClassType.InheritsFrom(TDataSource))) then
Result := False;
end;
А вот так устанавливаем то самое, несчастное "ReadOnly":
procedure SetBooleanPropertyIfExists(AComp: TComponent; APropName: String;
AValue: Boolean);
var
PropInfo: PPropInfo;
begin
PropInfo := GetPropInfo(AComp.ClassInfo, APropName);
if PropInfo <> nil then
begin
if PropInfo^.PropType^.Kind = tkEnumeration then
SetOrdProp(AComp, PropInfo, Integer(AValue));
end;
end;
Всем спасибо, вопрос закрыт.
Val (2003-10-14 16:08:00) [2]
>Danilka © (14.10.03 15:47) [18]
с событиями ясно, но с контролами так нехорошо :(
Danilka (2003-10-14 15:47:00) [3]
[17] Val © (14.10.03 15:40)
Если форма - предок для других форм, то сделать у нее события OnBrowse, OnInsert, OnEdit, а наследники, могут в обработчиках этих событий изменять состояния своих контролов как им надо.
Val (2003-10-14 15:40:00) [4]
>Danilka © (14.10.03 15:28) [16]
1.возможно..но это теория.
2.согласен, но с кнопками и т.д. - другая история - можно менять состояния контейнеров, скажем, панелей, на которых они находятся, это не так заботит.
3. На формах-наследниках м.б. любое количество любых контролов, скажем в зависимости от полей отображаемого НД, в каждой форме и каждом контроле менять...или я не понял идеи?
Danilka (2003-10-14 15:28:00) [5]
[15] Val © (14.10.03 15:20)
Универсального никак не сделаешь: т.к., можно сделать DBAware компонент, который-бы не имел свойства ReadOnly, и даже не имел-бы свойства DataSource, или имел-бы, но оно называлось по-другому.
Кроме того, зачастую, в зависимости от состояний требуется менять состояния не только DBAware компонент, но и enable кнопок, например, и других компонент, которые вообще никакого отношения к DB не имеют.
А в чем проблема вручную в обработчиках нужных событий изменить свойства только того, что надо?
Val (2003-10-14 15:20:00) [6]
>Vlad © (14.10.03 15:11) [14]
нет, надо париться, потому что это может быть контрол и из RX и из Ehlib и из еще-черт-знает-откуда...
>All
Вопрос открыт. Ткните в ссылки по теме, пожалуйста.
Vlad (2003-10-14 15:11:00) [7]
Лучше не парься, и сделай как я говорил в [1]
Перебрать все DB компоненты не сложно. Их не так много.
Val (2003-10-14 14:55:00) [8]
как это, что?
property Controls[Index: Integer]: TControl;
откуда я возьму у TControl свойство ReadOnly, скажем?
Vlad (2003-10-14 14:47:00) [9]
Ну и что, в цикле проходишь по всем контролам (именно контролам, а не компонентам) и смотришь, есть ли у них DataSource c помощью ф-ции dmtr © (14.10.03 14:38) [7]
Только имей ввиду, что форма - это иерархическая структура, так что цикл должен быть рекурсивным.
dmtr (2003-10-14 14:46:00) [10]
Вот полный вариант
uses TypInfo, DB;
function IsDataSource(Comp: TComponent): Boolean;
var
PropInfo: PPropInfo;
begin
PropInfo := GetPropInfo(Comp.ClassInfo, "DataSource");
Result := PropInfo <> nil;
if Result then
if not ((PropInfo^.Proptype^.Kind = tkClass) and
(GetTypeData(PropInfo^.PropType^).ClassType.InheritsFrom(TDataSource))) then
Result := False;
end;
dmtr (2003-10-14 14:44:00) [11]
Да, еще в Uses добавь TypInfo и вместо InheritsForm напиши InheritsFrom
Val (2003-10-14 14:43:00) [12]
да, да, ControlCount, не в этом проблема - как им всем свойство поменять? Ведь это могут быть какие_угодно контролы, как стандартные, так и другие - это формочка, которую я пишу, будет неким предком для других форм проекта, на которой в зависимости от ее состояния (browse,insert,edit) нужно изменять ReadOnly у DBAware Controls.
jack128 (2003-10-14 14:41:00) [13]
> dmtr © (14.10.03 14:38) [7]
уточнение ;-) uses TypInfo;
dmtr (2003-10-14 14:38:00) [14]
function IsDataSource(Comp: TComponent): Boolean;
var
PropInfo: PPropInfo;
begin
PropInfo := GetPropInfo(Comp.ClassInfo, "DataSource");
Result := PropInfo <> nil;
if Result then
if not (PropInfo^.Proptype^.Kind = tkClass) and
(GetTypeData(PropInfo^.PropType^).ClassType.InheritsForm(TDataSource))) then
Result := False;
end;
Vlad (2003-10-14 14:36:00) [15]
Ну и что, у TQuery тоже есть DataSource, хотя он не является контролом.
В любом случае придется цикл писать. Но тогда уж не ComponentCount, а ControlCount. И процедура будет рекурсивной.
Val (2003-10-14 14:29:00) [16]
Danilka © (14.10.03 14:28) [4]
MyComp.FieldAddress("DataSource") <> nil ?
Danilka (2003-10-14 14:28:00) [17]
[2] dmtr © (14.10.03 14:21)
а как узнать, есть ли у компонента MyComp, который является экземпляром класса TMyComp, свойство DataSource или нет?
Val (2003-10-14 14:28:00) [18]
это понятно, я и говорю, что не хочется делать такое приведение для всех DBAware классов - как-то не по-человечески...
Vlad (2003-10-14 14:21:00) [19]
for i:=0 to form1.ComponentsCount-1 do
begin
if Components[i] is TDBEdit then with TDBEdit(Components[i]) do...
if Components[i] is TDBCombobox then with TDBCombobox(Components[i]) do...
....
end;
dmtr (2003-10-14 14:21:00) [20]
Помойму у DB контролов обязательно есть свойство DataSource. Поэтому, пробегись в цикле по всем контролам и у кого есть это свойство, тот тебе и нужен.