Ir al contenido


Foto

Creando Formularios existentes


  • Por favor identifícate para responder
15 respuestas en este tema

#1 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 21 noviembre 2011 - 07:38

Tengo el siguiente procedimiento:



delphi
  1. procedure ShowCatalog(Forma: TForm; TreeItem: TTreeview; Page: TPageControl; TreeIndex,PageIndex: Integer);
  2. begin
  3.   Forma := TForm(Forma).Create(Application);
  4.     try
  5.       TreeItem.Items[TreeIndex].Selected := True;
  6.       Page.ActivePageIndex := PageIndex;
  7.       Forma.ShowModal;
  8.     finally
  9.       Forma.Free;
  10.     end;
  11. end;



Pero al ejecutar me manda una ejecucion, y es cuando intento crear el formulario, su uso es el siguiente, suponiendo que tengo un formlario llamado FCatalogo:



delphi
  1. ShowCatalog(FCatalogo, FCatalogo.Treeview1,FCatalogo.PageControl1,2,2);



Saludos.
  • 0

#2 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 21 noviembre 2011 - 08:31

Buenas,

Creo que lo que deberías de pasar por parámetro no es el formulario, sino la clase de éste. Algo así:



delphi
  1. procedure ShowCatalog(FormClass: TFormClass; TreeItem: TTreeview; Page: TPageControl; TreeIndex,PageIndex: Integer);
  2. var
  3.   Forma: TForm;
  4. begin
  5.   Forma := FormClass.Create(Application);
  6.     try
  7.       TreeItem.Items[TreeIndex].Selected := True;
  8.       Page.ActivePageIndex := PageIndex;
  9.       Forma.ShowModal;
  10.     finally
  11.       Forma.Free;
  12.     end;
  13. end;



A parte de eso, estas pasando por parámetro un TTreeview y un TPageControl que aun no han sido creados dado que pertenecen a un formulario aun no creado, por lo que estás pasando un nil.

No lo he probado, pero la idea debería de ser esa ;-)

Nos leemos

  • 0

#3 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 21 noviembre 2011 - 08:36

Hola Fernando,
¿Cuál es el error que te aparece?


Si la idea es comprobar antes si existe debes disponer de las variables para cada uno, o bien recorrer la propiedad Forms[] para determinar si existe la ventana abierta gracias a Assigned y en caso negativo recién crear.
Otro motivo de posibles problemas está en el hecho de que si defines un dueño al momento de crear un form no deberías liberarlo. Precisamente esa es la idea del dueño.


Si tu quieres liberar los forms una ves presentados recomiendo que no le asignes dueño:




delphi
  1. Forma := TForma.Create(nil);




Y aquí aprovecho para hacer un paréntesis. Si bien es legal hacer:




delphi
  1. Forma := TForm(Forma).Create();




Y aparentemente funciona, recuerda que estás haciendo un cast hacia una clase base. Por defecto cuando creamos un form, Delphi genera una nueva clase por cada uno: Form1 -> TForm1, Form2 -> TForm2, etc... Debería ser la propia de la propia clase y tipo al momento de crear.


Puedes hacer uso de las referencias de clases:




delphi
  1. type
  2. TFormClass = class of TForm;
  3.  
  4.  
  5. var
  6.   miFormClass: TFormClass;
  7.   form: TForm;
  8.  
  9.  
  10. begin
  11.   miFormClass := TFormClass(Forma);
  12.   Forma := miFormClass.Create(nil);  // O Application si es el caso
  13. end;




De este modo te garantizas de que se haga uso del constructor y tipo adecuado y como extra no hay moldeo.


Saludos,
  • 0

#4 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 21 noviembre 2011 - 08:49

Hola a ambos y gracias por su respuestas, aplicando sus consejos no me funcionaron, pero, me parece que los tiros vienen como dice Cadetill, estoy llamando a componentes que aun no existen aunque esten ahi, dejame como re-estructuro ese codigo.


Saludos.
  • 0

#5 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 21 noviembre 2011 - 09:17

Bueno, yo aqui me ando complicando mas de la cuenta :D



delphi
  1. procedure ShowCatalog(Forma: TForm; TreeName,PageName: String; TreeIndex,PageIndex: Integer);
  2. var idx: Integer;
  3. begin
  4.   Forma := TForm(Forma).Create(Application);
  5.     try
  6.       for idx := 0 to Forma.ComponentCount - 1 do begin
  7.         if (Forma.Components[idx] is TTreeView) And
  8.           (Forma.Components[idx].Name = TreeName) then
  9.               TTreeView(Forma.Components[idx]).Items[TreeIndex].Selected := True
  10.         else if (Forma.Components[idx] is TPageControl) And
  11.                 (Forma.Components[idx].Name = PageName)  then
  12.               TPageControl(Forma.Components[idx]).ActivePageIndex := PageIndex;
  13.       end;
  14.       Forma.ShowModal;
  15.     finally
  16.       Forma.Free;
  17.     end;
  18. end;



Resultado:



delphi
  1. ---------------------------
  2. Cobros
  3. ---------------------------
  4. Access violation at address 005874E9 in module 'Cobros.exe'. Read of address 00000000.
  5. ---------------------------
  6. Aceptar 
  7. ---------------------------


  • 0

#6 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 21 noviembre 2011 - 09:58

Buenas,

El AV te lo da en esta linea, verdad?



delphi
  1. Forma := TForm(Forma).Create(Application);



Es debido a lo mismo de antes, Forma no es una clase, es un objeto y que aun no está creado, por lo que no puedes realizar el casting

Prueba como te he dicho antes



delphi
  1. procedure ShowCatalog(FormClass: TFormClass; TreeName,PageName: String; TreeIndex,PageIndex: Integer);
  2. var
  3.   Forma: TForm;
  4.   idx: Integer;
  5. begin
  6.   Forma := FormClass.Create(Application);
  7.   try
  8.     for idx := 0 to Forma.ComponentCount - 1 do begin
  9.       if (Forma.Components[idx] is TTreeView) And
  10.         (Forma.Components[idx].Name = TreeName) then
  11.         TTreeView(Forma.Components[idx]).Items[TreeIndex].Selected := True
  12.       else if (Forma.Components[idx] is TPageControl) And
  13.                 (Forma.Components[idx].Name = PageName)  then
  14.               TPageControl(Forma.Components[idx]).ActivePageIndex := PageIndex;
  15.     end;
  16.     Forma.ShowModal;
  17.   finally
  18.     FreeAndNil(Forma);
  19.   end;
  20. end;



Ejemplo de llamada..



delphi
  1. ShowCatalog(TCatalogo, '', '', 0, 0);



Nos leemos
  • 0

#7 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 21 noviembre 2011 - 10:03



delphi
  1. [DCC Error] Funciones.pas(188): E2010 Incompatible types: 'TFormClass' and 'TForm'




:
  • 0

#8 andres1569

andres1569

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 431 mensajes

Escrito 21 noviembre 2011 - 12:35

Hola,

como ha dicho Cadetill al principio, debes crear el formulario a partir de una clase, en tu caso de la clase del formulario que sirve de patrón o maestro. Esta clase la puedes tomar directamente del mismo formulario que pasas como parámetro, así que con la misma declaración que pusiste al principio del hilo serviría, cambiando la sentencia donde creas el formulario "clonado".

Pero veo también ahí un error en que pasas un parámetro, Forma, que utilizas luego para que apunte al nuevo formulario creado, y deberían ser dos diferentes: el parámetro Forma apuntando al formulario que sirve de patrón, y dentro de la función NewForma que debe apuntar al nuevo formulario que vamos a crear:




delphi
  1. procedure ShowCatalog(Forma: TForm; TreeName,PageName: String; TreeIndex,PageIndex: Integer);
  2. var
  3.   NewForma : TForm; 
  4.   idx: Integer;
  5. begin
  6.   NewForma := TFormClass(Forma.ClassType).Create(Application);
  7.   try
  8.     for idx := 0 to NewForma.ComponentCount - 1 do begin
  9.       if (NewForma.Components[idx] is TTreeView) And
  10.         (NewForma.Components[idx].Name = TreeName) then
  11.             TTreeView(NewForma.Components[idx]).Items[TreeIndex].Selected := True
  12.       else if (NewForma.Components[idx] is TPageControl) And
  13.               (NewForma.Components[idx].Name = PageName)  then
  14.             TPageControl(NewForma.Components[idx]).ActivePageIndex := PageIndex;
  15.     end;
  16.     NewForma.ShowModal;
  17.   finally
  18.     NewForma.Free;
  19.   end;
  20. end;



  • 0

