Page 1 of 1

Tratando de leer un get de una ventana desde otra ventana...

Posted: Tue Jan 17, 2006 12:46 pm
by Rafael Clemente
Estoy intentando leer el contenido de un Get de una ventana desde otra ventana independiente. Efectivamente, leo el valor inicial del Get pero aunque escriba en él algo diferente, siempre leo el valor inicial.

Alguien podría mirarse estos dos prgs y decirme qué estoy haciendo mal? (ambos se compilan con Buildh.bat)

El programa que captura:
Code:

//----------------------------------------------------------------------------//
// Capt.prg - Prueba de captura de otra ventana
//----------------------------------------------------------------------------//
#include "FiveWin.ch"
#define GW_CHILD 5
#define GW_HWNDNEXT 2

FUNCTION Main()
LOCAL oWnd, hWnd, hCtrl, cClassName, cTitle
cTitle := PADR("TEST", 200)
IF MsgGet( "Entre titulo de una ventana abierta", "Titulo:", @cTitle)
hWnd := FindWindow( 0, ALLTRIM(cTitle))
IF hWnd <= 0
MsgInfo("No puedo capturar esa ventana")
ELSE
hCtrl := GetWindow( hWnd, GW_CHILD )
WHILE hCtrl != 0
cClassName := Upper(GetClassName(hCtrl))
IF cClassName = "EDIT"
? cClassName+" "+GetWindowText(hCtrl)
ENDIF
hCtrl = GetWindow( hCtrl, GW_HWNDNEXT )
END
ENDIF
ENDIF
RETURN NIL



y el programa cuyos gets quiero capturar:

Code:

// Test.prg
#include 'FIVEWIN.CH'
FUNCTION Main()
LOCAL oWnd, oGet1, oGet2, cGet1, cGet2
DEFINE WINDOW oWnd FROM 0,0 TO 12,35 TITLE 'Test'
cGet1 := "Hola "
cGet2 := "Bye "
@ 10,10 BUTTON "Button 01" SIZE 100,20 PIXEL OF oWnd ACTION MsgInfo("Button 01")
@ 40,10 GET oGet1 VAR cGet1 SIZE 100,20 PIXEL OF oWnd
@ 70,10 GET oGet2 VAR cGet2 SIZE 100,20 PIXEL OF oWnd
ACTIVATE WINDOW oWnd
RETURN NIL

Gracias,

Rafael

Posted: Tue Jan 17, 2006 12:54 pm
by Rafael Clemente
Lo siento: Aquí está el fuente de los dos programas anteriores, formateado como código:

Code: Select all

//----------------------------------------------------------------------------/
// Capt.prg - Prueba de captura de otra ventana
//----------------------------------------------------------------------------/
#include "FiveWin.ch"
#define GW_CHILD      5
#define GW_HWNDNEXT   2

FUNCTION Main()
LOCAL oWnd, hWnd, hCtrl, cClassName, cTitle
cTitle := PADR("TEST", 200)
IF MsgGet( "Entre titulo de una ventana abierta", "Titulo:", @cTitle)
   hWnd := FindWindow( 0, ALLTRIM(cTitle))
   IF hWnd <= 0
      MsgInfo("No puedo capturar esa ventana")
   ELSE
      hCtrl := GetWindow( hWnd, GW_CHILD )
      WHILE hCtrl != 0
            cClassName := Upper(GetClassName(hCtrl))
            IF cClassName = "EDIT"
               ? cClassName+"  "+GetWindowText(hCtrl)
            ENDIF
            hCtrl = GetWindow( hCtrl, GW_HWNDNEXT )
      END
   ENDIF
ENDIF
RETURN NIL

Code: Select all

//  Test.prg
#include 'FIVEWIN.CH'
FUNCTION Main()
LOCAL  oWnd, oGet1, oGet2, cGet1, cGet2
DEFINE WINDOW oWnd FROM 0,0 TO 12,35 TITLE 'Test'
cGet1 := "Hola        "
cGet2 := "Bye         "
@ 10,10  BUTTON "Button 01"  SIZE 100,20 PIXEL OF oWnd ACTION MsgInfo("Button 01")
@ 40,10  GET oGet1 VAR cGet1 SIZE 100,20 PIXEL OF oWnd
@ 70,10  GET oGet2 VAR cGet2 SIZE 100,20 PIXEL OF oWnd
ACTIVATE WINDOW oWnd
RETURN NIL

Posted: Tue Jan 17, 2006 7:09 pm
by Antonio Linares
Rafael,

Acabamos de probarlo, usando Harbour, y funciona correctamente:

Image

