Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Lazarus, FreePascal, Kylix, etc. (https://www.clubdelphi.com/foros/forumdisplay.php?f=14)
-   -   almacenar forms abiertos en un listbox (https://www.clubdelphi.com/foros/showthread.php?t=91539)

anubis 01-03-2017 06:56:55

almacenar forms abiertos en un listbox
 
Buenas,

quizá sea una pregunta de "perogrullo" pero me estoy matando la cabeza con este tema.

Tengo una aplicacion en la que los forms se abren como show en un panel principal sin problema. Puedo maximizar, minimizar, cerrar etc.
Gracias a este maravilloso foro y su ayuda.

Viendo otros post que preguntan sobre saber que forms estan abiertos, intente implementar eso mismo y cargarlos en un listbox, asi, cuando tuviera algun form "oculto" podria mostrarlo en primer plano.

Pues bien, seguro que es una tonteria pero no hay forma.

Tengo esto

Código Delphi [-]
procedure TPrincipal.tbutton_inventariosClick(Sender: TObject);
begin
  if not assigned(finventarios) then
  begin
  finventarios:=tfinventarios.Create(application);
  finventarios.Parent:=CONTENEDOR;
  finventarios.Show;
   formularios_abiertos;
  end
  else
  begin
   end;
end;

Ahi, lo que hago es preguntar si el formulario ha sido asignado y sino crea uno. Ya cuando lo cierro se libera (para no abrir el mismo 2 veces).
CONTENEDOR es un panel donde lo abro.
formularios_abiertos es donde hago lo siguiente:

Código Delphi [-]
procedure tprincipal.formularios_abiertos;
var
 i:integer;
begin
  listbox1.Clear;
  for i:= Screen.FormCount -1 downto 0 do
    if screen.Forms[i].Showing then
       if (screen.forms[i].Caption<>'Principal') and (screen.forms[i].caption<>'acceso') then
    listbox1.Items.Add(screen.Forms[i].Caption);

Funcionar funciona, porque, si hago click en una de las lineas del listbox me muestra el form, lo unico malo es que los forms estan guardados de forma inversa en el listbox y me muestra el ultimo.
Si, es porque la i va en descendente y el listbox lo guarda en ascendente. Eso lo entiendo

El chiste es que si lo pongo al reves, al seleccionar el ultimo formulario del listbox me acaba tirando un error y no precisamente de index -1.

Tambien intente usar un array para guardar los forms y luego pasarlos al listbox pero es el mismo resultado.

No debe ser complicado pero ....

Gracias.

ecfisa 01-03-2017 09:07:26

Hola.
Cita:

Empezado por anubis (Mensaje 513819)
...
El chiste es que si lo pongo al reves, al seleccionar el ultimo formulario del listbox me acaba tirando un error y no precisamente de index -1.

Usando,
Código Delphi [-]
...
  for i := Screen.FormCount-1 downto 0 do
    if Screen.Forms[i].Showing and ( Screen.Forms[i] <> Self ) then
      ListBox1.Items.Add( Screen.Forms[i].Caption );
...
muestra el título de los formularios por el órden de aparición que previamente se les dé.

¿ Cuál es el código asignado al evento OnClick del ListBox y que mensaje de error te muestra exáctamente ?

Saludos :)

anubis 01-03-2017 16:59:54

Gracias por responder.

El problema viene en el listbox, que los recoge en orden inverso.

Creo el formulario, los recojo en un listbox y ya tengo la lista.

si le doy click a uno de los elementos, lo que hago es:

Código Delphi [-]
showmessage(screen.Forms[listbox1.ItemIndex].caption+' '+inttostr(listbox1.ItemIndex));
 screen.Forms[listbox1.ItemIndex].Show;

Y no corresponde el numero del screen.forms con el nombre almacenado.

roman 01-03-2017 17:26:26

Cita:

Empezado por anubis (Mensaje 513842)
Y no corresponde el numero del screen.forms con el nombre almacenado.

No tendría porqué corresponder. Tu ListBox tiene (por lo menos) dos formularios menos que ScreenForms. Los índices de una lista y la otra van a diferir.

LineComment Saludos

anubis 01-03-2017 17:37:07

Efectivamente amigo roman, por eso se los quite después.
Perdón si los deje en el código, pero estuve haciendo un montón de pruebas sin resultado.
Como comentaba, el recorrido de los forms se hace de mas a menos y en el listbox se añaden de menos a mas, creo que va por ahi la cosa.

Lo que no entiendo es el porqué se hace así con los forms, si lo hago al revés, si funciona relativamente, pero me da un error si elijo la última opción del listbox.

edito: en una de las veces, al pulsar una de las opciones del listbox, me sale frProgressForm en una ventanita y despues mensaje que pone violación de acceso.
Imagino que, el recorrer los forms de ascendente a descendente tenga alguna explicación, porque ahí no hay error, solo que el orden no es el correcto en el listbox

roman 01-03-2017 17:42:11

Y ¿cuál es el error? Creo que aún no lo has dicho.

LineComment Saludos

anubis 01-03-2017 18:53:21

Si, perdón, lo edité después.

Cita:

Edito: en una de las veces, al pulsar una de las opciones del listbox, me sale frProgressForm en una ventanita y despues mensaje que pone violación de acceso.
Imagino que, el recorrer los forms de ascendente a descendente tenga alguna explicación, porque ahí no hay error, solo que el orden no es el correcto en el listbox

ecfisa 01-03-2017 19:37:29

Hola.

Creo que el cargar los punteros a formularios dentro del ListBox te va a simplificar el asunto, te pongo un ejemplo :
Código Delphi [-]
....
uses Unit2, Unit3, Unit4, Unit5;

procedure TForm1.LoadForms;
var
  i : Integer;
begin
  ListBox1.Clear;
  for i := Screen.FormCount-1 downto 0 do
    if Screen.Forms[i] <> Self then
    begin
      Screen.Forms[i].Parent := Panel1;
      Screen.Forms[i].Show;
    end;
  for i := Screen.FormCount-1 downto 0 do
    if Screen.Forms[i].Showing and ( Screen.Forms[i] <> Self ) then
      ListBox1.AddItem( Screen.Forms[i].Caption, Pointer(Screen.Forms[i]) );
  // ListBox1.Sorted := True;  //(opcional)
  Randomize;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  LoadForms;
end;

procedure TForm1.ListBox1Click(Sender: TObject);
const
  COLORS: array[0..3] of TColor = (clRed, clLime, clYellow, clBlue);
var
  i, ix: Integer;
begin
  ix := ListBox1.ItemIndex;    // selección actual
  if ListBox1.ItemIndex <> -1 then
  begin
    // restaurar color en todos los form.
    for i := 0 to ListBox1.Count-1 do
      TForm(ListBox1.Items.Objects[i]).Color := clBtnFace;
   // pintar form seleccionado con su color
    if ix <> -1 then
      TForm(ListBox1.Items.Objects[ix]).Color := Colors[ix];
  end;
end;

procedure TForm1.btnMergeClick(Sender: TObject);
var
  i, x: Integer;
begin
  for i := 0 to ListBox1.Items.Count-1 do
  begin
    x := Random(ListBox1.Items.Count);
    ListBox1.Items.Move(i, x);
  end;
end;

Salida del ejemplo:


De este modo simpre habrá correspondencia entre el nombre mostrado en el ListBox y el objeto sobre el que accionar, espero te sirva.

Saludos :)