#9 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 21 noviembre 2011 - 05:14

Yo cambiaría un poco el diseño a algo mas flexible, algo así:




delphi
  1. unit UBase;
  2.  
  3.  
  4. interface
  5.  
  6.  
  7. uses
  8.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  9.   Dialogs, ComCtrls;
  10.  
  11.  
  12. type
  13.   TBase = class(TForm)
  14.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  15.     procedure FormShow(Sender: TObject);
  16.   protected
  17.     FTreeView: String;
  18.     FPageControl: string;
  19.     FTreeIndex: Integer;
  20.     FPageIndex: Integer;
  21.   public
  22.     class function Ejecutar(TreeName, PageName: String;
  23.       TreeIndex, PageIndex: Integer; AOwner: TComponent = nil): TModalResult;
  24.   end;
  25.  
  26.  
  27. implementation
  28.  
  29.  
  30. {$R *.dfm}
  31. { TBase }
  32.  
  33.  
  34. class function TBase.Ejecutar(TreeName, PageName: String;
  35.   TreeIndex, PageIndex: Integer; AOwner: TComponent): TModalResult;
  36.  
  37.  
  38. begin
  39.   if AOwner = nil then
  40.     AOwner := Application.MainForm;
  41.   with Create(AOwner) do
  42.     try
  43.       FTreeView := TreeName;
  44.       FPageControl := PageName;
  45.       FTreeIndex := TreeIndex;
  46.       FPageIndex := PageIndex;
  47.       Result := ShowModal;
  48.     finally
  49.       Free;
  50.     end;
  51. end;
  52.  
  53.  
  54. procedure TBase.FormClose(Sender: TObject; var Action: TCloseAction);
  55. begin
  56.   Action := caFree;
  57. end;
  58.  
  59.  
  60. procedure TBase.FormShow(Sender: TObject);
  61. var
  62.   idx: Integer;
  63. begin
  64.   for idx := 0 to Self.ComponentCount - 1 do
  65.   begin
  66.     if (Self.Components[idx] is TTreeView) And
  67.       (Self.Components[idx].Name = FTreeView) then
  68.       TTreeView(Self.Components[idx]).Items[FTreeIndex].Selected := True
  69.     else if (Self.Components[idx] is TPageControl) And
  70.       (Self.Components[idx].Name = FPageControl) then
  71.       TPageControl(Self.Components[idx]).ActivePageIndex := FPageIndex;
  72.   end;
  73. end;
  74.  
  75.  
  76. end.




Y llamaría a los forms heredados de TBase así:




delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   TDescendiente.Ejecutar('Tu tree view', 'Tu PageName', 'tu treeIndex', 'Tu pageIndex');
  4. end;
  5.  
  6.  
  7. //o así
  8.  
  9.  
  10. procedure TForm1.Button2Click(Sender: TObject);
  11. begin
  12.   if TDescendiente.Ejecutar('Tu tree view', 'Tu PageName', 'tu treeIndex',
  13.     'Tu pageIndex') = mrOk then
  14.     // Hacer cosas
  15.   else
  16.     // Hacer otras cosas
  17.   end;
  18.  
  19.  
  20. end.




Saludos.
  • 0

#10 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 22 noviembre 2011 - 07:30

@andres:




delphi
  1. ---------------------------
  2. Debugger Exception Notification
  3. ---------------------------
  4. Project Cobros.exe raised exception class EAccessViolation with message 'Access violation at address 00403E78 in module 'Cobros.exe'. Read of address 00000000'.
  5. ---------------------------
  6. Break  Continue  Help 
  7. ---------------------------


  • 0

#11 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 22 noviembre 2011 - 07:41

Pon el código que te da esa excepción, porque (al menos el que yo puse) lo probé antes de ponerlo y me funcionaba correctamente

Nos leemos
  • 0

#12 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 22 noviembre 2011 - 07:46

Pon el código que te da esa excepción, porque (al menos el que yo puse) lo probé antes de ponerlo y me funcionaba correctamente

Nos leemos



Pues es tal como lo coloca Andres:




