Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 01-04-2014
jplj jplj is offline
Miembro
 
Registrado: oct 2003
Posts: 189
Poder: 21
jplj Va por buen camino
Volver a mostrar una ventana abierta con ShellExecute

Hola

Tengo una aplicación que muestra un digamos "listado de documentos" que el usuario puede abrir con un simple click.
Para "abrir" un documento/fichero, se copia el fichero al directorio temporal del usuario y posteriormente se abre con ShellExecute.
Código Delphi [-]
    ShellExecute(Self.Handle, nil, PChar(tmpFileName),'', '',SW_SHOWNORMAL);

Ahora bien, el usuario sigue trabajando y sigue abirendo, minimizando, ... vamos que llena la pantalla, y más pronto que tarde vuelve a intentar abrir un documento que ya está abierto y "tapado" por muchos otros ...

Lo que yo quería es poder "traer al frente" el documento abierto, y no tener que "abrir" una nueva copia.

Buscando he encontrado la función ShowWindowAsync.

Código Delphi [-]
ShowWindowAsync(HWND_ventana, SW_MAXIMIZE);

Pero hace falta el handle de la ventana que se genera al llamar a ShellExecute.

¿Cómo podría obtener este handle?, y si no es posible ¿de qué otra forma podria hacerlo?


Muchas gracias de antemano.
Un Saludo
__________________
Sonríe. Mañana puede ser peor.
Responder Con Cita
  #2  
Antiguo 01-04-2014
Avatar de nlsgarcia
[nlsgarcia] nlsgarcia is offline
Miembro Premium
 
Registrado: feb 2007
Ubicación: Caracas, Venezuela
Posts: 2.206
Poder: 21
nlsgarcia Tiene un aura espectacularnlsgarcia Tiene un aura espectacular
jplj,

Cita:
Empezado por jplj
...¿de qué otra forma podría hacerlo?...
Pregunto: ¿Has considerado la idea de mostrar el archivo en un TListBox?

Revisa este código:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
begin
   ListBox1.Items.LoadFromFile('FileTest.txt');
end;
El código anterior carga un archivo en disco a un TListBox, la idea también aplica para un TMemo o un TRichEdit y puedes mostrar la información en pantallas separadas si tu aplicación así lo requiere.

Espero sea útil

Nelson.
Responder Con Cita
  #3  
Antiguo 02-04-2014
jplj jplj is offline
Miembro
 
Registrado: oct 2003
Posts: 189
Poder: 21
jplj Va por buen camino
No es posible. Los documentos pueden ser desde una hoja d cálculo a una imagen, pdf, presentación, ...
En principio cualquier tipo de archivo que suela ser empleado para almacenar información.
__________________
Sonríe. Mañana puede ser peor.
Responder Con Cita
  #4  
Antiguo 02-04-2014
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola jplj.

A ver si te sirve de este modo...
Código Delphi [-]
...
implementation
 
// En el ejemplo filtra documentos abiertos con: Block de notas, Adobe Reader y Libre Office. 
// (Agrega o cambia por los que desees)
function EnumWndProc(Handle: HWND; CB: TComboBox): BOOL; stdcall;
var
  Name: array[0..128] of Char;
  s: string;
begin
  Result := True;
  SendMessage(Handle, WM_GETTEXT, Sizeof(Name), integer(@Name));
  SetString(s ,PChar(@Name[0]), Length(Name));
  s:= UpperCase(s);
  if (AnsiPos('.TXT', s) > 0) or (AnsiPos('.PDF', s) > 0) or (AnsiPos('.ODS', s) > 0) then
    CB.Items.AddObject(Name, TObject(Handle));
end;

// Actualizar lista al entrar al combo
procedure TForm1.ComboBox1Enter(Sender: TObject);
begin
  ComboBox1.clear;
  EnumWindows(@EnumWndProc, LPARAM(ComboBox1));
  ComboBox1.ItemIndex:= 0;
end;