Posted: Tue Jan 17, 2006 7:20 pm
by Rafael Clemente
Antonio:
Sí, con el Bye de inicialización funciona. Pero intenta cambiar el Bye por cualquier otra cosa y captura. A mí me sigue dando "Bye"
Rafael

Posted: Tue Jan 17, 2006 7:29 pm
by Antonio Linares
Rafael,

Es bastante extraño, es como si Windows guardase esa información en un buffer interno, porque si cambias esta línea en test.prg:

@ 10,10 BUTTON "Button 01" SIZE 100,20 PIXEL OF oWnd ACTION MsgInfo(GetWindowText( oGet2:hWnd ))

verás que muestra el texto del GET correctamente.

Vas a tener que intentar capturar los datos usando otro sistema: el mensaje WM_COPYDATA. Tienes un ejemplo en samples\copy_16_32\fwcopy16.prg. El ejemplo es para 16 bits y habría que adaptarlo un poco para 32 bits.

Posted: Tue Jan 17, 2006 8:42 pm
by Paco Garcia
No será que no has pasado de Get, osea que has escrito pero el Get no ha perdido el foco y no ha hecho el SetWindowText interno que hace y lo único que tiene es el texto en pantalla.

Intenta dar el foco a otro control, osea que el cursor no esté en el Get sino en otro control.

Posted: Tue Jan 17, 2006 8:47 pm
by Rafael Clemente
Paco:
No. He hecho pruebas pulsando Return y Tab después de entrar el dato, y el problema persiste.

Si quieres probarlo tú mismo, el código que he puesto más arriba te permitirá ver el problema.
Saludos
Rafael

Posted: Tue Jan 17, 2006 8:49 pm
by Rafael Clemente
Antonio:
Me he mirado fwcopy16 pero me temo que ese nivel de C supera lo que yo me atrevo a hacer. Además, ese ejemplo parece que es para copiar datos de mi aplicación a otra ventana y yo necesito justo lo contrario: "Leer" de la otra ventana

Seguiremos dándole vueltas, porque tengo un cliente esperando que le diga algo... Saludos,
Rafael

WM_COPYDATA

Posted: Thu Jan 19, 2006 8:22 am
by Paco Garcia
Hola Rafael

Existen varias formas de comuncar dos aplicaciones. Una de ellas es utilizando la capacidad de las ventanas de recibir mensajes. Ya sabes que nuestros prorgramas a bajo nivel estan sembrados de SendMessage( hWnd,.... ) que son descifrados en el bucle de mensajes de Windows y mas concretamente en nuestras aplicaciones en el método HandleEvent.

Cuando tu inspeccionas el get estas utilizando en hWnd de un control obtenido de alguna forma. Ahora lo haremos mas o menos igual.
Paso a exponer el código y luego explico

1ª parte

Code: Select all

#include "FIVEWIN.CH"


static oWnd
#define WM_COPYDATA                74



function MAIN()


   LOCAL oBtn, oBtn2, oGet, nVar1 := 1
   LOCAL oGet2, nVar2 := 1
   LOCAL oGet3, cVar := "Pulsa el boton Send y busca un alert"

   DEFINE WINDOW oWnd TITLE "Prueba WM_COPYDATA"

         @  10, 10 GET    oGet  VAR nVar1 SIZE 50, 18 PIXEL OF oWnd
         @  30, 10 GET    oGet2 VAR nVar2 SIZE 50, 18 PIXEL OF oWnd
         @  50, 10 GET    oGet3 VAR cVar SIZE 250, 18 PIXEL OF oWnd
         @  80, 10 BUTTON oBtn  PROMPT "Send" SIZE 50, 24 PIXEL OF oWnd ACTION SendInfo( nVar1, nVar2, cVar )
         @ 110, 10 BUTTON oBtn2 PROMPT "Fin" SIZE 50, 24 PIXEL OF oWnd ACTION oWnd:End()


   ACTIVATE WINDOW oWnd

RETURN nil

function SendInfo( nVar, nVar2, cVar )
local hWnd := FindWindow(0,"Escuchando" )
// BUSCAS EL HANDLE DE LA VENTANA CON EL NOMBRE

DEFAULT nVar  := 1
DEFAULT nVar2 := 1
DEFAULT cVar  := ""


if hWnd != 0
   if cVar == ""
      Enviar( oWnd:hWnd, hWnd, 101, nVar, nVar2, cVar )
   else
      Enviar( oWnd:hWnd, hWnd, 100, nVar, nVar2, cVar )
   endif
else
   MsgInfo( "No encontre la ventana" )
endif

return nil

