Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > API de Windows
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 05-01-2020
MaxiDucoli MaxiDucoli is offline
Miembro
 
Registrado: feb 2006
Posts: 134
Poder: 19
MaxiDucoli Va por buen camino
Optimizar código

Hola, buenas tardes.
Aprovecho que hay un gurú que sabe bocha de WinApi y quería preguntar lo siguiente:

Tengo este código insertado en un Timer dentro de un formulario que se ejecuta como "Loading Screen" mientras se carga un emulador de fondo.
Una vez que abrió el emulador el código busca el Caption del mismo y lo trae al frente y luego se cierra.
Hay alguna manera de optimizar el código este o sí o sí se tiene que hacer de una manera como esta?

Se pueden buscar los exe en ejecución y terminarlos directamente? Eso sería de mucha ayuda para el programa principal así puedo cerrar los emuladores al presionar ESCAPE (que ya me solucionaron como hacerlo, pero lo hago algo "Sucio" y a veces falla).

Les dejo el código y muchas gracias de ante mano!!!!


Código Delphi [-]
unit close;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, jpeg, pngimage, Vcl.Forms,TLHelp32, Vcl.Dialogs, JvBackgrounds, Vcl.ExtCtrls;

type
  TFrmLaunchIMG = class(TForm)
    JvBackground1: TJvBackground;
    TmrClose: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure TmrCloseTimer(Sender: TObject);

  private
    { Private declarations }

  public
    { Public declarations }
  end;

var
  FrmLaunchIMG: TFrmLaunchIMG;
  Contador : integer;
  Win2 : HWND;
  Mensaje : String;

implementation

{$R *.dfm}



function FindWindowExtd(partialTitle: string): HWND;
var
  hWndTemp: hWnd;
  iLenText: Integer;
  cTitletemp: array [0..254] of Char;
  sTitleTemp: string;
begin
  hWndTemp := FindWindow(nil, nil);
  while hWndTemp <> 0 do begin
    iLenText := GetWindowText(hWndTemp, cTitletemp, 255);
    sTitleTemp := cTitletemp;
    sTitleTemp := UpperCase(copy( sTitleTemp, 1, iLenText));
    partialTitle := UpperCase(partialTitle);
    if pos( partialTitle, sTitleTemp ) <> 0 then
      Break;
    hWndTemp := GetWindow(hWndTemp, GW_HWNDNEXT);
  end;
  result := hWndTemp;
end;

procedure TFrmLaunchIMG.FormCreate(Sender: TObject);
begin
FrmLaunchIMG.Height := Screen.Height;
FrmLaunchIMG.Width := Screen.Width;
JVBackGround1.Image.Picture.LoadFromFile(ParamStr(1));
Contador := 0;
end;

procedure TFrmLaunchIMG.TmrCloseTimer(Sender: TObject);
begin
SetWindowPos(FrmLaunchIMG.Handle, HWND_TOPMOST, 0, 0, 0, 0,
                 SWP_NoMove or SWP_NoSize);
 inc(Contador);

 if Contador > 5 then Contador := 0;


      if Contador = 5 then
      Begin

            Win2 :=  FindWindowExtd('RetroArch');
            if IsWindow(Win2) then
            begin
                Sleep(200);
                //SetForegroundWindow(Win2);
                SetWindowPos(Win2, HWND_TOPMOST, 0, 0, 0, 0,
                SWP_NoMove or SWP_NoSize);
                application.Terminate;
            end;

            Win2 :=  FindWindowExtd('PPSSPP ');
            if IsWindow(Win2) then
            begin
                Sleep(200);
                //SetForegroundWindow(Win2);
                SetWindowPos(Win2, HWND_TOPMOST, 0, 0, 0, 0,
                SWP_NoMove or SWP_NoSize);
                application.Terminate;
            end;

            Win2 :=  FindWindowExtd('Slot');
            if IsWindow(Win2) then
            begin
                Sleep(200);
                //SetForegroundWindow(Win2);
                SetWindowPos(Win2, HWND_TOPMOST, 0, 0, 0, 0,
                SWP_NoMove or SWP_NoSize);
                application.Terminate;
            end;

            Win2 :=  FindWindowExtd('Cemu');
            if IsWindow(Win2) then
            begin
                Sleep(200);
                //SetForegroundWindow(Win2);
                SetWindowPos(Win2, HWND_TOPMOST, 0, 0, 0, 0,
                SWP_NoMove or SWP_NoSize);
                application.Terminate;
            end;

            Win2 :=  FindWindowExtd('Redream');
            if IsWindow(Win2) then
            begin
                Sleep(200);
                //SetForegroundWindow(Win2);
                SetWindowPos(Win2, HWND_TOPMOST, 0, 0, 0, 0,
                SWP_NoMove or SWP_NoSize);
                application.Terminate;
            end;

            Win2 :=  FindWindowExtd('FS-UAE');
            if IsWindow(Win2) then
            begin
                Sleep(200);
                //SetForegroundWindow(Win2);
                SetWindowPos(Win2, HWND_TOPMOST, 0, 0, 0, 0,
                SWP_NoMove or SWP_NoSize);
                application.Terminate;
            end;

            Win2 :=  FindWindowExtd('Future');
            if IsWindow(Win2) then
            begin
                Sleep(200);
                //SetForegroundWindow(Win2);
                SetWindowPos(Win2, HWND_TOPMOST, 0, 0, 0, 0,
                SWP_NoMove or SWP_NoSize);
                application.Terminate;
            end;

            Win2 :=  FindWindowExtd('MAME');
            if IsWindow(Win2) then
            begin
                Sleep(200);
                //SetForegroundWindow(Win2);
                SetWindowPos(Win2, HWND_TOPMOST, 0, 0, 0, 0,
                SWP_NoMove or SWP_NoSize);
                application.Terminate;
            end;

            Win2 :=  FindWindowExtd('scummvm');
            if IsWindow(Win2) then
            begin
                Sleep(200);
                //SetForegroundWindow(Win2);
                SetWindowPos(Win2, HWND_TOPMOST, 0, 0, 0, 0,
                SWP_NoMove or SWP_NoSize);
                application.Terminate;
            end;

            Win2 :=  FindWindowExtd('Dolphin');
            if IsWindow(Win2) then
            begin
                Sleep(200);
                //SetForegroundWindow(Win2);
                SetWindowPos(Win2, HWND_TOPMOST, 0, 0, 0, 0,
                SWP_NoMove or SWP_NoSize);
                application.Terminate;
            end;

            Win2 :=  FindWindowExtd('WINGAMES');
            if IsWindow(Win2) then
            begin
                Sleep(200);
                //SetForegroundWindow(Win2);
                SetWindowPos(Win2, HWND_TOPMOST, 0, 0, 0, 0,
                SWP_NoMove or SWP_NoSize);
                application.Terminate;
            end;

            Win2 :=  FindWindowExtd('DAPHNE');
            if IsWindow(Win2) then
            begin
                Sleep(200);
                //SetForegroundWindow(Win2);
                SetWindowPos(Win2, HWND_TOPMOST, 0, 0, 0, 0,
                SWP_NoMove or SWP_NoSize);
                application.Terminate;
            end;
      End;