// Traer al frente la ventana seleccionada
procedure TForm1.ComboBox1Change(Sender: TObject);
var
  Wnd: HWND;
begin
  with TComboBox(Sender) do
  begin
    Wnd:= FindWindow(nil, PChar(Items[ItemIndex]));
    if Wnd <> 0 then
    begin
      ShowWindow(Wnd, SW_SHOWNORMAL);
      BringWindowToTop(Wnd);
    end;
  end;
end;
...
Del mismo modo podría implementarse mediante un TListBox que se hiciera visible ante el click de un botón y se ocultara luego de la selección.

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....

Última edición por ecfisa fecha: 02-04-2014 a las 02:24:01. Razón: agregar comentario
Responder Con Cita
  #5  
Antiguo 02-04-2014
Avatar de nlsgarcia
[nlsgarcia] nlsgarcia is offline
Miembro Premium
 
Registrado: feb 2007
Ubicación: Caracas, Venezuela
Posts: 2.206
Poder: 21
nlsgarcia Tiene un aura espectacularnlsgarcia Tiene un aura espectacular
jplj,

Cita:
Empezado por jplj
...Volver a mostrar una ventana abierta con ShellExecute..."traer al frente" el documento abierto, y no tener que "abrir" una nueva copia...En principio cualquier tipo de archivo que suela ser empleado para almacenar información...
Revisa este código:
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ShellAPI, ComCtrls, ExtCtrls;

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

const
   FileName : Array[0..3] of String = ('Nelson.txt', 'Nelson.xlsx', 'Nelson.pdf', 'Nelson.jpg');
   FilePrg : Array[0..3] of String = (' - NotePad',
                                      ' - Microsoft Excel',
                                      ' - Adobe Reader',
                                      ' - Windows Photo Viewer');

var
   Form1: TForm1;

implementation

{$R *.dfm}

// Inicializa un TListBox con archivos de Windows
procedure TForm1.FormCreate(Sender: TObject);
var
   i : Integer;
begin
   for i  := Low(FileName) to High(FileName) do
      ListBox1.Items.Add(FileName[i]);
end;

// Abre una sola ventana de un archivo con su aplicación por default en Windows
procedure TForm1.Button1Click(Sender: TObject);
var
  WindowHandle : THandle;
  WindowName : String;

begin

  WindowName := FileName[ListBox1.ItemIndex] + FilePrg[ListBox1.ItemIndex];

  WindowHandle := FindWindow(nil,PChar(WindowName));

  if SetForegroundWindow(WindowHandle) then
     ShowWindow(WindowHandle, SW_SHOWNORMAL)
  else
     ShellExecute(0, nil, PChar(FileName[ListBox1.ItemIndex]),'', '',SW_SHOWNORMAL);

end;

end.
El código anterior en Delphi 7 bajo Windows 7 Professional x32, permite abrir los archivos contenidos en el TListBox con su aplicación por default en Windows por medio de ShellExecute y en caso de ser seleccionados nuevamente colocar la ventana de la aplicación en el tope del Z-Order (Si esta activa) o abrirla nuevamente si esta fue previamente cerrada, en resumen: Se abre una sola ventana por archivo seleccionado.

Nota: Es fundamental que se coloque el nombre correcto de la aplicación (Como aparece en la ventana de la misma), en el formato: " - ApplicationName", si lo anterior no es correcto la aplicación se abrirá tantas veces como sea llamada.

Revisa esta información:
Espero sea útil

Nelson.
Responder Con Cita
  #6  
Antiguo 02-04-2014
jplj jplj is offline
Miembro
 
Registrado: oct 2003
Posts: 189
Poder: 21
jplj Va por buen camino
Muchas gracias por vuestra ayuda ...

Voy a trabajar con las ideas que me habéis proporcionado, y comentaré la solución si la hayo o los problemas que me encuentre.

De todas formas un par de apuntes rápidos:
  • Cuando decía
    Cita:
    ... aplicación que muestra un digamos "listado de documentos" que ...
    Era un simplificación, realmente se muestra una información de los documentos de una forma bastante más compleja.

  • La idea propuesta por nlsgarcia:
    Cita:
    WindowName := FileName[ListBox1.ItemIndex] + FilePrg[ListBox1.ItemIndex];
    WindowHandle := FindWindow(nil,PChar(WindowName));
    Es lo que he intentado pero me encontre que no fuí capaz de averiguar el nombre de la ventana.
    • ¿El standar de título de una ventana es NombreFichero + ' - ' + NombreAplicación?
    • Se presupone que conocemos por anticipado el nombre de la aplicación que abrirá el documento, y en mi caso no es así. ¿Sería posible conocer en tiempo de ejecución cuál es la aplicación predeterminada para abrir un tipo determinado de archivo?, creo que conseguirlo sería la mejor forma solucionar el problema.

Lo dicho, muchas gracias
__________________
Sonríe. Mañana puede ser peor.
Responder Con Cita
  #7  
Antiguo 02-04-2014
jplj jplj is offline
Miembro
 
Registrado: oct 2003
Posts: 189
Poder: 21
jplj Va por buen camino
Repecto a ...

Cita:
◦ ... ¿Sería posible conocer en tiempo de ejecución cuál es la aplicación predeterminada para abrir un tipo determinado de archivo? ...
La solución puede ser FindExecutable function
__________________
Sonríe. Mañana puede ser peor.
Responder Con Cita
  #8  
Antiguo 02-04-2014
Avatar de nlsgarcia
[nlsgarcia] nlsgarcia is offline
Miembro Premium
 
Registrado: feb 2007
Ubicación: Caracas, Venezuela
Posts: 2.206
Poder: 21
nlsgarcia Tiene un aura espectacularnlsgarcia Tiene un aura espectacular
jplj

Cita:
Empezado por jplj
¿El standard de título de una ventana es NombreFichero + ' - ' + NombreAplicación?
Si es correcto

Cita:
Empezado por jplj
¿Sería posible conocer en tiempo de ejecución cuál es la aplicación predeterminada para abrir un tipo determinado de archivo?
Si es posible, sin embargo lo que se requiere en tu caso es el nombre de la ventana en el formato NombreFichero + ' - ' + NombreAplicación, por lo cual el nombre de la aplicación por default (Ejecutable en Disco), no corresponderá necesariamente con el nombre de la aplicación en la ventana de la misma en el formato anteriormente mencionado.

Revisa este código:
Código Delphi [-]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ShellAPI, ComCtrls, ExtCtrls, Registry;

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

const
   FileName : Array[0..3] of String = ('Nelson.txt', 'Nelson.xlsx', 'Nelson.pdf', 'Nelson.jpg');

var
   Form1: TForm1;

implementation

{$R *.dfm}

// Obtiene la lista de Ventanas Activas
function EnumWndProc(Handle: HWND; LP: TStrings): BOOL; stdcall;
var
   WindowName: array[0..128] of Char;
   AuxStr: string;

begin

   Result := True;

   SendMessage(Handle, WM_GETTEXT, Sizeof(WindowName), integer(@WindowName));

   SetString(AuxStr ,PChar(@WindowName[0]), Length(WindowName));

   AuxStr := LowerCase(AuxStr);

   if (AnsiPos('.txt', AuxStr) > 0)
   or (AnsiPos('.xlsx', AuxStr) > 0)
   or (AnsiPos('.pdf', AuxStr) > 0)
   or (AnsiPos('.jpg', AuxStr) > 0)
   then
      LP.Add(WindowName);

end;

// Inicializa un TListBox con archivos de Windows
procedure TForm1.FormCreate(Sender: TObject);
var
   i : Integer;
begin
   for i  := Low(FileName) to High(FileName) do
      ListBox1.Items.Add(FileName[i]);
end;

// Abre una sola ventana de un archivo con su aplicación por default en Windows
procedure TForm1.Button1Click(Sender: TObject);
var
   WindowHandle : THandle;
   WindowName : String;
   ListPrg : TStringList;
   i : Integer;

