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 Expand view
//----------------------------------------------------------------------------/
// 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 Expand view
// 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:
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 Expand view
#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 Expand view
#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_copydata&btnG=B%C3%BAsqueda+en+Google&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