end;



end.
Responder Con Cita
  #2  
Antiguo 06-01-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
No termino de entender con precisión lo que pretendes. ¿Quieres abrir un proceso, esperar a que esté abierto y entonces ponerlo en primer plano y tras esto cerrar la aplicación que lo abrió?


SI es esto lo que pretendes, yo utilizaría un createprocess que esperaría que se abra, localizaría el handle de la ventana del proceso abierto para ponerlo en primer plano y luego me termino tranquilamente.


Para localizar el handle de la ventana no usaría FindWindow, existe una forma mejor. Puesto que conocemos el hProcess del proceso hijo, conocemos su ProcessID. Con esto en la mano, enumeramos las ventanas hasta encontrar una que tenga ese ProcessID y nos quedamos con su Handle para ponerla en primer plano.


Código Delphi [-]

// Importamos GetProcessId si nuestro delphi no la tiene

function GetProcessId(hProcess: THANDLE): DWORD; stdcall;  external  Kernel32;



........................


implementation


//------------------------------------------------------------------------------
// Enumeramos las ventanas para encontrar la que tenga el PId buscado.
function GetWindowFromPId(PId: DWORD): THandle;
type
  TWinParam = record
    Handle: THandle;
    PId: DWORD;
  end;
  PWinParam = ^TWinParam;
var
  WinParam: TWinParam;

  function EnumWindowsProc(Handle: Thandle; lParam: LPARAM): BOOL; stdcall;
  var
    PId: DWORD;
  begin
    Result:= true;
    PId:= 0;
    GetWindowThreadProcessId(Handle, PId);
    if PWinParam(lParam).PId = PId then
    begin
      PWinParam(lParam).Handle:= Handle;
      Result:= false;
    end;
  end;

begin
  WinParam.Handle:= 0;
  WinParam.PId:= PId;
  EnumWindows(@EnumWindowsProc, LPARAM(@WinParam));
  repeat
    Result:= WinParam.Handle;
    WinParam.Handle:= Windows.GetParent(Result);
  until WinParam.Handle = 0;
end;

//------------------------------------------------------------------------------
// Creamos un proceso.
function Execute(CommandLine: String): THandle;
var
  SI: TStartupInfo;
  PI: TProcessInformation;
begin
  ZeroMemory(@SI, sizeof(TStartupInfo));
  SI.cb:= sizeof(SI);
  SI.dwFlags:= STARTF_USESHOWWINDOW or STARTF_USEPOSITION or STARTF_USESIZE;
  SI.wShowWindow:= SW_SHOW;
  Result:= 0;
  if CreateProcess(nil, PCHAR(CommandLine), nil, nil, false, 0, nil, nil, SI, PI) then
  begin
    WaitForInputIdle(PI.hProcess, 10000);
    Result:= GetWindowFromPId(PI.dwProcessId);
    CloseHandle(PI.hProcess);
    CloseHandle(PI.hThread);
  end;
end;

// Creamos un proceso, localizamos la ventana y la ponemos en primer plano
// Luego nos cerramos.
procedure EjecutamosyNosVamos;
var
  hWin: HWND;