begin

   ListPrg := TStringList.Create;

   EnumWindows(@EnumWndProc, LPARAM(ListPrg));

   WindowName := EmptyStr;

   for i := 0 to ListPrg.Count - 1 do
      if AnsiPos(FileName[ListBox1.ItemIndex],ListPrg.Strings[i]) > 0 then
      begin
         WindowName := ListPrg[i];
         Break;
      end;

   if WindowName = EmptyStr then
      ShellExecute(0, nil, PChar(FileName[ListBox1.ItemIndex]),'', '',SW_SHOWNORMAL)
   else
   begin
      WindowHandle := FindWindow(nil,PChar(WindowName));

      if SetForegroundWindow(WindowHandle) then
         ShowWindow(WindowHandle, SW_SHOWNORMAL);
   end;

   ListPrg.Free

end;

end.
El código anterior (Versión 2 del código del Msg #5) en Delphi 7 bajo Windows 7 Professional x32, permite abrir de forma automática los archivos contenidos en el TListBox con su aplicación por default en Windows por medio de ShellExecute y en caso de ser seleccionados nuevamente, colocar la ventana de la aplicación en el tope del Z-Order si esta activa por medio de las APIs EnumWindows, FindWindow y SetForegroundWindow o abrirla nuevamente si esta fue previamente cerrada, en resumen: Se abre una sola ventana por archivo seleccionado.

Nota: El nombre de la ventana (Segundo parámetro de la funcion FinWindow), debe estar en el formato "DocumentName - ApplicationName" el cual es obtenido de forma automática por medio de la función EnumWindows.

Revisa esta información:
Espero sea útil

Nelson.

Última edición por nlsgarcia fecha: 02-04-2014 a las 16:49:27.
Responder Con Cita
  #9  
Antiguo 02-04-2014
Avatar de Chris
[Chris] Chris is offline
Miembro Premium
 
Registrado: abr 2007
Ubicación: Jinotepe, Nicaragua
Posts: 1.678
Poder: 18
Chris Va por buen camino
Este es un problema extraño. ShellExecute en su segunda llamada debería activar automáticamente la ventana en la que ya está abierto el documento. Esto puede deverse a un problema en la configuración del registro o un problema con tu código.

Por ejemplo, si abres un documento desde el explorador, la segunda vez que lo intentas abrirlo (haciendo doble-click) te debería activar la ventana previamente creada con el documento.

Intenta modificar tu código colocando el verbo explícitamente. Además pasaremos nil en los parámentros y ruta del archivo (nil != '') y por último el handle del escritorio, normalmente 0.
Código Delphi [-]
ShellExecute(0, 'open', PChar(tmpFileName), nil, nil, SW_SHOW);
__________________
Perfil Github - @chrramirez - Delphi Blog - Blog Web
Responder Con Cita
  #10  
Antiguo 03-04-2014
jplj jplj is offline
Miembro
 
Registrado: oct 2003
Posts: 189
Poder: 21
jplj Va por buen camino
Chris he comprobado lo que me dices, tanto en W7 con en XP abre una nueva ventana. Ocurre lo mismo desde el explorador.

Nelson, exactamente lo que andaba buscando

Muchas gracias por vuestra ayuda.
Juan P.
__________________
Sonríe. Mañana puede ser peor.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Volver a Mostrar los registros de un Dbgrid despues de haber echo una consulta verde_esmeralda PHP 0 20-05-2011 20:03:38
TThread y cerrar una ventana previamente abierta gluglu OOP 1 14-05-2007 20:19:54
Enviar texto a la ventana abierta Mr.Vaka Varios 4 28-11-2005 19:57:31
Volver a mostrar un formulario creado dinámicamente. jplj Varios 2 10-02-2005 14:19:27
abrir .htm en una nueva ventana con shellexecute ruina API de Windows 5 24-06-2004 20:47:54


La franja horaria es GMT +2. Ahora son las 14:09:26.


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
Copyright 1996-2007 Club Delphi