#pragma BEGINDUMP
#include "windows.h"
#include "hbapi.h"

// AQUI TE CREAS LA ESTRUCTURA QUE QUIERAS CON LOS DATOS QUE QUIERAS PASAR
typedef struct tagMYREC
{
   HWND hWndOrigen;
   char  s1[250];
   int   nFila;
   int   nColumna;
} MYREC;




HB_FUNC( ENVIAR )
{
   HWND hWndOrigen = ( HWND ) hb_parnl( 1 );
   HWND hWndDestino = ( HWND ) hb_parnl( 2 );
   int nMsg = hb_parni( 3 ); // <<< IDENTIFICADOR DEL MENSAJE PARA QUE DESDE
                             // LA VENTANA DESTINO DECIDAS LO QUE HACER EN ESTE CASO
   COPYDATASTRUCT MyCDS;
   MYREC MyRec;

   // AQUI LE DAS VALOR A LOS DATOS DE LA ESTRUCTURA
   MyRec.hWndOrigen = hWndOrigen;
   MyRec.nFila = hb_parni( 4 );
   MyRec.nColumna = hb_parni( 5 );
   strcpy( MyRec.s1, hb_parc( 6 ) );

//
// Fill the COPYDATA structure
//
   MyCDS.dwData = nMsg;
   MyCDS.cbData = sizeof( MyRec );  // size of data
   MyCDS.lpData = &MyRec;

   // SE LO ENVIAS A LA VENTANA DESTINO SIEMPRE DE ESTA FORMA
   SendMessage( hWndDestino, WM_COPYDATA,(WPARAM)(HWND) hWndOrigen,(LPARAM) (LPVOID) &MyCDS );
   hb_ret();
}

HB_FUNC( RECIBIR )
{
   PCOPYDATASTRUCT pMyCDS;
   pMyCDS = (PCOPYDATASTRUCT) hb_parnl( 1 );

   // RECIBES LOS DATOS Y LOS DEVUELVES AL HANDLEEVENT DE LA VENTANA
   // SI QUIERES QUE LA COMUNICACIÓN SEA EN LOS DOS SENTIDOS
   // TENDRIAS QUE TENER AQUI TAMBIEN EL HANDLEEVENT REDEFINIDO

   hb_reta( 5 );
   hb_stornl( (long)((MYREC *)(pMyCDS->lpData))->hWndOrigen, -1, 1 );
   hb_storni( pMyCDS->dwData, -1, 2 );
   hb_storni( ((MYREC *)(pMyCDS->lpData))->nFila, -1, 3 );
   hb_storni( ((MYREC *)(pMyCDS->lpData))->nColumna, -1, 4 );
   hb_storc ( ((MYREC *)(pMyCDS->lpData))->s1, -1, 5 );

}





#pragma ENDDUMP

Esta sería la aplicación que solicita datos a otra aplicación (ventana)

2ª Parte
La aplicación que recibe el mensaje y que lo procesa

Code: Select all

#include "FIVEWIN.CH"
#define WM_COPYDATA                74

static aDatos := {}


PROCEDURE MAIN()

   LOCAL oWnd, oMenu

   oWnd := TWindow2():New(0,0,20,20,"Escuchando",,oMenu,,,,,,,,,,!.F.,!.F.,!.F.,!.F.,.F. )
   ACTIVATE WINDOW oWnd ON INIT WndCenter( oWnd:hWnd )

RETURN

//--------------------------------------------------------------------


CLASS TWindow2 FROM TWindow

      CLASSDATA lRegistered AS LOGICAL

      METHOD New( nTop, nLeft, nBottom, nRight, cTitle, nStyle, oMenu,;
                  oBrush, oIcon, oParent, lVScroll, lHScroll,;
                  nClrFore, nClrBack, oCursor, cBorder, lSysMenu, lCaption,;
                  lMin, lMax, lPixel ) CONSTRUCTOR

      METHOD HandleEvent( nMsg, nWParam, nLParam )

ENDCLASS

METHOD New( nTop, nLeft, nBottom, nRight, cTitle, nStyle, oMenu,;
                  oBrush, oIcon, oParent, lVScroll, lHScroll,;
                  nClrFore, nClrBack, oCursor, cBorder, lSysMenu, lCaption,;
                  lMin, lMax, lPixel ) CLASS TWindow2




return super:New( nTop, nLeft, nBottom, nRight, cTitle, nStyle, oMenu,;
                  oBrush, oIcon, oParent, lVScroll, lHScroll,;
                  nClrFore, nClrBack, oCursor, cBorder, lSysMenu, lCaption,;
                  lMin, lMax, lPixel )


METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TWindow2

local aReturn
local hWndOrigen
local nCDMsg
local nFila, nColumna, cText


if nMsg == WM_COPYDATA

   aReturn    := Recibir( nLParam )
   hWndOrigen := aReturn[1]
   nCDMsg     := aReturn[2]
   nFila      := aReturn[3]
   nColumna   := aReturn[4]
   cText      := aReturn[5]

   do case
      case nCDMsg == 100

           ? "Mensaje " + str( nCDMsg ), nFila, nColumna, cText,"El titulo de la ventana que ha pintado esto es",::cTitle
           return 0

      case nCDMsg == 101
           ? "Mensaje " + str( nCDMsg ), nFila, nColumna, cText,"El titulo de la ventana que ha pintado esto es",::cTitle

           return 0
      // case nCDMsg == ... lo que se quiera y cuantos se quieran

   endcase


endif

return super:HandleEvent( nMsg, nWParam, nLParam )



*****************************************************************************
******************************************************************************
******************************************************************************
******************************************************************************
#pragma BEGINDUMP
#include "windows.h"
#include "hbapi.h"

// AQUI TE CREAS LA ESTRUCTURA QUE QUIERAS CON LOS DATOS QUE QUIERAS PASAR
typedef struct tagMYREC
{
   HWND hWndOrigen;
   char  s1[250];
   int   nFila;
   int   nColumna;
} MYREC;




HB_FUNC( ENVIAR )
{
   HWND hWndOrigen = ( HWND ) hb_parnl( 1 );
   HWND hWndDestino = ( HWND ) hb_parnl( 2 );
   int nMsg = hb_parni( 3 ); // <<< IDENTIFICADOR DEL MENSAJE PARA QUE DESDE
                             // LA VENTANA DESTINO DECIDAS LO QUE HACER EN ESTE CASO
   COPYDATASTRUCT MyCDS;
   MYREC MyRec;

   // AQUI LE DAS VALOR A LOS DATOS DE LA ESTRUCTURA
   MyRec.hWndOrigen = hWndOrigen;
   MyRec.nFila = hb_parni( 4 );
   MyRec.nColumna = hb_parni( 5 );
   strcpy( MyRec.s1, hb_parc( 6 ) );

//
// Fill the COPYDATA structure
//
   MyCDS.dwData = nMsg;
   MyCDS.cbData = sizeof( MyRec );  // size of data
   MyCDS.lpData = &MyRec;

   // SE LO ENVIAS A LA VENTANA DESTINO SIEMPRE DE ESTA FORMA
   SendMessage( hWndDestino, WM_COPYDATA,(WPARAM)(HWND) hWndOrigen,(LPARAM) (LPVOID) &MyCDS );
   hb_ret();
}

HB_FUNC( RECIBIR )
{
   PCOPYDATASTRUCT pMyCDS;
   pMyCDS = (PCOPYDATASTRUCT) hb_parnl( 1 );

   // RECIBES LOS DATOS Y LOS DEVUELVES AL HANDLEEVENT DE LA VENTANA
   // SI QUIERES QUE LA COMUNICACIÓN SEA EN LOS DOS SENTIDOS
   // TENDRIAS QUE TENER AQUI TAMBIEN EL HANDLEEVENT REDEFINIDO

   hb_reta( 5 );
   hb_stornl( (long)((MYREC *)(pMyCDS->lpData))->hWndOrigen, -1, 1 );
   hb_storni( pMyCDS->dwData, -1, 2 );
   hb_storni( ((MYREC *)(pMyCDS->lpData))->nFila, -1, 3 );
   hb_storni( ((MYREC *)(pMyCDS->lpData))->nColumna, -1, 4 );
   hb_storc ( ((MYREC *)(pMyCDS->lpData))->s1, -1, 5 );

}

#pragma ENDDUMP

Con un poco de ingenio puedes hacer que las dos aplicaciones sean capaces de "hablarse" y contarse las cosas que necesites.

Observa que en la segunda aplicación he redefinido el Método HandleEvent de la nueva clase ventana para poder evaluar el mensaje WM_COPYDATA.

http://www.google.es/search?hl=es&q=wm_ ... ogle&meta=

Un saludo

[/code]

Posted: Thu Jan 19, 2006 2:31 pm
by Rafael Clemente
Paco:
Muchísimas gracias por tu respuesta, que más bien es todo un manual de cómo conseguir conexión entre dos aplicaciones. Me lo estudio y te digo los resultados.
Repito, muchas gracias por todo el trabajo que te has tomado. Un saludo,
Rafael