begin
  hWin:= Execute('Notepad.exe');
  SetWindowPos(hWin, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE or SWP_NOSIZE);
  Close;  //Nos vamos
end;




Saludos.
Responder Con Cita
  #3  
Antiguo 06-01-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por MaxiDucoli Ver Mensaje

Se pueden buscar los exe en ejecución y terminarlos directamente? Eso sería de mucha ayuda para el programa principal...

Se me olvidaba esta parte.


Se puede terminar cualquier proceso a lo bruto aunque no es lo más recomendable. Se hace con la API TerminateProcess, pero es mejor tratar de terminarlos enviando el mensaje WM_CLOSE a la ventana principal de la aplicación. Si te interesa como buscar y matar procesos a lo bruto te dejo esto que escribí hace unos años:


Código Delphi [-]
uses
  Windows, TLHelp32;

.................

function EnablePrivilege(name: String; Enable: boolean = true): boolean;
var
  hToken: Cardinal;
  priv: TOKEN_PRIVILEGES;
begin
  priv.PrivilegeCount:= 1;
  priv.Privileges[0].Attributes:= 0;
  if Enable then priv.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED;
  LookupPrivilegeValue(nil, PCHAR(name), priv.Privileges[0].Luid);
  OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken);
  AdjustTokenPrivileges (hToken, FALSE, priv, sizeof(priv), nil, PDWORD(nil)^);
  Result:= (GetLastError = ERROR_SUCCESS);
  CloseHandle (hToken);
end;

procedure KillProcess(FileName: String);
var
  Process, hSysSnapshot: THandle;
  PE: TPROCESSENTRY32;
begin
  EnablePrivilege('SeDebugPrivilege');
  PE.dwSize:= sizeof(TPROCESSENTRY32);
  hSysSnapshot:= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if (hSysSnapshot <> INVALID_HANDLE_VALUE) and Process32First(hSysSnapshot, PE) then
    repeat
      if (lstrcmpi(PE.szExeFile, PAnsiChar(FileName)) = 0) and (GetCurrentProcessID <> PE.th32ProcessID) then
      begin
        Process:= OpenProcess(PROCESS_TERMINATE, false, PE.th32ProcessID);
        if Process <> 0 then
        begin
          TerminateProcess(Process, 0);
          CloseHandle(process);
        end;
      end;
    until not Process32Next(hSysSnapshot, PE);
  CloseHandle(hSysSnapshot);
  EnablePrivilege('SeDebugPrivilege', false);
end;


Saludos.
Responder Con Cita
  #4  
Antiguo 02-02-2020
MaxiDucoli MaxiDucoli is offline
Miembro
 
Registrado: feb 2006
Posts: 134
Poder: 19
MaxiDucoli Va por buen camino
La ventana que necesito cerrar no hace más que abrirse en primer plano maximizada, de fondo tener una imagen como para tapar todo lo que sucede detrás y la idea es que una vez que se ejecute el programa emulador que deseo, esta ventana se cierre, ya que todo esto lo ejecuto desde un archivo .bat que te describo acá abajo:

@echo START
set HOME="\RetroLife\emulators\retroarch"
START "LAUNCHIMG" /B /D "\RetroLife" "FrmClose.exe" %2
START "RUN-EMU" /W /B /D "\RetroLife\emulators\retroarch" "retroarch.exe" -L "\RetroLife\emulators\retroarch\cores\%3_libretro.dll" --config "\RetroLife\emulators\retroarch\config\retroarch.cfg" --appendconfig "\RetroLife\emulators\retroarch\config\RetroLife-override.cfg" %1 --log-file "\RetroLife\logs\%3-Logfile.txt" -v
@echo Done


Lo que pasa acá es así:

Estoy dentro de un frontend de emuladores (EmulationStation por si lo conoces o Recalbox, Batocera, Retropie lo usan también pero en Linux) ejecuto el bat y le paso 3 parámetros

