Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Problemas con ShellExecute (https://www.clubdelphi.com/foros/showthread.php?t=59745)

ninguno 07-09-2008 06:57:18

Problemas con ShellExecute
 
Hola

Tengo un problema con ShellExecute que no se cómo pillarlo. La cuestión es que tengo que lanzar 2 app externas y posicionarlas en pantalla de forma que se vean las 2. Para hacerlo, lanzo la siguiente función 2 veces, una para cada app:

Código:

HWND __fastcall TStep3::EjecApp(AnsiString aFile,bool Wait)
{
 
bool Exit = false;
 
int MSec = 0;
  HWND aHandle =
0;
  AnsiString aTitle =
"";
 
  ShellExecute(this->Handle,
"open", (TmpDir + aFile).c_str(), NULL, NULL, SW_NORMAL);
 
 
if ( !Wait ) return aHandle;
 
 
do {
    Sleep(
200);
    MSec = MSec +
200;
   
if (MSec >= 2000) Exit = true;
    aHandle = LocatedWindows(aTitle, aPartialTitle);
  }
while ( (aHandle != 0) | Exit );
 
 
return aHandle;
}

aFile contiene el fichero a ejecutar y Wait me indica si tengo que devolver el handle de la ventana principal (en cuyo caso lo busco mediante la función LocatedWindows) o no.

Bien, la cuestión es que si le digo que no necesito handle, ShellExecute funciona siempre, pero si le digo que me lo devuelva (para poder posicionar una ventana lo necesito para la función SetWindowPos) ShellExecute deja de funciuonar hasta reiniciar el programa. Está claro que el error está en esta función, pero no llego a alcanzar a ver el por qué. Os pongo la función:

Código:

HWND __fastcall TStep3::LocatedWindows(AnsiString aTitle)
{
  HWND nHwnd =
0;
  HWND nInitHwnd =
0;
  HWND nCurrWnd =
0;
 
int nLength = 0;
 
char * aTitulo = "";
 
  nHwnd = GetDesktopWindow();
  nInitHwnd = GetWindow( nHwnd, GW_CHILD );
  nCurrWnd = GetWindow( nInitHwnd, GW_HWNDFIRST );
 
while ( nCurrWnd != 0 )
  {
    nLength = GetWindowTextLength(nCurrWnd);
   
if (nLength > 0)
    {
      GetWindowText(nCurrWnd, aTitulo,
255);
     
if ( UpperCase(aTitulo) == UpperCase(aTitle) )
       
return nCurrWnd;
    }
 
    nCurrWnd = GetWindow( nCurrWnd, GW_HWNDNEXT );
  }
 
 
return 0;
}


Alguna idea?

Gracias

cHackAll 08-09-2008 02:13:31

Lo que no comprendo es como puedes llamar a una funcion con 2 argumentos, habiendo sido declarada solo con uno (LocatedWindows)! te dejo un ejemplo un poco distinto y un poco mas "correcto", pues GetWindow te puede retornar el manejador de una insancia anteriormente creada de la misma aplicacion.

Código:

int __stdcall EnumProc(void * hWnd, long lParam)
{
 if (IsWindowVisible(hWnd)) // aquí puedes realizar tu comparación si es el caso
  SetWindowPos(hWnd, HWND_TOPMOST, lParam, 0, 0, 0, SWP_NOSIZE);
 return TRUE;
}
 
void Exec(AnsiString CommandLine, long Left)
{
 STARTUPINFO si = {sizeof si};
 PROCESS_INFORMATION pi;
 CreateProcessA(NULL, CommandLine.c_str(), NULL, NULL, 0, 0, NULL, NULL, &si, &pi);
 WaitForInputIdle(pi.hProcess, INFINITE);
 EnumThreadWindows(pi.dwThreadId, (int (__stdcall *)())EnumProc, Left);
}
 
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 Exec("c:\\windows\\notepad.exe", 0);
 Exec("c:\\windows\\notepad.exe", 500);
}

Saludos

ninguno 08-09-2008 13:17:28

Hola

Cita:

Empezado por cHackAll (Mensaje 312326)
Lo que no comprendo es como puedes llamar a una funcion con 2 argumentos, habiendo sido declarada solo con uno (LocatedWindows)!

jejeje, todo tiene una explicación :)
Me limité a hacer una limpieza de las funciones para quitar el código que no tenía nada que ver con el problema y se me pasó quitar ese parámetro :)

Referente al código que me planteas.....
Si entiendo bien la ayuda del MSDN, EnumThreadWindows te ejecutará una función callback tantas veces como ventanas no-hijas tenga la aplicación lanzada o creada mediante CreateProcessA, ¿es eso correcto?

Y la función WaitForInputIdle espera a que la aplicación lanzada esté totalmente cargada (o al menos la ventana principal), ¿también es esto correcto?

Si es así, tu solución la veo, no se si mejor o peor, pero sí más "limpia"

Gracias por la respuesta

cHackAll 08-09-2008 20:45:38

Cita:

Empezado por ninguno (Mensaje 312370)
...Si entiendo bien la ayuda del MSDN, EnumThreadWindows te ejecutará una función callback tantas veces como ventanas no-hijas tenga la aplicación lanzada o creada mediante CreateProcessA, ¿es eso correcto?...

Si, todas las ventanas padres no así las hijas de los mismos.

Cita:

Empezado por ninguno (Mensaje 312370)
...Y la función WaitForInputIdle espera a que la aplicación lanzada esté totalmente cargada (o al menos la ventana principal), ¿también es esto correcto?

Si

Cita:

Empezado por ninguno (Mensaje 312370)
...Si es así, tu solución la veo, no se si mejor o peor, pero sí más "limpia"

Bueno, si utilizas GetWindow realizarás un enumerado de todas las ventanas
en busca de un texto en su título o su clase, pero pueden existir N instancias de una aplicacion y por ende N ventanas de la misma clase y muy probablemente tambien con el mismo título. Entonces no hay forma de asegurar mediante GetWindow, FindWindow o parecidos, que la instancia encontrada sea la que tu creaste.

Es por ello que uso y aconsejo usar CreateProcess pues retorna los identificacodres del proceso e hilo principal (y en algunas ocaciones ShellExecuteEx pues tambien retorna informacion propia del proceso creado.)

Cita:

Empezado por ninguno (Mensaje 312370)
...Gracias por la respuesta...

You are Welcome :)


La franja horaria es GMT +2. Ahora son las 18:58:23.

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