![]() |
Formas
Hola a todos, les agradeceria me pudieran informar como hago para convertir una variable de tipo string, en la cual tengo el nombre de una forma que debo abrir, y luego abrir dicha forma.
Gracias :confused::confused: Se me olvidaba decirles que la idea es llamar las formas hijas, pues estoy trabajando con MDI. |
Código:
procedure TForm1.Button1Click(Sender: TObject); |
Tienes toda la razon y te agradezco, pero el problema esta en que la variable es de tipo string, viene de un query
NombreForma := QueryNombreForma.AsString; Ahora quiero abrir esta forma que se como se llama porque es el resultado de un query, pero no se como decir que en esa variable esta el nombre de la forma y que esa forma es la que necesito abrir. Gracias de antemano,:confused: :confused: :confused: |
Si el formulario ya está creado entonces basta que busques su nombre en la variable global Forms.
Pero si lo que deseas es crear el formulario a partir de su nombre te recomiendo que en lugar de guardar el nombre del formulario guardes el nombre de la clase del formulario, esto es, en lugar de guardar 'MiForm' guardes 'TMiForm'. Una vez hecho esto puedes obtener la referencia de clase necesaria para poder construir el formulario usando la función GetClass de la unidad Classes.pas: Código:
var Código:
initialization |
Nuevamente, si el formulario ya esta creado, y lo debo llamar desde la forma madre, realmente no se donde se coloca el initialization, perdoneme pero soy algo novata.
var FormaClase : TFormClass; Forma : TForm; begin FormaClase := TFormClass(GetClass(NombreForma)); If FormaClase <> nil then begin Forma:= TFormaClase.Create(Self); Forma.Show; end Esto no me funciona porque me imagino que no he podido saber donde coloco el initialization. Por fis, gracias por la ayuda y recuerden que soy novata :confused: :confused: |
Cita:
Código:
unit nombre de la unidad; |
Hola Marcela, la sección de inicialización es opcional por lo que puede o no formar parte de la Unit, se coloca dentro de bloque de implementación, aquí trascribo lo copiado de la ayuda de Delphi para mas claridad
Código:
implementation |
Lamento molestar tanto, pero hice todo y nada. Auxilio :eek: :confused: :rolleyes:
procedure TMDI…. var Hija: Tform; Str_Forma: String; FormaClase: TFormClass; begin Try : begin Qad_Forma.Close; Qad_Forma.Parameters.ParamByName('Numero').Value := Int_NumeroForma; Qad_Forma.Open; : begin Str_Forma := 'T' + Qad_FormaORES_FORMA.Value; FormaClase := TFormClass(GetClass(Str_Forma)); Hija := TFormaClase.Create(Self); Hija.Show; end; end; : end; Initialization RegisterClass(TFormaClase); Hice todo esto, pero me sale un Error, "no declarado identificador TFormaClase", por fis que estoy haciendo mal si de acuerdo a un filtro en un query, tengo guardada en una tabla el nombre de l forma. |
Cita:
Código:
Hija := TFormaClase.Create(Self); // Saludos |
Hola nuevamente, sale errores, ya no se para donde coger, me va tocar buscar otras alternativas.
esto pasa cuando ejecuta la linea de Initialization RegisterClass(FormaClase); Project Inicial.exe raised exception class EAccessViolation with message 'Access violation at address 0053E4B2 in module "Inicial.exe". Read of address 000002C'. Process stopped. Use Step or Run to continue. El proyecto Inicial.exe ejecuto la clase de la excepción EAccessViolation con el mensaje 'la violación de Acceso a dirección 0053E4B2 en el módulo "Inicial.exe." Lea de dirección 000002C.' El proceso detuvo. Use el Paso o Corra para continuar. si elimino esta linea , entonces el error se ejecuta en la linea: Hija := FormaClase.Create(Self); No se que hacer?, gracias por su colaboración, y perdonen que sea tan cansona. :( |
Yo te recomendaría, ahora que sabes cuál es la sección initialization releer mi primer mensaje en este hilo y tener cuidado con lo que estás escribiendo.
Sé que estás empezando con Delphi y el tema de las referencias de clase no es un tema básico, sin embargo no me queda claro si ya buscaste en la ayuda de Delphi acerca de ello y conviene que le des una leída para que los errores que te aparecen no parezcan tan en chino. Te hago un resumen: Las referencias de clase (en inglés class references) son algo así como meta clases-- Una variable cuyo tipo es una referencia de clase, es una variable cuyos valores son tipos de clases. Considera este caso concreto: Código:
type Aquí, TForm es un tipo de datos, particularmente una clase. Como cualquier otro tipo de datos puedes declarar variables de este tipo: Código:
var Código:
var Así, puedes asignar: FormaClase := TForm1; ya que la clase TForm1 es un descendente de TForm. Observa aquí el punto importante: Una asignación como FormaClase := Forma; donde Forma es como la declarada arriba, no es válida ya que Forma es un objeto de la clase TForm, es decir una variable de tipo TForm, más no es el tipo TForm. ¿Para qué sirven estas referencias de clase? Recuerda cómo se construye un objeto, por ejemplo Forma: Forma := TForm.Create(...); Observa que antes del punto está un tipo de datos, una clase, TForm. Como una referencia de clase toma como valor un tipo de datos puedes sustituir TForm en la asignación anterior por una referencia de clase, cuyo valor sea igual a TForm: Código:
FormaClase := TForm; Forma := FormaClase.Create(...); sin haber antes asignado TForm a FormaClase es como si hicieras nil.Create(...); lo que provoca un error de violación de acceso. Regresando a tú problema específico. El procedimiento RegisterClass toma como parámetro una referencia de clase. Como FormaClase es de tipo referencia de clase el compilador no te marca ningún error. Sin embargo, seguramente FormaClase no ha sido inicializada, es nil, de manera que cuando pones RegisterClass(FormaClase); es como si pusieras RegisterClass(nil); y de ahí la violación de acceso. Ahora bien, cuando tienes un procedimiento, por decir algo, con un parámetro de tipo Integer: Código:
procedure MiProc(I: Integer); Código:
I := 84; MiProc(84); Lo mismo sucede con RegisterClass. En lugar de usar una variable como FormaClase para pasársela cómo parámetro, puedes pasarle directamente el valor que te interesa; en este caso TMiForma (o como quiera que se llame la clase de tu formulario): RegisterClass(TMiForma); // Continúa ... |
Ahora que tienes una noción de las referencias de clases, desmenucemos lo que te escribí en mi primer mensaje de este hilo. Voy a suponer que TMiForma es una de las clase de formularios que te interesa "guardar" en la base de datos".
El primer punto a notar, como lo dije en su momento, es que lo más conveniente es guardar no el nombre del formulario, sino de la clase del formulario ya que este último es el que te sirve para crear dinámicamnete formularios de dicha clase. En otras palabras, en lugar de guardar la cadena "MiForma" en la base de datos, lo que guardas es "TMiForma". Normalmente, para crear un formulario de tipo TMiForma basta que pongas: Código:
var "TMiForma.Create(...)" y pasársela a alguna función de tipo Eval o como quiera que se llame en VB para ejecutar la instrucción. Para suplir esta limitación, Delphi implementa las referencias de clase y crea una tabla que asocia nombres de clases con las clases en sí: Código:
GetClass('TEdit') -> TEdit Entonces, para que GetClass funcione, el nombre de la clase debe estar en dicha tabla, es decir, debe estar registrada. Delphi registra algunas clases automáticamnete pero otras debe uno mismo registrarlas. Ese es el caso de TMiForma y para ello se usa RegisterClass(TMiForma) Este registro puede hacerse en cualquier momento pero para poder crear formularios de tipo TMiForma en cualquier momento lo que conviene es que el registro se haga apenas comience el programa, esto es, en la sección initializatio del formulario. Posteriormente, para crear tus formularios dinámicamente es que usas las referencias de clase. No puedes, como vimos, usar la instrucción Forma := TMiForma.Create(...) pero sí puedes sustituir TMiForma por una referencia de clase: Código:
var GetClass(NombreClase) donde NombreClase es una variable de tipo String cuyo valor es el que obtienes de la consulta SQL. Ahora bien, como GetClass es una función genérica lo que regresa es una referencia de clase para la clase TPersistent que está muy arriba en la jerarquía de clases de Delphi. Esto es así porque GetClass no puede saber qué descendientes habrá. Si tu usas: Código:
var Pero por el momento no te confundas con esta parte y sabe simplemente que debes hacer un "type casting" FormaClase := TFormClass(GetClass(NombreClase)); Con esto ya tienes la referencia de clase que necesitas. Si por alguna razón la clase no quedó registrada entonces GetClass devuelve nil y por ello hay que verificar el valor de regreso: Código:
if FormaClase <> nil then Forma := FormaClase.Create(...); ------------ Yo sé que esto es largo y no para entenderse a la primera pero creo que te puede dar una mejor idea de lo que está pasando y cómo usar correctamente el ejemplo que te dí al mero principio del hilo. Lee esta información sin tratar de digerir todo de un jalón y concrétate al ejemplo del mero principio del hilo. Haz pruebas omitiendo en un principio el uso de las consultas SQL, simplemente registra la clase de un sólo formulario y entiende un código como: Forma := FormaClase('TMiForma'); así, directa la cadena sin variables intermedias. Siguiente paso, registra dos clases de formularios y trata de construir instancias de ellos tomando el nombre de su clase de un Edit. Sólo hasta que estos ejemlos los tengas bien maduros es que intentas hacerlo ya tomando los nombres de la base de datos. Es decir, "paso a pasito" // Saludos |
La franja horaria es GMT +2. Ahora son las 02:26:10. |
Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi