FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour O.T.: C贸mo capturar objetos individuales
Posts: 365
Joined: Sat Oct 08, 2005 07:59 PM
O.T.: C贸mo capturar objetos individuales
Posted: Tue Feb 28, 2006 02:52 PM

Un amigo me ense帽贸 una versi贸n antigua del PaintShop 4 (versi贸n de 1997...) Este programa tiene una interesante funci贸n de captura de objetos, es decir, permite "recortar" y guardar como imagen los objetos de otra aplicaci贸n. Es especialmente 煤til para hacer manuales o helps, ya que permite capturar im谩genes de botones, listboxes, e incluso says y gets.

Lo curioso es que la identificaci贸n del objeto es autom谩tica e inmediata. Basta con poner el cursor sobre 茅l. El Paint Shop lo identifica como un objeto y lo marca con un recuadro negro. Pulsa una tecla de funci贸n y su imagen queda capturada en el formato que deses...

Mi pregunta es: 驴Alguien sabe c贸mo implem
entar algo semejante desde FWH? Quiero decir, lo de que un prorgama de FWH sea capaz de identificar y "recortar" los controles que componen otra aplicaci贸n. Hasta ahora conseguido capturar como BMPs pantallas enteras y ventanas de otras aplicaciones. Eso no es problema. Lo que no s茅 por d贸nde empezar es lo de identificar los controls individuales, en especial, Says y Gets

驴Alguna sugerencia?

Rafael

Posts: 172
Joined: Fri Oct 07, 2005 12:00 PM
O.T.: C贸mo capturar objetos individuales
Posted: Tue Feb 28, 2006 05:46 PM
隆隆 compa帽ero !!!

ahi va:


      pt := GetCursorPos()
      hWnd := ::SmallestWindowFromPoint( pt )

/*****************************************************************************************/
  METHOD SmallestWindowFromPoint( point ) CLASS TSpy
/*****************************************************************************************/
	local rect, rcTemp
	local hParent, hWnd, hTemp

	hWnd := WindowFromPoint( point[2], point[1] )
	if hWnd != 0

		rect := GetWndRect( hWnd )
		hParent := GetParent( hWnd )

		// Has window a parent?
		if hParent != 0

			// Search down the Z-Order
			hTemp := hWnd
			do while .t.

				hTemp  := GetWindow( hTemp, GW_HWNDNEXT )

				// Search window contains the point, hase the same parent, and is visible?
				rcTemp := GetWndRect( hTemp )
				if PtInRect( point[1],point[2], rcTemp  ) .and. GetParent(hTemp) == hParent .and. IsWindowVisible(hTemp)

					// Is it smaller?
					if (rcTemp[4] - rcTemp[2]) * (rcTemp[3] - rcTemp[1]) < ((rect[4] - rect[2]) * (rect[3] - rect[1]))
						// Found new smaller window!
						hWnd := hTemp
						rect := GetWndRect(hWnd)
					endif
				endif
				if hTemp == 0
				   exit
				endif
			enddo
		endif
	endif

	return hWnd


Ya sabes, estoy de guardia :-) :-) :-)

Parte es de mi cosecha y parte del Google.

Un saludo
Posts: 365
Joined: Sat Oct 08, 2005 07:59 PM
O.T.: C贸mo capturar objetos individuales
Posted: Tue Feb 28, 2006 05:55 PM

Paco:
Es fant谩stico esto de tener un inform谩tico de guardia!!!! :D
Me lo estudio y te digo algo.
10E6 de gracias!!!
Rafael

Posts: 365
Joined: Sat Oct 08, 2005 07:59 PM
O.T.: C贸mo capturar objetos individuales
Posted: Tue Feb 28, 2006 08:47 PM

Paco:
Lo acabo de probar a fondo. FORMIDABLE!!! Es exactamente lo que yo buscaba. Y pensar que he gastado un mont贸n de horas en pruebas in煤tiles...
Muchas gracias otra vez.
Rafael

Posts: 172
Joined: Fri Oct 07, 2005 12:00 PM
O.T.: C贸mo capturar objetos individuales
Posted: Tue Feb 28, 2006 09:34 PM

Ya, yo tambien lo habia buscado exactamente igual y lo solucione hace ya una temporada larga. Por si te interesa se puede hacer muchas cosas con esto, por ejemplo:

  • inspeccionar las propiedades de los controles, ventanas, dialogos etc a nivel de API.
  • Mandar mensajes a una ventana que los recogera y procesar谩 de la forma que le programes.
  • sacar fotos, por supuesto
    y un monton de cosas mas

En cuanto al efecto de rect谩ngulo negro, usa el truco de una ventana estilo WS_POPUP que ocupe toda la pantalla y con la brocha NULL. De esta forma puedes pintar lo que quieras "sobre las ventanas" a base de obtener el hDC de la ventana transparente.

Un saludo

Paco (PDG)

:)

Posts: 365
Joined: Sat Oct 08, 2005 07:59 PM
O.T.: C贸mo capturar objetos individuales
Posted: Wed Mar 01, 2006 07:11 AM

Paco:
Una 煤ltima pregunta para dar el tema por cerrado (de momento... :wink: ).

Ya tengo tu receta funcionando. Puede capturar sin problemas los handles de los controles que componen otra aplicaci贸n. Con GetWindowText(hWnd) en un Say puedo leer el texto del Say; en un checkbox, puedo leer su prompt... 驴Hay alguna forma de leer el contenido de un Get? 驴Y de una casilla de un browse?
Saludos,

Rafael

Posts: 172
Joined: Fri Oct 07, 2005 12:00 PM
O.T.: C贸mo capturar objetos individuales
Posted: Wed Mar 01, 2006 08:21 AM
Hola

Que yo sepa sin mas, no. Lo que si que puedes hacer es preparar tus programas para que sean capaces de interpretar mensajes especiales que tu envies y en funci贸n de eso establecer un protocolo de comunicaci贸n entre dos aplicaciones. Por ejemplo con WM_COPYDATA.

Con este ejemplo puedes enviar y recibir datos de una aplicaci贸n a otra:

#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 );

}

HB_FUNC( REGISTERWINDOWMESSAGE )
{
     hb_retni( RegisterWindowMessage( ( LPCTSTR ) hb_parc(1)));
}

#pragma ENDDUMP


Luego con la funci贸n RegisterWindowMessage puedes registrar un mensaje en cada aplicaci贸n a nivel de Windows, asegurandote de que ese mensaje ser谩 煤nico en windows.

Luego en el HandleEvent de la ventana o del control capturas ese mensaje y estableces la comunicaci贸n entre la aplicaci贸n que escucha y la aplicaci贸n que espia.

    nMensaje := RegisterWindowMessage( "WM_MIMENSAJE" )

En HandleEvent tendr铆as que preguntar por if nMsg == nMensaje ...

Un saludo
Posts: 365
Joined: Sat Oct 08, 2005 07:59 PM
O.T.: C贸mo capturar objetos individuales
Posted: Wed Mar 01, 2006 08:57 AM

Paco:
Me estudiar茅 tu ejemplo pero me temo que ya empieza a superar mis habilidades. Adem谩s, lo que estaba intentando conseguir era leer una aplicaci贸n que no era m铆a (por ejemplo, una Contabilidad comercial) as铆 que dif铆cilmente la podr茅 preparar para que responda a mis mensajes.
Buscar茅 otro camino. De todas formas, gracias por tu ayuda. Hasta la pr贸xima, un saludo,

Rafael

Continue the discussion