ecfisa 01-03-2017 20:00:43

Me olvidaba... para completar el ejemplo, liberar form al azar
Código Delphi [-]
...
procedure TForm1.btnLiberaClick(Sender: TObject);
begin
  TForm(ListBox1.Items.Objects[Random(Screen.FormCount)]).Free;
  LoadForms; // actualizar ListBox
end;

Saludos :)

anubis 02-03-2017 01:24:13

gracias por el detalle ;).

Estaba intentando probar la unit que posteaste y me sale, a la hora de compilar:
Código Delphi [-]
 ListBox1.AddItem( Screen.Forms[i].Caption, Pointer(Screen.Forms[i]));

Cita:

uprincipal.pas(182,75) Error: Incompatible type for arg no. 2: Got "Pointer", expected "TObject"
algo le falta o sobra ;)

roman 02-03-2017 15:44:42

Cita:

Empezado por anubis (Mensaje 513884)
uprincipal.pas(182,75) Error: Incompatible type for arg no. 2: Got "Pointer", expected "TObject"

Le sobra el Pointer.

LineComment Saludos

ecfisa 02-03-2017 18:40:56

Hola.
Cita:

Empezado por anubis (Mensaje 513884)
Cita:

uprincipal.pas(182,75) Error: Incompatible type for arg no. 2: Got "Pointer", expected "TObject"

Rehice la prueba en Lazarus y efectivamente no tolera ese moldeo, Delphi (donde hice el ejemplo) no tiene inconveniente.

Para evitar el error en Lazarus podrías cambiar "Pointer" por "TObject" o, como correctamente apunta roman, quitar directamente el moldeo.

Saludos :)

roman 02-03-2017 19:04:00

Cita:

Empezado por ecfisa (Mensaje 513923)
Rehice la prueba en Lazarus y efectivamente no tolera ese moldeo, Delphi (donde hice el ejemplo) no tiene inconveniente.

De todas formas, el moldeo es innecesario ya que el segundo parámetro de AddItem está declarado como TObject.

LineComment Saludos


La franja horaria es GMT +2. Ahora son las 16:06:13.

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