Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   MDIChild (Access Violation), enviar valores entre formularios hijos. (https://www.clubdelphi.com/foros/showthread.php?t=95703)

erikrocha 27-05-2022 04:17:23

MDIChild (Access Violation), enviar valores entre formularios hijos.
 
Hola a todos, luego de estar por algún tiempo navegando entre post y post dentro del foro decidí abrir uno nuevo. Agradezco su tiempo.

Tengo 3 formularios:

Código Delphi [-]
1.main   (MDIForm)
2.pos    (MDIChild)
3.search (MDIChild)

Necesito enviar un valor del 3.frm_search -> 2.frm_pos.

Código Delphi [-]
...
{ desde este formulario frm_search intentando enviar al frm_pos }
uses
  pos;
...
procedure Tfrm_search.button1(Sender: TObject);
begin
  frm_pos.label1.caption := 'abc';
end;

Hice pruebas, si los formularios hijos los tengo autocreados, no hay problemas puedo enviar variables entre ellos. He leído en unos posts del foro que algunos solucionaron así su problema, los ocultaron y luego de acuerdo a sus necesidades los fueron mostrando.

Código Delphi [-]
Auto-create forms
frm_main
frm_pos
frm_search

El problema es cuando creo dinamicamente los formularios hijos, recibo un error: Access Violation

Código Delphi [-]
Auto-create forms:
frm_main

Available forms:
frm_pos
frm_search

...
{ creo mi formulario en tiempo de ejecución }
var
  search: Tfrm_search;
begin
  search := Tfrm_search.create(self);
end;

Un post en el foro explica sobre los formularios modales y su función. Un formulario no debe de escribir directamente a ningun otro formulario. debe de pedir el valor y al cerrarse debe devolver ese valor al formulario que lo solicito. No se como implementarlo. Estaría agradecido si puedieran compartirme un link y/o documentación para poder estudiar más sobre este tema.

Se me ocurre muchos motivos que llevan a mi error; cuando creo un formulario en tiempo de ejecución estoy creando una instancia y cuando quiero enviar el valor al formulario no estoy apuntando correctamente por lo que recibo el error <<Access Violation>>

Gracias.

Neftali [Germán.Estévez] 27-05-2022 09:43:12

Lo más sencillo, creo, es que hagas un pequeño ejemplo donde se reproduzca el error y lo subas, si no es difícil saber en qué punto es el error y cómo solucionarlo.
No creo que sea complicado y seguramente estás accediendo a una variable que no tiene valor o a un objeto que ya has destruído.

También puedes ejecutar el programa paso a paso para detectar en qué punto se produce.

movorack 27-05-2022 18:06:28

¡Hola, Erikrocha!

Como dice Neftalí con algo mas de código puede que sea mas claro lo que expones.

Aún así de lo que nos haz compartido entiendo que el error se presenta al llamar a la instancia global frm_pos desde una instancia local de Tfrm_search, como lo muestras en este código:

Código Delphi [-]
{ creo mi formulario en tiempo de ejecución }
var
  search: Tfrm_search;
begin
  search := Tfrm_search.create(self);
end;


...
{ desde este formulario frm_search intentando enviar al frm_pos }
uses
  pos;
...
procedure Tfrm_search.button1(Sender: TObject);
begin
  frm_pos.label1.caption := 'abc';
end;

Acá la pregunta es. ¿Está disponible frm_pos al momento del llamado en Tfrm_search.button1? Es posible que no! Es probable que lo hayas liberado o que tengas en memoria otra instancia de ese formulario. Ahí es donde debemos ver tu código para ayudarte mejor.

Si solo manejas una única instancia de TFrm_pos, entonces puedes validar que exista antes de usarla o mostrar el formulario de búsqueda. y así no tendrías el error del access violation.

Código Delphi [-]
{ creo el formulario de busqueda en tiempo de ejecución }
var
  search: Tfrm_search;
begin
  //Validas frm_pos  
  if not assigned(frm_pos) then
    Application.createform(frm_pos, TFrm_pos);

  search := Tfrm_search.create(self);  
  search.Show;
end;

escafandra 27-05-2022 19:39:05

Cuando se crean dinámicamente, desconoces los punteros a las ventanas MDIChildren. Es por eso que falla, entonces la estrategia debe ser recorrerlas para encontrar la que te interesa.


Mira a ver si estas pinceladas te dan una idea:
Código Delphi [-]
var
  I: Integer;
begin
  for I := 0 to MDIChildCount-1 do
    if MDIChildren[n].Name = 'Minombre_de_Clase' then
      if MDIChildren[n] is TMyMDMI_Pos then TMyMDMI_Pos(MDIChildren[n]).Label1.Caption:= 'Mensaje';
end;




Saludos.

erikrocha 28-05-2022 00:02:45

1 Archivos Adjunto(s)
Hola Neftali, movorack y escafandra. Gracias por sus respuestas. Tienen razón, entonces aquí les muestro todo el código y también les adjunto los archivos, si lo ejecutan verán el error. Una vez más gracias por su tiempo.

main (MDIForm)

Código Delphi [-]
unit main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  Tfrm_main = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frm_main: Tfrm_main;

implementation

{$R *.dfm}

uses
  pos;

procedure Tfrm_main.Button1Click(Sender: TObject);
var
  pos: Tfrm_pos;
begin
  pos := Tfrm_pos.Create(self);
end;

end.

pos (MDIchild)

Código Delphi [-]
unit pos;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  Tfrm_pos = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frm_pos: Tfrm_pos;

implementation

{$R *.dfm}

uses
  search;

procedure Tfrm_pos.Button1Click(Sender: TObject);
var
  search: Tfrm_search;
begin
  search := Tfrm_search.Create(self);
end;

end.

search (MDIchild)

Código Delphi [-]
unit search;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  Tfrm_search = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frm_search: Tfrm_search;

implementation

{$R *.dfm}

uses
  pos;

procedure Tfrm_search.Button1Click(Sender: TObject);
begin
  frm_pos.Label1.Caption := edit1.Text;
end;

end.

escafandra 28-05-2022 01:14:31

Tal como te proponía y para tu caso en particular:


Código Delphi [-]
procedure Tfrm_search.Button1Click(Sender: TObject);
var
  n: Integer;
begin
  with Application.MainForm do
  for n := 0 to MDIChildCount-1 do
    if MDIChildren[n] is Tfrm_pos then Tfrm_pos(MDIChildren[n]).Label1.Caption:= Edit1.Text;
end;




Saludos.


La franja horaria es GMT +2. Ahora son las 15:54:24.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi