Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   SendMessage y dos instancias de una aplicación (https://www.clubdelphi.com/foros/showthread.php?t=31926)

Aldo 22-05-2006 16:12:25

SendMessage y dos instancias de una aplicación
 
Hola a Todos:

Estoy trabajando con Delphi5 y tengo una aplicación que permite la ejecución de solo una instancia a la vez. Esto está logrado creando Mutex y cuando se ejecuta la segunda instancia de la aplicación, se envía un mensaje a la primera instancia para que ésta se venga al primer plano y la segunda instancia deja de ejecutarse.

Hasta aquí todo bien, el problema que tengo ahora es que quiero mandar otro mensaje a la primera instancia de la aplicación antes de hacer todo lo explicado en el párrafo anterior y lo hago, pero la primera instancia no me responde, por lo visto no recibe el mensaje.

Os pongo la parte del código fuento que previene que se ejecute más de una instancia de la aplicación a la vez:
Código Delphi [-]
 {Attempt to create a named mutex}
     CreateMutex( nil, False,  PChar( 'Main' ) );

     {if it failed then there is another instance}
     if GetLastError = ERROR_ALREADY_EXISTS then
        begin
           EnviarMensaje;

           {Send all windows our custom message - only our other}
           {instance will recognise it, and restore itself}
           SendMessage( HWND_BROADCAST, RegisterWindowMessage( 'Main' ), 0, 0 );

           {Lets quit}
           Halt(0);
        end;

El problema viene en el Procedimiento EnviarMensaje;
Código Delphi [-]
     procedure EnviarMensaje;
     var
        nHwnd     : HWND;
        Estructura: TGdbMantEstruc;
        nModo     : TModoEjecucion;
        nResult   : Integer;
     begin
        nHwnd := FindWindow( PChar( 'TMain' ), CAPT_VENTANA_PPAL_GDBMANT );
        if nHwnd <> 0 then
           begin
              ClearGdbMantEstruc( Estructura ); // Inicializar la Estructura 
              try
                 // Según los parámetros de la línea de comandos del llamado a la 
                 // aplicación, devuelve un tipo que dice que debe hacerse
                 nModo := DetectarModoEjecucion();  

                 case nModo of
                    // LLenar la parte de la estructura con la información
                    // necesaria para que se ejecute la aplicación al recibir el 
                    // mensaje desde la otra instancia
                    tEjecutarAhora : 
                       if ParamCount = 2 then 
                          Estructura.szDescTareaOld := ParamStr( 2 );  
                 end;
                  
                 // Envío de un mensaje a la otra instancia de la misma aplicación 
                 // con el mensaje que se calcula automáticamente como 
                 // WM_USER + 1000 + nModo, pasando en wParam un puntero a 
                 // la estructura con toda la información necesaria según sea el 
                 // caso de nModo
                 nResult := SendMessage( nHwnd, 
                                         ModoEjecucionToCodigoMessage( nModo ), 
                                         longint( @Estructura ), 
                                         0 );
              finally
                 // Liberar la memoria que ya no se usa de la estructura 
                 ClearGdbMantEstruc( Estructura, True );
              end;
           end;
     end;

Por ultimo en el procedimiento DefaultHandler del formulario principal de la aplicación se pone lo siguiente para tratar el mensaje que se supone que debe llegar a ella, pero que no está llegando.

Código Delphi [-]
procedure TMain.DefaultHandler(var Message);
begin
  inherited DefaultHandler(Message);

  if TMessage( Message ).Msg = fUserMessage then
     begin
        ReplyMessage( 0 );
        CargarFicheroLog;
     end
  else if TMessage( Message ).Msg >= WM_USER + 1000 then
     begin
        case TMessage( Message ).Msg of
           WM_USER + 1000 + 0  : { tNormal };
           WM_USER + 1000 + 1  : { tTaskBar };
           WM_USER + 1000 + 2  : { tInstalar };
           WM_USER + 1000 + 3  : { tDesinstalar };
           WM_USER + 1000 + 4  : { tCrearAccion };
           WM_USER + 1000 + 5  : { tCrearProgramacion };
           WM_USER + 1000 + 6  : { tEditarAccion };
           WM_USER + 1000 + 7  : { tEditarProgramacion };
           WM_USER + 1000 + 8  : { tEliminarTarea };
           WM_USER + 1000 + 9  : { tEliminarAccion };
           WM_USER + 1000 + 10 : { tEliminarProgramacion };
           WM_USER + 1000 + 11 : { tDetenerServicio };
           WM_USER + 1000 + 12 : { tIniciarServicio };
           WM_USER + 1000 + 13 : { tRefrescar };
           WM_USER + 1000 + 14 : { tEjecutarAhora }
              EjecutarTarea( PGdbMantEstruc( TMessage( Message ).WParam )^.szDescTareaOld );
        end;
     end;
end;

No sé si lo que quiero hacer es factible o no y si es afirmativo, entonces ¿ En que me puedo estar equivocando ?.

Les agradezco el tiempo prestado y sus posibles respuestas de antemano

luisgutierrezb 22-05-2006 18:04:56

bueno, el registerwindowsmessage, debes registrarlo luego luego en la primera instancia, cuando entre la segunda, al volverle a dar el registerwindowmessage te devolvera el mismo numero de mensaje, asi que los 2 ya podran procesarlo...

lo que tambien se me ocurre, porque no desde la primera aplicacion usas un setforegroundwindow desde la aplicacion que se abrio la segunda vez y asi no tienes que mandar un mensaje

Aldo 22-05-2006 18:20:06

Traspaso de Estructura como parámetros entre 2 aplicaciones
 
He dado un giro a mi pregunta inicial y he usado el RegisterWindowMessage para que las dos instancias de la misma aplicación se entiendan entre si con el mismoi dentificador de mensaje y he cambiado un poco la función que envia elmensaje. Ahora ha quedado así
Código Delphi [-]
procedure EnviarMensaje;
     var
        Estructura  : TTGebMantEtruct;
        nModo       : TModoEjecucion;
        nResult     : Integer;
     begin
           ClearGdbMantEstruc( Estructura );
           try
              nModo := DetectarModoEjecucion();

              case nModo of
                 tEjecutarAhora : if ParamCount = 2 then Estructura.szDescTareaOld := PChar( ParamStr( 2 ) );
              end;

              nResult     := SendMessage( HWND_BROADCAST,
                                          RegisterWindowMessage( CAPT_WND_MESSAGE_ACTIVATE_APP ),
                                          Integer( nModo ),
                                          longint( @Estructura ) );
           finally
              ClearGdbMantEstruc( Estructura, True );
           end;
     end;

Ahora si se comunican las dos instancias, pero tengo un nuevo problema y es que la primera instancia cuando recibe el mensaje, éste le llega vacío. Os mando la declaración de la estructura para ver si es que hago algo mal
Código Delphi [-]
   TGdbMantEstruc = packed record
      szDescTareaOld    : WideString;
      szDescTareaNew    : WideString;
      bTareaActiva      : Boolean;
      clsAcciones       : TColeccionAcciones;
      clsProgramaciones : TColeccionProgramaciones;
   end;

   PGdbMantEstruc = ^TGdbMantEstruc;
   TTGebMantEtruct = TGdbMantEstruc;

Y la función que procesa el Mensaje cuando llega ha quedado así:

Código Delphi [-]
procedure TMain.DefaultHandler(var Message);
var
   szTareaName: String;
begin
  inherited DefaultHandler(Message);

   if TMessage( Message ).Msg = RegisterWindowMessage( CAPT_WND_MESSAGE_ACTIVATE_APP ) then
     begin
        szTareaName := PGdbMantEstruc( @TMessage( Message ).LParam )^.szDescTareaOld;
        ShowMessage( 'szTareaName ' + szTareaName ); 
        // El ShowMessage lo pongo para ver que me trae en el campo szDescTareaOld de la estructura 
        case TMessage( Message ).WParam of
              0  : { tNormal };
              1  : { tTaskBar };
              2  : { tInstalar };
              3  : { tDesinstalar };
              4  : { tCrearAccion };
              5  : { tCrearProgramacion };
              6  : { tEditarAccion };
              7  : { tEditarProgramacion };
              8  : { tEliminarTarea };
              9  : { tEliminarAccion };
              10 : { tEliminarProgramacion };
              11 : { tDetenerServicio };
              12 : { tIniciarServicio };
              13 : { tRefrescar };
              14 : { tEjecutarAhora }
                 EjecutarTarea( PGdbMantEstruc( @TMessage( Message ).LParam )^.szDescTareaOld );
        end;
     end;
end;

Os sigo agradeciendo el tiempo prestado por tratar de ayudarme

seoane 22-05-2006 19:43:12

Código Delphi [-]
szTareaName := PGdbMantEstruc( @TMessage( Message ).LParam )^.szDescTareaOld;

A simple vista, me parece que en esta linea te sobra la @.


La franja horaria es GMT +2. Ahora son las 05:34:42.

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