Entra

View Full Version : [C++] Simulare Click mouse/Immagini


Valas
09-06-2008, 18:04
Allora raga devo fare un programma abbastanza complesso, ho quasi finito ma mi sono bloccato su un particolare aspetto.
Innanzitutto premetto che stò utilizzando Visual Studio 2008 e programmo in C++.

1- Mi servirebbe una funzione che simula il click sinistro del mouse ogni tot secondi.
Su internet ho trovato alcune funzioni ma non mi vanno...

2- Ho bisogno di una funzione che cambia finestra di windows (ovvero va alla finestra chiamata tal de tali) e catturi un immagine:
un quadrato che va da X1,Y1 a X2,Y2 della finestra tal de tali.

Dopodichè dovrebbe confrontare questa immagine catturata con varie immagini in archivio e vedere se sono perfettamente identiche.
Non ne ho idea di come si fa...

PS: Nn pensate male non mi serve per niente di losco :p


Grazie in anticipo per qualunque aiuto e suggerimento!:D

Valas
10-06-2008, 10:06
Up


Nessuno può aiutarmi? :confused:
plssssssssssssssssssssssss

variabilepippo
10-06-2008, 10:37
Nessuno può aiutarmi?


Passi per il banale punto 1) (basta inviare un messaggio WM_LBUTTONDOWN seguito da un WM_LBUTTONUP, per esempio) al resto del post non si può rispondere in 2 righe (soprattutto se *non hai idea* di come farlo tu sa solo) e probabilmente non sono in molti ad avere tempo/voglia di farlo. ;)

Valas
10-06-2008, 16:13
Qualcosa di più sul punto 1?:D

In particolare servirebbe il codice di una funzione in C++ così:

Click(WindowName, X, Y);

Ovvero dando il nome di una finestra e le coordinate XY, relative al punto dove clikkare della finestra, effettui subito un Click....

ringrazio in anticipo per qualunque aiuto :)

variabilepippo
10-06-2008, 16:23
In particolare servirebbe il codice di una funzione in C++ così:


Sono 3 righe di codice in croce: con la macro MakeLParam ottieni il punto partendo dalle coordinate, poi invochi PostMessage, la prima volta con WM_LBUTTONDOWN (passi come LParam il punto sul quale cliccare), la seconda con WM_LBUTTONUP. Il primo parametro della PostMessage è l'handle della finestra la cui window procedure riceverà il messaggio.

|_ArgH_|
10-06-2008, 18:24
The mouse_event function synthesizes mouse motion and button clicks.

Windows NT/2000/XP: This function has been superseded. Use SendInput instead.

direttamente dall'SDK di zio Bill.

PS: mouse_event su winxp funziona non so su Vista e successivi

Valas
12-06-2008, 17:31
ho risolto il punto uno, ma per il punto 2 che io sappia l'unica soluzione è di prendere le due immagini e confrontarle con getpixel()...
un pixel alla volta : \ mi sà che è lunga la cosa.... anche perchè mi dicevano che come funzione è abbastanza lenta...
Cmq non saprei nella pratica come aprire l'immagine che ho salvato(magari è anche semplice)

Qualche altra soluzione? :|

Valas
15-06-2008, 17:51
Raga ho un problema con getpixel perchè mi restituisce sempre lo stesso valore: 4294967295
che per quanto capito è un valore "errore".

codice:
POINT pt;
HWND GHandle()
{
return FindWindow(NULL, "Finestra");
}

HDC hdc = GetDC(GHandle());

GetCursorPos(&pt);
GetPixel(hdc,pt.x,pt.y)