1 - Ubicación del juegos (ROM)
2 - nombre del sistema (es acá donde carga FrmClose.exe y le paso como parámetro el segundo parámetro del BAT que le indicaría donde cargar la imagen de fondo.
3 - Nombre para que guarde el LOG de todo lo que hace el emulador y seguir sus fallos.


Por lo que esa ventana que quiero cerrar no hace más que eso, mostrarse hasta que se abra el emulador.

Si le pongo que esa ventana lance directamente el emulador sin usar un BAT, cuando cierro esa ventana el frontend "piensa" que ya cerré el emulador y se vuelve a mostrar, dejando el emulador corriendo y eso no sirve.
Cuando cierro el emulador, el frontend debe volver a su estado maximizado, para esperar que le pase la ruta de otro juego o sistema.

Tenés alguna idea de como hacer para esperar a "ver" esa ventana del emulador y ahí cerrar la ventana de la imagen?

Por eso se me había ocurrido saber si el proceso se estaba ejecutando y cerrarla así nomás sin enviar ningún CLOSE.
Responder Con Cita
  #5  
Antiguo 02-02-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
El problema es que no entiendo lo que quieres decir.
No se que es "esa ventana" no a que proceso corresponde, si es del emulador, si es tu Bat o si es una aplicación tuya.


Una ventana se puede cerrar pero si cierras su proceso, se acabó. No volverá a abrirse.
Cuando una ventana es la ventana principal de un proceso, generalmente cerrarla supone cerrar el proceso.


La consola no representa una ventana de un proceso sino un proceso sobre el que se ejecuta otro, usando la consola como sistema de interface. Cerrar la consola implica cerrar el proceso.


Si quieres saber si un proceso se está ejecutando, puedes usar este código:
Código Delphi [-]
uses
  Windows, TLHelp32;

function IsRuning(FileName: PAnsiChar): boolean;
var
  PE: TPROCESSENTRY32;
  ProcessHandle: THandle;
begin
  Result:= false;
  PE.dwSize:= sizeof(TPROCESSENTRY32);
  ProcessHandle:= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if Process32First(ProcessHandle, PE) then
    repeat
      if lstrcmpi(PE.szExeFile, FileName) = 0 then
      begin
        Result:= true;
        break;
      end;
    until not Process32Next(ProcessHandle, PE);
  CloseHandle(ProcessHandle);
end;


Puedes encontrar más información aquí y aquí.




Saludos.

Última edición por escafandra fecha: 02-02-2020 a las 21:03:50.
Responder Con Cita
  #6  
Antiguo 03-02-2020
MaxiDucoli MaxiDucoli is offline
Miembro
 
Registrado: feb 2006
Posts: 134
Poder: 19
MaxiDucoli Va por buen camino
Es medio complicado todo esto para mi y por eso me complico al querer explicarlo.

A ver si puedo sin repetir lo que te dije antes jajajaja!!

Desde el frontend de emuladores yo lanzo mi bat.
En ese bat lanzo dos programas hechos por mi:

En el primer programa que se ejecuta con START lanzo el FRM que muestra la imagen del emulador, esa que tiene que estar un poco abierta tapando todo, hasta que el emulador esté en ejecución.

Ese emulador yo lo largo inmediatamente después de lanzar el FRM en el bat con START pero a este le pongo la opcion /W para que espere a que termine el preceso para cerrarse el bat y de esta manera el frontend no se cierre automáticamente y espere a que termine de ejecutar el emulador.

Con lo que me diste de IsRunning() voy a probar de ponerlo en un Timer dentro del primer programa (el lanzador de imagen) y que espere 5 segundos para ver si se lanzo el emulador y si da TRUE que se cierre.


Muchas gracias.
Responder Con Cita
  #7  
Antiguo 03-02-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
¿El frontend es un programa de consola?
¿Porque dependes de un Bat y no lo haces todo con una APP?
¿Porqué quieres una ventana para tapar? ¿Tapar que?
¿Has pensado que tu ventana "Tapadora" no tiene porqué cerrarse, que puede esconderse?


Tu mecanismo es enrevesado, debes tratar de encontrar una estrategia clara, sencilla y limpia.


Saludos.
Responder Con Cita
  #8  
Antiguo 03-02-2020
MaxiDucoli MaxiDucoli is offline
Miembro
 
Registrado: feb 2006
Posts: 134
Poder: 19
MaxiDucoli Va por buen camino
Cita:
Empezado por escafandra Ver Mensaje
¿El frontend es un programa de consola?
¿Porque dependes de un Bat y no lo haces todo con una APP?
¿Porqué quieres una ventana para tapar? ¿Tapar que?
¿Has pensado que tu ventana "Tapadora" no tiene porqué cerrarse, que puede esconderse?


Tu mecanismo es enrevesado, debes tratar de encontrar una estrategia clara, sencilla y limpia.


Saludos.

El frontend es un programa visual (creo que está hecho con SDL2)
Uso un bat por que no me di maña para hacerlo con un solo programa (fue mi idea original y tuve muchas fallas)
La ventana para "tapar" lo que hace es ponerse en primer plano con una imagen abarcando toda la pantalla y lo que tapa son todas las ventanas de consola que se ejecuten antes de arrancar el emulador y que quede más presentable.


Mi problema en hacerlo con un solo programa fue que sí o sí el frontend tiene que llamar a otro programa para que se ejecute, dado que no puedo hacer que ejecute el mismo programa abierto y que este me tire todo desde ahí.

Por eso hice una vez un post preguntando si se podían enviar mensajes a programas abiertos y (creo que vos) me respondiste que si y era con dos programas. Uno que era el "server" y el otro el "receptor". Lo hice así, pero era complicado para todo lo que quería hacer también.

O sea que si yo puedo ejecutar un programa hecho por mi, que este programa ejecute lo que quiero y abra el frontend y luego cuando el frontend quiera lanzar el emulador, tenga que volver a ejecutar mi programa abierto, seber que está abierto y en vez de ejecutarse, solo pasarle parámetros y lanzarlo me solucionaría todo.
Mi idea original era así, pero no sé hacer eso y busqué por todos lados, hasta pregunté acá, pero no encontré respuesta.



Lo de la idea ya lo sé. Es que soy muy desordenado y a eso hay que sumarle que mucho no sé de Delphi, solo lo básico y un poquito más capaz, ya que no soy programador.

Si podés darme un "empujón" con una idea para esto te lo agradecería mucho.

Gracias!
Responder Con Cita
  #9  
Antiguo 03-02-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
A ver si entiendo. Quieres tapar lo que hace frontend hasta que termine. Luego quieres destapar pero más tarde frontend volverá a actuar y lo querrás volver a tapar. ¿Es así?
Eso implica que el programa tapador o no se cierra o requiere que le digan que tape. ¿Eso lo hace frontend?


No es complicado establecer un sistema de comunicación usando archivos de memoria compartida. Imagina este escenario:
Una App se ejecuta con unos parámetros en la linea de comandos y hace determinada cosa. Otra aplicación o el mismo usuario quiere pasarle más parametros pero sin cerrar la app. Para ello abre otra instancia de la app con los nuevos parámetros. Esta nueva instancia al empezar detecta que ya estaba corriendo otra copia, entonces lo que hace es abrir un archivo de memoria compartida, copia la línea de comandos en él y envía un mensaje a la primera instancia que le díce "¡Oye!, que te he mandado unas cosas". Este mensaje es un mensaje de Windows con PostMessage. La Primara instancia recibe el mensaje y lee el archivo de memoria compartida con toda la linea de parárametros y actúa en consecuencia. Mientras, la segunda instancia se autodestruye y jamás se ejecutará en su plenitud. Ambas instancias son de un mismo ejecutable, son lo mismo, pero actúan según si ya existía una previa.


Hay otras formas de comunicación pero ésta es sencilla desde el punto de vista del usuario pues para pasar parámetros siempre usa la misma forma, abrir la app y pasar los parámetros. el resto es automático.


Si esto te sugiere una solución puedes seguir adelante. Aquí publiqué una clase que crea un archivo de memoria compartida.




Saludos.
Responder Con Cita
  #10  
Antiguo 04-02-2020
MaxiDucoli MaxiDucoli is offline
Miembro
 
Registrado: feb 2006
Posts: 134
Poder: 19
MaxiDucoli Va por buen camino
Cita:
Empezado por escafandra Ver Mensaje
A ver si entiendo. Quieres tapar lo que hace frontend hasta que termine. Luego quieres destapar pero más tarde frontend volverá a actuar y lo querrás volver a tapar. ¿Es así?
Eso implica que el programa tapador o no se cierra o requiere que le digan que tape. ¿Eso lo hace frontend?


No es complicado establecer un sistema de comunicación usando archivos de memoria compartida. Imagina este escenario:
Una App se ejecuta con unos parámetros en la linea de comandos y hace determinada cosa. Otra aplicación o el mismo usuario quiere pasarle más parametros pero sin cerrar la app. Para ello abre otra instancia de la app con los nuevos parámetros. Esta nueva instancia al empezar detecta que ya estaba corriendo otra copia, entonces lo que hace es abrir un archivo de memoria compartida, copia la línea de comandos en él y envía un mensaje a la primera instancia que le díce "¡Oye!, que te he mandado unas cosas". Este mensaje es un mensaje de Windows con PostMessage. La Primara instancia recibe el mensaje y lee el archivo de memoria compartida con toda la linea de parárametros y actúa en consecuencia. Mientras, la segunda instancia se autodestruye y jamás se ejecutará en su plenitud. Ambas instancias son de un mismo ejecutable, son lo mismo, pero actúan según si ya existía una previa.


Hay otras formas de comunicación pero ésta es sencilla desde el punto de vista del usuario pues para pasar parámetros siempre usa la misma forma, abrir la app y pasar los parámetros. el resto es automático.


Si esto te sugiere una solución puedes seguir adelante. Aquí publiqué una clase que crea un archivo de memoria compartida.




Saludos.
Que lindo sería saber tanto.

voy a ojear el código, busar qué es todo lo que no entiendo en lo que a funciones y procedimientos el código use, así de verdad sé qué y cómo lo hace y te cuento como me fue.
Te molestaria si te posteo en una respuesta un video del FrontEnd, así más o menos entendés como trabaja y capaz se te ocurre algo más práctico?

Dónde aprendiste Delphi tan bien?
Yo vivo en Argentina y la verdad que de los pocos cursos que dan, solo era Visual Basic, después C# en muy pocos lados , ActionScript para Flash y ahora lo que más dan era JAVA, Python, Android y Visual C#.
Pero jamás encontré uno de Delphi que tanto me gusta ese lenguaje.

Igualmente al no trabajar de programador no le di la atención necesaria por que yendo al caso a Delphi lo agarré en el año 2002 más o menos y de a poquito lo fui usando y aprendiendo por mi cuenta en internet y lo malo fue que lo que más hacía (y hago no voy a mentir) es copiar y pegar código de otros sin estudiar bien lo que hace y ahí mi error de no haber aprendido bien y más para Windows que con las API de windows si las entendés se hace todo muy fácil.
Responder Con Cita
  #11  
Antiguo 04-02-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por MaxiDucoli Ver Mensaje
Que lindo sería saber tanto.
Si, ya me gustaría saber tanto...




Cita:
Empezado por MaxiDucoli Ver Mensaje
voy a ojear el código, busar qué es todo lo que no entiendo en lo que a funciones y procedimientos el código use, así de verdad sé qué y cómo lo hace y te cuento como me fue.
Te molestaria si te posteo en una respuesta un video del FrontEnd, así más o menos entendés como trabaja y capaz se te ocurre algo más práctico?
Está bien que mires código y que lo entiendas pero tienes que diseñar una estrategia y luego implementarla. Si no, el resultado será muy chapucero. Puedes colgar los videos que quieras.




Cita:
Empezado por MaxiDucoli Ver Mensaje
Dónde aprendiste Delphi tan bien?
Yo vivo en Argentina y la verdad que de los pocos cursos que dan, solo era Visual Basic, después C# en muy pocos lados , ActionScript para Flash y ahora lo que más dan era JAVA, Python, Android y Visual C#.
Pero jamás encontré uno de Delphi que tanto me gusta ese lenguaje.
Lo importante no es el lenguaje sino tener claro que hacer con él. A mi me gusta más el C para lo que suelo hacer y Builder es primi hermado de delphi, así que me manejo en las dos caras de la moneda. Quizás puedas leer alguno de los libros recomendados para delphi, empezando con el incunable "La Cara Oculta de delphi 4" pero a escribir código se aprende escribiendo, leyendo y entendiendo. La documentación de la API de Windows que da M$ es muy buena pero hay que pensar en C. Hay mucha gente que le tiene miedo. En realidad te permite ir mucho más allá del límite de la VCL, pero siempre a bajo nivel.


Saludos.
Responder Con Cita
  #12  
Antiguo 02-03-2020
MaxiDucoli MaxiDucoli is offline
Miembro
 
Registrado: feb 2006
Posts: 134
Poder: 19
MaxiDucoli Va por buen camino
Volví. (mucho trabajo)

Cita:
Empezado por escafandra Ver Mensaje
Si, ya me gustaría saber tanto...





Está bien que mires código y que lo entiendas pero tienes que diseñar una estrategia y luego implementarla. Si no, el resultado será muy chapucero. Puedes colgar los videos que quieras.





Lo importante no es el lenguaje sino tener claro que hacer con él. A mi me gusta más el C para lo que suelo hacer y Builder es primi hermado de delphi, así que me manejo en las dos caras de la moneda. Quizás puedas leer alguno de los libros recomendados para delphi, empezando con el incunable "La Cara Oculta de delphi 4" pero a escribir código se aprende escribiendo, leyendo y entendiendo. La documentación de la API de Windows que da M$ es muy buena pero hay que pensar en C. Hay mucha gente que le tiene miedo. En realidad te permite ir mucho más allá del límite de la VCL, pero siempre a bajo nivel.


Saludos.
Hola.
Vuelvo un rato después de algo de trabajo y poco tiempo a seguir con mi hobbie para poder despejarme un poco.

Me gustaría preguntarte alguna cosita para ver si cambio todo mi programa de raíz y lo empiezo de nuevo.


Pongamos que hago todo el programa de nuevo.

El front end lanza mi programa el cual abre y muestra la imagen de "LOADING GAME".
Lo que quiero es que al cargarse el emulador, mi programa se dé cuenta que el emulador está en ejecución.

Se puede saber si ese programa está en primer plano, está maximizado y ahí "esconder" la ventana de mi programa hasta que el emulador se cierre y ahí cerrarla?

Por que en realidad eso es todo lo que necesito que mi programa haga y con tanto bat y programas externos la estoy empeorando.

O sea;

FrontEnd ----> Lanza mi programa y queda a la espera de que mi programa termine para volver a primer plano.
Mi programa ---> Aparece encima de todo, mostrando una imagen de "LOADING GAME" o algo así, lanza el emulador y queda a le espera de que el emulador termine, para cerrarse y de esta manera darle el permiso al Frontend para que vuelva al prmer plano.


Podrías darme alguna de idea de como poder lograr eso sin liarme hasta no entender más nada y desistir, por favor?

Muchas gracias!!!!!
Responder Con Cita
  #13  
Antiguo 02-03-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Ok. Te presento un programita que se ejecuta maximizado mostrando un Label que dice "LOADING GAME" al arrancar. Luego Ejecuta "Notepad.exe" y se esconde. Al cerrar Notepad, el programita se termina.


Espero que esta sea la idea de lo que quieres hacer.


Código Delphi [-]
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    function Execute(CommandLine: String): cardinal;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//------------------------------------------------------------------------------
// Creamos un proceso.
function TForm1.Execute(CommandLine: String): cardinal;
var
  SI: TStartupInfo;
  PI: TProcessInformation;
begin
  ZeroMemory(@SI, sizeof(TStartupInfo));
  SI.cb:= sizeof(SI);
  SI.dwFlags:= STARTF_USESHOWWINDOW or STARTF_USEPOSITION or STARTF_USESIZE;
  SI.wShowWindow:= SW_SHOW;
  Result:= 0;
  if CreateProcess(nil, PCHAR(CommandLine), nil, nil, false, 0, nil, nil, SI, PI) then
  begin
    WaitForInputIdle(PI.hProcess, 10000);
    Visible:= false;
    WaitForSingleObject(PI.hProcess,INFINITE);
    GetExitCodeProcess(PI.hProcess, Result);
    CloseHandle(PI.hProcess);
    CloseHandle(PI.hThread);
  end
  else
    Result:= $FFFFFFFF;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  WindowState:= wsMaximized;
  FormStyle:= fsStayOnTop;
  BorderStyle:= bsNone;
  Label1.Caption:= '"LOADING GAME"';
  Label1.Font.Size:= 30;
  Label1.Font.Style:= [fsBold];


  // Simula que tarda en cargar...
  Timer1.Interval:= 2000;  // Poner Timer1.Interval:= 1 para no esperar nada,
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // Simula que tarda en cargar...
  Execute('Notepad.exe');

  Visible:= True;
  Label1.Caption:= 'NOS VAMOS';
  Update;
  Sleep(500);
  Close;
end;

end.


Saludos.
Responder Con Cita
  #14  
Antiguo 03-03-2020
MaxiDucoli MaxiDucoli is offline
Miembro
 
Registrado: feb 2006
Posts: 134
Poder: 19
MaxiDucoli Va por buen camino
Cita:
Empezado por escafandra Ver Mensaje
Ok. Te presento un programita que se ejecuta maximizado mostrando un Label que dice "LOADING GAME" al arrancar. Luego Ejecuta "Notepad.exe" y se esconde. Al cerrar Notepad, el programita se termina.


Espero que esta sea la idea de lo que quieres hacer.


Código Delphi [-]
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    function Execute(CommandLine: String): cardinal;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//------------------------------------------------------------------------------
// Creamos un proceso.
function TForm1.Execute(CommandLine: String): cardinal;
var
  SI: TStartupInfo;
  PI: TProcessInformation;
begin
  ZeroMemory(@SI, sizeof(TStartupInfo));
  SI.cb:= sizeof(SI);
  SI.dwFlags:= STARTF_USESHOWWINDOW or STARTF_USEPOSITION or STARTF_USESIZE;
  SI.wShowWindow:= SW_SHOW;
  Result:= 0;
  if CreateProcess(nil, PCHAR(CommandLine), nil, nil, false, 0, nil, nil, SI, PI) then
  begin
    WaitForInputIdle(PI.hProcess, 10000);
    Visible:= false;
    WaitForSingleObject(PI.hProcess,INFINITE);
    GetExitCodeProcess(PI.hProcess, Result);
    CloseHandle(PI.hProcess);
    CloseHandle(PI.hThread);
  end
  else
    Result:= $FFFFFFFF;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  WindowState:= wsMaximized;
  FormStyle:= fsStayOnTop;
  BorderStyle:= bsNone;
  Label1.Caption:= '"LOADING GAME"';
  Label1.Font.Size:= 30;
  Label1.Font.Style:= [fsBold];


  // Simula que tarda en cargar...
  Timer1.Interval:= 2000;  // Poner Timer1.Interval:= 1 para no esperar nada,
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // Simula que tarda en cargar...
  Execute('Notepad.exe');

  Visible:= True;
  Label1.Caption:= 'NOS VAMOS';
  Update;
  Sleep(500);
  Close;
end;

end.


Saludos.
Muchas gracias por tomarte el tiempo que es un recurso irrecuperable.
Esta tarde, en cuanto regrese del trabajo, esto va a ser lo primero que me ponga a hacer.

La verdad es que no me puedo explicar como pudo ser algo tan sencillo y jamás imaginarlo. Ja!
Bueno están los que saben y son fuente inagotable de sabiduría y los que no aprendemos por más ganas que le echemos. 😂 🤣 😂

Te agradezco y más tarde te paso el reporte de como me fue.

Muy agradecido!
Saludos!!!!!
Responder Con Cita
  #15  
Antiguo 09-03-2020
MaxiDucoli MaxiDucoli is offline
Miembro
 
Registrado: feb 2006
Posts: 134
Poder: 19
MaxiDucoli Va por buen camino
Hola acá molestando otra vez.

Sabés que el programa se me queda tildado y no ejecuta nada?
Parece que el problema es acá:

if CreateProcess(nil, PCHAR(CommandLine), nil, nil, false, 0, nil, nil, SI, PI)

Pero no puedo saber por qué.
Me dice error
reised exception class $C00000005 with mesage 'access violation at 0x7788d00: write of adress 0x005eb846'

Qué puede ser?
Responder Con Cita
  #16  
Antiguo 09-03-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por MaxiDucoli Ver Mensaje
Hola acá molestando otra vez.

Sabés que el programa se me queda tildado y no ejecuta nada?
Parece que el problema es acá:

if CreateProcess(nil, PCHAR(CommandLine), nil, nil, false, 0, nil, nil, SI, PI)

Pero no puedo saber por qué.
Me dice error
reised exception class $C00000005 with mesage 'access violation at 0x7788d00: write of adress 0x005eb846'

Qué puede ser?
Tendrás que especificar más cosas, cual es el código exacto que has usado, S.O. y compilador. Para concretar las cosas te subo el proyecto que hice con su binario. Está escrito y compilado con delphi7.

Te propongo un cambio:
Código Delphi [-]
//------------------------------------------------------------------------------
// Creamos un proceso.
function TForm1.Execute(CommandLine: String): cardinal;
var
  SI: TStartupInfo;
  PI: TProcessInformation;
begin
  ZeroMemory(@SI, sizeof(TStartupInfo));
  SI.cb:= sizeof(SI);
  SI.dwFlags:= STARTF_USESHOWWINDOW or STARTF_USEPOSITION;// or STARTF_USESIZE;
  SI.wShowWindow:= SW_SHOW;
  Result:= 0;
  if CreateProcess(nil, PCHAR(CommandLine), nil, nil, false, 0, nil, nil, SI, PI) then
  begin
    WaitForInputIdle(PI.hProcess, 10000);
    Visible:= false;
    WaitForSingleObject(PI.hProcess,INFINITE);
    GetExitCodeProcess(PI.hProcess, Result);
    CloseHandle(PI.hProcess);
    CloseHandle(PI.hThread);
  end
  else
    Result:= $FFFFFFFF;
end;

Lo puedes encontrar aquí: Exec_Whait_End.zip.


Saludos.
Archivos Adjuntos
Tipo de Archivo: zip Exec_Whait_End.zip (192,5 KB, 12 visitas)

Última edición por escafandra fecha: 09-03-2020 a las 08:16:21.
Responder Con Cita
  #17  
Antiguo 10-03-2020
MaxiDucoli MaxiDucoli is offline
Miembro
 
Registrado: feb 2006
Posts: 134
Poder: 19
MaxiDucoli Va por buen camino
Hola.
Con el Project1.exe funciona.
Muestra el Form, abre cmd.exe y cuando cierro cmd.exe dice NOS VEMOS y se cierra todo.

Pero con el código fuente me da el mismo error.


Uso Windows 10 actualizado a la última versión, Delphi 10.3.1, el códgo lo puse exactamente como me lo mandaste.

Pero me tira el error ese que te indiqué antes.

Que raro.
Responder Con Cita
  #18  
Antiguo 10-03-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Es problema del unicode el delphi. Si se fuerza a usar AnsiChar funcionará. Este problema no ocurre en C, posiblemente esté mas declarada la API.
Prueba este código que si funciona en Berlin y funcionará en tu versión de delphi:


Código Delphi [-]
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    function Execute(CommandLine: AnsiString): cardinal;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//------------------------------------------------------------------------------
// Creamos un proceso.
function TForm1.Execute(CommandLine: AnsiString): cardinal;
var
  SI: TStartupInfoA;
  PI: TProcessInformation;
begin
  ZeroMemory(@SI, sizeof(TStartupInfoA));
  SI.cb:= sizeof(SI);
  SI.dwFlags:= STARTF_USESHOWWINDOW or STARTF_USEPOSITION;
  SI.wShowWindow:= SW_SHOW;
  Result:= 0;
  if CreateProcessA(0, PAnsiChar(CommandLine), nil, nil, false, 0, nil, nil, SI, PI) then
  begin
    WaitForInputIdle(PI.hProcess, 10000);
    Visible:= false;
    WaitForSingleObject(PI.hProcess,INFINITE);
    GetExitCodeProcess(PI.hProcess, Result);
    CloseHandle(PI.hProcess);
    CloseHandle(PI.hThread);
  end
  else
    Result:= $FFFFFFFF;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ShowWindow(Handle, SW_MAXIMIZE);
  WindowState:= wsMaximized;
  FormStyle:= fsStayOnTop;
  BorderStyle:= bsNone;
  Label1.Caption:= '"LOADING GAME"';
  Label1.Font.Size:= 30;
  Label1.Font.Style:= [fsBold];
  // Simula que tarda en cargar...
  Timer1.Interval:= 2000;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled:= false;
  // Simula que tarda en cargar...
  Execute('cmd.exe');
  Visible:= True;
  Label1.Caption:= 'NOS VAMOS';
  Update;
  Sleep(500);
  Close;
end;

end.

He añadido discretas mejoras y pasado a PAnsiChar.


Saludos.
Responder Con Cita
  #19  
Antiguo 27-03-2020
MaxiDucoli MaxiDucoli is offline
Miembro
 
Registrado: feb 2006
Posts: 134
Poder: 19
MaxiDucoli Va por buen camino
Espectacular!!!!!
Ahora funciona.
Le voy a hacer todas las modificaciones que se necesitan y después te voy a pasar el link para que puedas verlo como quedó, si querés.
Va a ser como empezar desde cero, pero va a valer la pena.

MUCHÍSIMAS GRACIAS!!!!!

Perdón por tardar tanto, pero con esto del virus, mi trabajo me demanda el triple te tiempo y llego muy cansado.

Última edición por Casimiro Notevi fecha: 27-03-2020 a las 21:30:47.
Responder Con Cita
Respuesta



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
Optimizar codigo n03l Varios 3 28-11-2013 21:07:11
optimizar el codigo en menos lineas darkbits Varios 5 19-07-2013 13:32:40
Ayuda como Optimizar Código JerS OOP 3 24-06-2011 05:59:44
optimizar codigo acrophet Varios 5 16-01-2011 23:28:39
Optimizar el sgte codigo BlueSteel Varios 9 14-08-2007 22:33:24


La franja horaria es GMT +2. Ahora son las 05:55:36.


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