delphi
  1. //Procedimiento que maneja el formulario de Catalogo
  2. //Asi me evito demasiadas lineas en cada menu
  3. procedure ShowCatalog(Forma: TForm; TreeName,PageName: String; TreeIndex,PageIndex: Integer);
  4. var
  5.   NewForm: TForm;
  6.   idx: Integer;
  7. begin
  8.   NewForm := TFormClass(Forma.ClassType).Create(Application);
  9.     try
  10.       for idx := 0 to NewForm.ComponentCount - 1 do begin
  11.         if (NewForm.Components[idx] is TTreeView) And
  12.           (NewForm.Components[idx].Name = TreeName) then
  13.               TTreeView(NewForm.Components[idx]).Items[TreeIndex].Selected := True
  14.         else if (NewForm.Components[idx] is TPageControl) And
  15.                 (NewForm.Components[idx].Name = PageName)  then
  16.               TPageControl(NewForm.Components[idx]).ActivePageIndex := PageIndex;
  17.       end;
  18.       NewForm.ShowModal;
  19.     finally
  20.       NewForm.Free;
  21.     end;
  22. end;



El objetivo de ese codigo, es para ahorrarme la cantidad de lineas en mi proyecto, imaginense colocar este codigo en 10 menus diferentes:



delphi
  1. procedure TFMain.UsuariosdelSistema1Click(Sender: TObject);
  2. begin
  3.   FCatalogo := TFCatalogo.Create(Self);
  4.     try
  5.       FCatalogo.lbCatInfo.Caption := 'Usuarios del Sistema';   
  6.       FCatalogo.trCatMenu.Items[3].Selected := True;
  7.       UnTab(FCatalogo.pcCatalogo,3);
  8.       FCatalogo.ShowModal;
  9.     finally
  10.       FCatalogo.Free;
  11.     end;
  12. end;



:| asi que ando buscando casi un 90% de ahorro en lineas :p
  • 0

#13 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 22 noviembre 2011 - 09:10

Buenas,

Sigo diciendo lo mismo, el obejto Forma no está creado, por lo que no puedes acceder a su propiedad ClassType, de ahí que te salte el AV.

Prueba a hacerlo de la forma que te indiqué más arriba.

Además, puedes evitar el bucle haciendo algo así que creo queda más "limpio"



delphi
  1. procedure ShowCatalog(FormClass: TFormClass; TreeName,PageName: String; TreeIndex,PageIndex: Integer);
  2. var
  3.   Forma: TForm;
  4.   Comp: TComponent;
  5. begin
  6.   Forma := FormClass.Create(Application);
  7.   try
  8.     Comp := Forma.FindComponent(TreeName);
  9.     if Comp is TTreeView then
  10.       TTreeView(Comp).Items[TreeIndex].Selected := True;
  11.     Comp := Forma.FindComponent(PageName);
  12.     if Comp is TPageControl then
  13.       TPageControl(Comp).ActivePageIndex := PageIndex;
  14.     Forma.ShowModal;
  15.   finally
  16.     FreeAndNil(Forma);
  17.   end;
  18. end;
  19.  
  20. procedure TForm1.Button1Click(Sender: TObject);
  21. begin
  22.   ShowCatalog(TForm2, '', '', 0, 0);
  23. end;



Nos leemos
  • 0

#14 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 22 noviembre 2011 - 09:46



delphi
  1. ---------------------------
  2. Debugger Exception Notification
  3. ---------------------------
  4. Project Cobros.exe raised exception class EAccessViolation with message 'Access violation at address 0042900C in module 'Cobros.exe'. Read of address 00000010'.
  5. ---------------------------
  6. Break  Continue  Help 
  7. ---------------------------




Lo raro que al ignorar el error si me abre el formulario, y al hacer un break me marca en




delphi
  1. Forma.ShowModal:



  • 0

#15 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 22 noviembre 2011 - 10:47

Si haces un debug (breakpoint en la 1era linea del procedimiento) en qué linea te salta el error? Porque he probado el código y me funciona bien

Nos leemos

  • 0

#16 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 22 noviembre 2011 - 11:57

El código de Cadetill debería funcionar bien, pienso que el AV  podría ocurrir si pasas como parámetro un índice inexistente ante todo para el TPageControl.

Saludos
  • 0




IP.Board spam blocked by CleanTalk.