2010-01-12 2 views
0

Я пишу процедуру, чтобы закрыть все созданные и открытые adoquery в (любой) форме, проблема в том, что мне нужно сделать листинг в форме для идентификации компонентов. как я могу сделать динамическое приведение, как показано в примере?Форма динамически

мне нужно что-то вроде этого

Procedure OpenADODataSets(Form:TForm;FormType:TClass); 
... 
... 
(Form as FormType).ComponentCount 

или

Procedure OpenADODataSets(Form:TForm;FormType:TClass); 
... 
... 
FormType(Form).ComponentCount 

это код.

Procedure OpenADODataSets(Form:TForm;FormType:TClass); 
var 
    i: integer; 
begin 

    for i:=0 to (Form as FormType).ComponentCount-1 do 
    if (Form as FormType).Components[i].ClassType=TADOQuery then 
     if not TADOQuery((Form as FormType).Components[i]).Active then 
     TADOQuery((Form as FormType).Components[i]).Open; 

end; 

UPDATE

проблема решается с ответом @Edelcom

Procedure OpenADODataSets(Form:TForm); 
var 
    i: integer; 
begin 

    for i:=0 to Form.ComponentCount-1 do 
    if Form.Components[i].ClassType=TADOQuery then 
     if not TADOQuery(Form.Components[i]).Active then 
     TADOQuery(Form.Components[i]).Open; 

end; 
+0

Зачем вам нужно (форма как FormType)? – Edelcom

+1

Вместо того, чтобы проверять, является ли тип компонента * точно равным * 'TADOQuery', вы должны использовать оператор ** is ** для проверки того, сходит ли компонент * из *' TADOQuery': ', если Form.Components [i] TADOQuery, а не TADOQuery (Form.Components [i]). Active then ... ' –

ответ

2

Почему вам нужна (форма как FormType) (как я заметил). Посмотрел часть моего собственного кода, который работает отлично: цель

procedure TProgSettingsVisual.FillStandardSaveFilesForForm(const pForm: TForm;); 
var i : integer; 
    x : string; 
    thisComponent : TComponent; 
begin 
    With pForm do 
    begin 
     for i := 0 to ComponentCount-1 do 
     begin 
     thisComponent := Components[i]; 

     x := LowerCase(Components[i].ClassName); 


     if x = 'tovcinifilestore' 
     then begin 
      TOvcIniFileStore(Components[i]).IniFileName := FormSaveFile(pForm); 
     end; 

     if x = 'tovdformstate' 
     then begin 
      ... 
     end; 

     if x = 'tovccomponentstate' 
     then begin 
       ... 
+0

+1, каждая форма является потомком TForm, поэтому TForm будет работать нормально, вам не нужно ее бросать. Хотя TDataModule не получается из TForm, поэтому вам может потребоваться обработать его отдельно. –

+1

Нет, J, вам не нужно обрабатывать его отдельно.* Все потомки 'TComponent' имеют необходимые свойства,' ComponentCount', 'Component' и' ClassName'. Не то, чтобы последнее на самом деле было хорошей идеей использовать; используйте оператор ** is ** для проверки типов компонентов, а не сравнения строк. Возможно, что два объекта имеют одно и то же имя класса, но могут быть разных типов. –

1

Приведения типов является рассказать компилятора типа идентификатора, так что он может генерировать правильный код, который использует этот идентификатор. Когда ваш желаемый тип хранится в переменной, компилятор не может выполнять проверку типов. Он не может подтвердить, что значение времени выполнения FormType будет типом, который имеет свойство Components, поэтому он не может скомпилировать код.

Вы не можете вводить тип в тип, если не знаете, что это такое. Если вам нужно это сделать, вы делаете что-то неправильно. Задайте вопрос о том, что вы действительно пытаетесь сделать. (См. Также: «Проблема XY.»)

В вашем случае то, что вы пытаетесь сделать, это написать функцию, которая работает во многих видах форм. Но все свойства, которые вы используете из объекта формы, действительно доступны для всех типов форм, потому что они представлены в TForm или ранее. Фактически, свойства, которые вы используете, представлены в TComponent - все компоненты могут владеть другими компонентами, поэтому все они имеют Components и ComponentCount. Вам не нужно знать, какой конкретный тип имеет форму, потому что ваш код может работать одинаково хорошо с любым типом типа.

procedure OpenADODataSets(Owner: TComponent); 
var 
    i: Integer; 
begin 
    for i := 0 to Owner.ComponentCount - 1 do 
    if Owner.Components[i] is TADOQuery 
     and not TADOQuery(Owner.Components[i]).Active then 
     TADOQuery(Owner.Components[i]).Open; 
end; 

Или даже, как в Delphi 2005:

procedure OpenADODataSets(Owner: TComponent); 
var 
    comp: TComponent; 
begin 
    for comp in Owner do 
    if comp is TADOQuery 
     and not TADOQuery(comp).Active then 
     TADOQuery(comp).Open; 
end; 

Поскольку наборы данных уже проверить, являются ли они активны, прежде чем открывать себя, вы действительно не должны проверить первый:

if comp is TADOQuery then 
    TADOQuery(comp).Open; 
+0

Роб, почему вы проверяете активное состояние AdoQuery в этом коде, прежде чем открывать его ?! Метод Setter для активного свойства уже проверяет, активен ли набор данных или нет, и активирует его только в том случае, если он закрыт. – vcldeveloper

+0

Я основывал свой код на коде в вопросе. Основное внимание в этом вопросе было не на лучший способ открытия запросов, поэтому я решил не изменять эту часть кода, чтобы не отвлекать от этой точки. Кроме того, я не думаю, что вы читали до конца моего ответа, иначе вы бы увидели, что я в конечном счете рассмотрю ту самую проблему, о которой вы меня спрашиваете. –

+0

Да, вы правы, я не читал последнюю строку вашего ответа между двумя кодами кода. Спасибо за разъяснение. – vcldeveloper

Смежные вопросы