2009-11-12 2 views
2

Как сделать это в Delphi:Как использовать аргумент в гипсе с Delphi

procedure ToggleVisibility(ControlClass : TControlClass); 
var 
    i : integer; 
begin 
    for i := 0 to ComponentCount - 1 do 
    if Components[i] is ControlClass then 
     ControlClass(Components[i]).Visible := not Control(Components[i]).Visible; 
end; 

Компилятор не позволяет бросок в этом случае. Есть идеи?

Я использую Delphi 2007.

+0

Возможный дубликат http://stackoverflow.com/questions/1083087/cast-tobject-using-his-classtype - Я не уверен, потому что я не на 100% уверен, что я понимаю, что вы пытаетесь сделать , –

+2

Почему вы вызываете параметр ComponentClass, но он имеет тип TControlClass? Не следует ли вместо этого параметра указывать ControlClass? –

+0

Джеруэн, ты прав. – Harriv

ответ

2
(Components[i] as ComponentClass).Visible 
+0

Если я правильно понял вопрос, это не сработает, потому что ComponentClass - это метакласс, и вы не можете использовать его с помощью одного из них. Я ответил с большим количеством объяснений - просто подумал, что я должен объяснить нижний план. –

+2

Я ценю объяснение. На самом деле можно использовать типы классов для безопасного литья. Вы можете попробовать код, если не верите мне. – Tihauan

+0

У меня нет Дельфы, где я сейчас, но я возьму ваше слово за это! Я просто попытался отменить нижний план, и он сказал, что он слишком стар - извините:/ –

10

Поскольку компонент является TControl или потомок вы должны бросить в TControl:

procedure ToggleVisibility(ComponentClass : TControlClass); 
var 
    i : integer; 
begin 
    for i := 0 to ComponentCount - 1 do begin 
    if Components[i] is ComponentClass then 
     TControl(Components[i]).Visible := not TControl(Components[i]).Visible; 
    end; 
end; 
+0

Что делать, если вы измените TControlClass на что-то еще позже. Легко забыть о зависимости, которую вы принимаете как предоставленной. – Tihauan

+0

@ Тихуан: Правда. Я не слишком много думал об этом, поскольку считаю, что вся идея ошибочна и никогда не будет писать такую ​​процедуру. Обратите внимание, что он даже не компилируется, поскольку он стоит, как и код в вопросе. – mghie

+0

Не хотите сказать, что если «Компоненты [i] - TControl»? –

1

Попробуйте эту опцию с помощью RTTI

Uses 
TypInfo; 

procedure TForm1.ToggleVisibility(ComponentClass: TClass); 
var 
    i  : integer; 
    PropInfo: PPropInfo; 
    aValue : Variant; 
begin 
    for i := 0 to ComponentCount - 1 do 
    if Components[i] is ComponentClass then 
    begin 
     PropInfo := GetPropInfo(Components[i].ClassInfo, 'Visible'); 
     if Assigned(PropInfo) then 
     begin 
     aValue:=GetPropValue(Components[i], 'Visible'); 
     if PropInfo.PropType^.Kind=tkEnumeration then //All enumerated types. This includes Boolean, ByteBool, WordBool, LongBool and Bool 
     SetOrdProp(Components[i], PropInfo, Longint(not Boolean(aValue))); 
     end; 
    end; 
end; 

Выполнение

ToggleVisibility(TEdit); 
+1

Действительно ли вы уверены, что все свойства 'Visible' на всех возможных компонентах Delphi имеют тип, который можно отличить от' Boolean'? – mghie

+0

@mghie, Хорошо, я просто обновляю код. – RRUZ

+0

@mghie Чтобы изменить тип свойства, вам необходимо переопределить свойство. Но с переоценкой свойства Visible вы можете жадно скрывать/показывать элемент управления, чтобы ваш код, возможно, тоже не работал, как ожидалось. :-) –

2

Не имеет смысла бросать ComponentClass (Components [i]). Видимо, потому что .Visible должен быть определенного класса для правильной компиляции. Поэтому вам нужно указать точный класс, который должен быть отличен. Например, если TControl имеет свойство .Visible, но производный класс создает новый вид свойства .Visible, компилятор не знает, из какого из двух свойств он должен скомпилировать.

Вопрос в том, хотите ли вы инвертировать TControl.Visible, тогда вы должны написать (Components [i] как TControl) .Visible. Наверное, это то, чего ты хочешь.

Если вы хотите инвертировать .Visible любого потомка TControl, независимо от того, относится ли он к видимому или нет элемента управления, и независимо от того, связано ли это с TControl.Visible или нет, тогда вы должны пойти на Решение RTTI, описанное в другом месте.

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