2009-07-04 11 views
5

¿Cómo puedo hacer que mi código funcione? :) He tratado de formular esta pregunta, pero después de varios intentos fallidos, creo que ustedes detectarán el problema más rápido mirando el código que leyendo mis 'explicaciones'. gracias.lanzan TObject usando su ClassType?

setCtrlState([ memo1, edit1, button1], False); 

_

procedure setCtrlState(objs: array of TObject; bState: boolean = True); 
var 
    obj: TObject; 
    ct: TClass; 
begin 
    for obj in objs do 
    begin 
    ct := obj.ClassType; 


    if (ct = TMemo) or (ct = TEdit) then 
     ct(obj).ReadOnly := not bState;  // error here :(

    if ct = TButton then 
     ct(obj).Enabled:= bState;  // and here :(

    end; 
end; 

Respuesta

5

Sería más fácil de usar RTTI en lugar de conversión explícita, es decir:

uses 
    TypInfo; 

setCtrlState([ memo1, edit1, button1], False); 

procedure setCtrlState(objs: array of TObject; bState: boolean = True); 
var 
    obj: TObject; 
    PropInfo: PPropInfo; 
begin 
    for obj in objs do 
    begin 
    PropInfo := GetPropInfo(obj, 'ReadOnly'); 
    if PropInfo <> nil then SetOrdProp(obj, PropInfo, not bState); 

    PropInfo := GetPropInfo(obj, 'Enabled'); 
    if PropInfo <> nil then SetOrdProp(obj, PropInfo, bState); 
    end; 
end; 
+0

esto es * exactamente * lo que estaba buscando. ¡Gracias! –

4

, es necesario especificar el objeto ct a un TMemo/TEdit/TButton antes de poder establecer las propiedades del objeto.

La línea donde se obtienen los errores se está equivocando porque ct sigue siendo un TClass, no un TButton/etc. Si lanzas a un TButton, podrás establecer habilitado en verdadero.

Recomiendo leer en casting in Delphi. Personalmente, recomendaría usar los operadores as/es en lugar de usar ClassType, también. El código será más simple en ese caso, y mucho más comprensible.


En lo personal, me gustaría escribir esto más como:

procedure setCtrlState(objs: array of TObject; bState: boolean = True); 
var 
    obj: TObject; 
begin 
    for obj in objs do 
    begin 
    // I believe these could be merged by using an ancestor of TMemo+TEdit (TControl?) 
    // but I don't have a good delphi reference handy 
    if (obj is TMemo) then 
     TMemo(obj).ReadOnly := not bState; 

    if (obj is TEdit) then 
     TEdit(obj).ReadOnly := not bState; 

    if (obj is TButton) then 
     TButton(obj).Enabled := bState; 
    end; 
end; 
7

Debe convertir explícitamente objeto de alguna clase. Esto debería funcionar:

procedure setCtrlState(objs: array of TObject; bState: boolean = True); 
var 
    obj: TObject; 
    ct: TClass; 
begin 
    for obj in objs do 
    begin 
    ct := obj.ClassType; 

    if ct = TMemo then 
     TMemo(obj).ReadOnly := not bState 
    else if ct = TEdit then 
     TEdit(obj).ReadOnly := not bState 
    else if ct = TButton then 
     TButton(obj).Enabled := bState; 
    end; 
end; 

Esto se puede acortar usando "is" operador - no es necesario para la variable ct:

procedure setCtrlState(objs: array of TObject; bState: boolean = True); 
var 
    obj: TObject; 
begin 
    for obj in objs do 
    begin 
    if obj is TMemo then 
     TMemo(obj).ReadOnly := not bState 
    else if obj is TEdit then 
     TEdit(obj).ReadOnly := not bState 
    else if obj is TButton then 
     TButton(obj).Enabled := bState; 
    end; 
end; 
+0

No debería segundo encasillado en cada caso fuera "TEdit" en lugar de "TMemo"? – Argalatyr

+0

+0.5 por decir que tiene que realizar moldes para cada tipo. +0.5 para usar "es" –

+0

arreglé el error tipográfico mencionado por Argalatyr –

3

No hay necesidad de echar a TMemo y TEdit por separado, ya que son ambos descendientes de la clase padre común, que tienen la propiedad de sólo lectura:

procedure TForm1.FormCreate(Sender: TObject); 

    procedure P(const Obj: TComponent); 
    begin 
    if Obj is TCustomEdit then 
     TCustomEdit(Obj).ReadOnly := True; 
    end; 

begin 
    P(Memo1); 
    P(Edit1); 
end; 
2

puede evitar hacer referencia a diferentes unidades y la conversión explícita si no importa un pequeño golpe de rendimiento y limita los cambios a las propiedades publicadas. Eche un vistazo a la unidad TypInfo incluida con Delphi.

Cuestiones relacionadas