71104
15-06-2008, 18:15
non serve che confronti pixel per pixel con GetPixel, anche perché ti hanno detto bene: ci metteresti una vita. devi ottenere i bits di ciascuna immagine con GetDIBits (http://msdn.microsoft.com/en-us/library/ms532334.aspx) e confrontare i due buffers di memoria con una semplice memcmp.

Valas
15-06-2008, 18:32
Perfetto grazie mille adesso ci lavoro.

In ogni caso sai come mai mi dà questo errore? Perchè lo devo cmq usare una volta...

Valas
15-06-2008, 19:33
Una cosa:

Io devo prelevare un immagine rettangolare che parte da XY e arriva a X2Y2, di una specifica finestra!

Poi se ce l'ho riesco a confrontarla ma come faccio ad averla? °_°
Ho trovato solo funzioni che catturano l'intera immagine di finestre....

71104
15-06-2008, 19:40
In ogni caso sai come mai mi dà questo errore? probabilmente perché le coordinate che specifichi stanno fuori dal rettangolo della finestra: GetCursorPos restituisce coordinate relative al riferimento cartesiano dello schermo (origine degli assi in alto a sinistra, tipicamente fuori dalla tua finestra), GetPixel invece vuole coordinate relative al riferimento della finestra (origine sull'angolo superiore sinistro della finestra).

per convertire usa ScreenToClient (http://msdn.microsoft.com/en-us/library/ms533179.aspx) o ClientToScreen (http://msdn.microsoft.com/en-us/library/ms532670.aspx).

71104
15-06-2008, 19:45
Una cosa:

Io devo prelevare un immagine rettangolare che parte da XY e arriva a X2Y2, di una specifica finestra!

Poi se ce l'ho riesco a confrontarla ma come faccio ad averla? °_°
Ho trovato solo funzioni che catturano l'intera immagine di finestre.... crea un nuovo DC compatibile con quella della finestra usando CreateCompatibleDC, crea un bitmap con CreateCompatibleBitmap e selezionacelo con SelectObject, trasferisci verso questo nuovo DC il rettangolo di interesse con BitBlt, preleva i dati con GetDIBits. ora scusa ma metterti tutti i link a MSDN mi secca un po', te le cerchi da solo chè tanto stanno tutte qui (http://msdn.microsoft.com/en-us/library/ms536795(VS.85).aspx). :D

Valas
15-06-2008, 19:53
probabilmente perché le coordinate che specifichi stanno fuori dal rettangolo della finestra: GetCursorPos restituisce coordinate relative al riferimento cartesiano dello schermo (origine degli assi in alto a sinistra, tipicamente fuori dalla tua finestra), GetPixel invece vuole coordinate relative al riferimento della finestra (origine sull'angolo superiore sinistro della finestra).


Escluderei perchè ho posizionato la finestra in posizione 0,0 e poi ho fatto molti tentativi col cursore ovunque sullo schermo...

Grazie adesso provo : D tanto su msdn se sò il nome delle funzioni li trovo fast ty

71104
15-06-2008, 21:39
Escluderei perchè ho posizionato la finestra in posizione 0,0 e poi ho fatto molti tentativi col cursore ovunque sullo schermo... nel caso generale non mi viene in mente altro: suppongo che l'HDC che passi alla GetPixel sia valido e che abbia un bitmap selezionato. vedi se GetLastError restituisce informazioni utili, e soprattutto vedi se la prima chiamata che fallisce è proprio la GetPixel, e non magari la GetDC.

EDIT - o magari la FindWindow :D sicuro di averla trovata sta finestra?


Grazie adesso provo : D tanto su msdn se sò il nome delle funzioni li trovo fast ty occhio a non prendere la documentazione di Windows CE: me la ritrovo sempre tra le pa**e nei risultati del motore di ricerca (Win32 è praticamente duplicato).

Valas
15-06-2008, 22:24
scusa ma mi sono incasinato di brutto...
quello che ho capito:
HWND GHandle()
{
return FindWindow(NULL, "Finestra");
}

HDC hdc = GetDC(GHandle());

x = 100; y = 100;
HDC hdc2 = CreateCompatibleDC(hdc);

HBITMAP bitmap = CreateCompatibleBitmap(hdc2, 250, 250);

SelectObject(
hdc, // handle to DC
bitmap // handle to object
);
BitBlt(
hdc2, // handle to destination DC
x, // x-coord of destination upper-left corner
y, // y-coord of destination upper-left corner
250, // width of destination rectangle
250, // height of destination rectangle
hdc, // handle to source DC
x, // x-coordinate of source upper-left corner
y, // y-coordinate of source upper-left corner
MERGECOPY
);


// qua proprio mi perdo nel nulla
LPVOID bits;
LPBITMAPINFO bitm;

GetDIBits(
hdc2, // handle to DC
bitmap, // handle to bitmap
NULL, // first scan line to set
NULL, // number of scan lines to copy
bits, // array for bitmap bits
bitm, // bitmap data buffer
DIB_RGB_COLORS // RGB or palette index
};

fatto ciò (che sarà sicuramente sbagliato)
Come faccio a salvare l'immagine che ne esce in maniera permanente e poi ad aprirne una mia e a confrontarla? Se mi fate vedere il codice ve ne sarei grato grazie... (scusate l'ignoranza ma per me è un aspetto completamente nuovo)


nel caso generale non mi viene in mente altro: suppongo che l'HDC che passi alla GetPixel sia valido e che abbia un bitmap selezionato. vedi se GetLastError restituisce informazioni utili, e soprattutto vedi se la prima chiamata che fallisce è proprio la GetPixel, e non magari la GetDC.
la finestra la trova sicuramente perchè gli chiedo sempre di metterla in primo piano appena parte, e il GetDC restituisce
tipo 880119B8, quindi direi che funziona.

71104
16-06-2008, 10:57
Come faccio a salvare l'immagine che ne esce in maniera permanente http://msdn.microsoft.com/en-us/library/ms532311(VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms532340(VS.85).aspx


e poi ad aprirne una mia e a confrontarla? caricare un'immagine da file è un dilemma a causa del numero di formati che esistono per la memorizzazione delle immagini. se devi leggere un file .bmp basta che usi LoadImage (http://msdn.microsoft.com/en-us/library/ms648045(VS.85).aspx), altrimenti devi o sviluppare del codice ad-hoc per leggere lo specifico formato o utilizzare una libreria di terze parti, come la libpng (http://www.libpng.org/).


Se mi fate vedere il codice ve ne sarei grato grazie... (scusate l'ignoranza ma per me è un aspetto completamente nuovo) ora non ci allarghiamo :D non ho tutto questo tempo. io ti posso dare delle indicazioni e posso linkarti le pagine di documentazione, poi sulla documentazione te la cavi da solo; anche perché trattandosi di documentazione molto vecchia ormai è "matura": la Microsoft ci lavora e la migliora da parecchi anni (decenni direi) e si tratta anche di argomenti ben conosciuti.

Valas
16-06-2008, 11:36
Ok grazie, ma il codice che ho scritto è giusto? Mi sembra assurdo che non abbia fatto qualche casino:confused:

71104
16-06-2008, 17:12
Ok grazie, ma il codice che ho scritto è giusto? Mi sembra assurdo che non abbia fatto qualche casino:confused: ne hai fatti una valanga infatti :Prrr:
pare che alla documentazione tu abbia dato solo un'occhiata fugace. non essere assetato di risultati perché Win32 è complesso e con la fretta non ne avrai mai: non ci sono scorciatoie, leggi tutto quello che devi leggere e vedrai che non ti... "perderai nel nulla".

qualche osservazione:
- controlla sempre i valori di ritorno per eventuali errori: se si è verificato un errore non continuare, libera tutte le risorse allocate ed esci.
- come mai nella BitBlt hai specificato x e y (cioè, 100-100) come coordinate dell'uper-left corner del rettangolo di destinazione? non dovrebbero essere 0-0 ?
- sempre nella BitBlt, non sarebbe meglio SRCCOPY? come mai hai passato MERGECOPY?
- quando devi passare uno zero numerico evita di usare la costante NULL: quella in genere si usa solo per i puntatori.
- alla GetDIBits stai chiedendo di restituirti precisamente zero scanlines, cioè le stai chiedendo di non copiarti nulla nel buffer.
- non hai inizializzato ne' la variabile bits ne' la variabile bitm.

Valas
16-06-2008, 20:35
Grazie per la pazienza!
Innanzitutto ti dico che sono più niubbo di quanto sembro... e sembro parecchio niubbo!

nella BitBlt ho specificato per provare 100-100 perchè sono le coordinate dove devo iniziare il rettangolo da copiare. non chiedermi perchè l'ho messo 2 volte...
Il fatto è che già di inglese sò poco e quindi su msdn capisco il 50% delle cose...

In ogni caso così è troppo complicato per i miei gusti, ho risolto il problema del getpixel che insensatamente il problema era che il nome della finestra era "finestra " e non "finestra"...
Ovvero se ci aggiungo uno spazio in fondo va se no no....
Anche se alla fine la funzione che mi metteva in primo piano la finestra funzionava cmq.... :mbe:


Comunque ho deciso di usare GetPixel prelevando dei pixel "campione" tipo 10 pixel di cui confronto il colore, se sono uguali allora ritengo tutta l'immagine uguale...
se non è più veloce sicuramente è meno snervante per la mia testolina : P