C/C++ [C++] Utiliser la fonction GetPixel

Inscrit
15 Avril 2011
Messages
457
Reactions
1
#1
Bonjour, je programme un petit bot en C++ orienté objet pour m'entraîner mais je n'arrive pas à utiliser la fonction GetPixel pour faire une recherche de pixels.
Voici la doc de la fonction : http://msdn.microsoft.com/en-us/library ... 85%29.aspx
J'ai deux problèmes :
- La fonction retourne un DWORD appelé COLORREF, j'aimerais convertir ce DWORD en hexadécimal.
- La fonction utilise un HDC, je ne sais pas comment ça marche, je ne sais pas quoi mettre comme valeur, j'avais essayé de trouver une valeur avec AutoIt Windows Info mais ça marche pas :S De plus, lorsque je mets 0, la fonction me retourne toujours la même valeur, soit 4294967295.

Je m'en remets donc à vous ;)
 

FastFrench

Membre Actif
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#2
NicoMasterChief a dit:
Bonjour, je programme un petit bot en C++ orienté objet pour m'entraîner mais je n'arrive pas à utiliser la fonction GetPixel pour faire une recherche de pixels.
Voici la doc de la fonction : http://msdn.microsoft.com/en-us/library ... 85%29.aspx
J'ai deux problèmes :
- La fonction retourne un DWORD appelé COLORREF, j'aimerais convertir ce DWORD en hexadécimal.
Un DWORD peut être exprimé en binaire, en hexa, en octal, en décimal... cela ne change rien à la valeur du DWORD. C'est juste une question d'affichage.

DWORD MaCouleur = GetPixel(...);
if (MaCouleur == 0x00FFFFFF) // Si blanc...

// C'est pareil que
if (MaCouleur == 16777215) // Si blanc...


NicoMasterChief a dit:
- La fonction utilise un HDC, je ne sais pas comment ça marche, je ne sais pas quoi mettre comme valeur, j'avais essayé de trouver une valeur avec AutoIt Windows Info mais ça marche pas :S De plus, lorsque je mets 0, la fonction me retourne toujours la même valeur, soit 4294967295.

Je m'en remets donc à vous ;)
4294967295 s'exprime 0xFFFFFFFF en hexadécimal. Si tu castes ton DWORD dans un int, ça devient -1. Si tu avais cherché un peu, tu aurais trouvé facilement que c'est un code d'erreur.
http://msdn.microsoft.com/en-us/library/dd144909(v=VS.85).aspx
MSDN a dit:
Return value

The return value is the COLORREF value that specifies the RGB of the pixel. If the pixel is outside of the current clipping region, the return value is CLR_INVALID (0xFFFFFFFF defined in Wingdi.h).
Pour comprendre l'utilisation des Device Context (DC), je te conseille de trouver un bouquin ou un bon tuto traitant le sujet. Tu ne pourras pas réellement programmer une interface graphique en C++ sous Windows sans comprendre ces p'tites choses.

De plus, tu dis programmer en C++, et là tu nous parles de C.

Si tu veux programmer en C++, il te faut choisir une bibliothèque de classes et t'y tenir (STL, MFC...)

Toutes les fenêtres et les contrôles sont des fenêtre, et dérivent en principe de l'objet de base décrivant une fenêtre (CWnd en MFC par exemple). A partir de ton contrôle graphique tu peux remonter au handle de la fenêtre associée (hWnd). Cela te permet d'obtenir un DC, avec la fonction GetDC.
http://msdn.microsoft.com/en-us/library ... 71(v=vs.85).aspx
(si tu restes en C)

En MFC, tu utilises plutôt CWnd::GetDC(), dont héritent tous les contrôles et autres fenêtres.

Quand tu as fini d'utiliser un DC, tu dois toujours le libérer (ReleaseDC).

Quoi qu'il en soit, regarde systématiquement l'aide associée aux fonctions Windows que tu utilises sur le site MSDN. C'est la référence et tu auras toutes les réponses dans la plupart des cas.
http://msdn.microsoft.com/fr-fr/library/
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#3
Salut FF, merci de ta réponse. Mais tu me parles d'interface graphique, je ne veux pas faire d'interface graphique, je veux juste faire une recherche sur ce qui apparaît à l'écran (comme PixelSearch en AutoIt, que tu connais très bien).

Tu me parles aussi de programmation en C, mais j'en ai jamais fait donc si j'ai utilisé du C, c'était pas intentionnel ^^, sauf la fonction GetPixel est spécifique au C. Dans ce cas-là, je vais pas pouvoir l'utiliser.

Donc, j'aimerais savoir si, pour utiliser un HDC dans la fonction GetPixel, je dois utiliser une bibliothèque ou s'il n'y pas un moyen "d'esquiver" ça ? Parce que je ne veux pas m'aventurer dans la GUI, vu que je ne compte pas en faire. Si c'est pas possible, j'essaierai de me renseigner sur la MFC Library.




FastFrench a dit:
Quoi qu'il en soit, regarde systématiquement l'aide associée aux fonctions Windows que tu utilises sur le site MSDN. C'est la référence et tu auras toutes les réponses dans la plupart des cas.
http://msdn.microsoft.com/fr-fr/library/
C'est ce que je fais tout le temps, mais c'est dommage qu'il n'y est rien en français.
 

FastFrench

Membre Actif
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#4
NicoMasterChief a dit:
FastFrench a dit:
Quoi qu'il en soit, regarde systématiquement l'aide associée aux fonctions Windows que tu utilises sur le site MSDN. C'est la référence et tu auras toutes les réponses dans la plupart des cas.
http://msdn.microsoft.com/fr-fr/library/
C'est ce que je fais tout le temps, mais c'est dommage qu'il n'y est rien en français.
En général, seules les vieilles fonctions C ne sont pas traduites. Les fonctions plus récentes le sont.
Quoi qu'il en soit, pour avoir un HDC, il te faut une fenêtre.
Tu peux éventuellement utiliser
Code:
GetForegroundWindow();
A la limite, si c'est la totalité de l'écran que tu veux, tu peux utiliser :
Code:
GetDC( NULL )
ou
Code:
GetDC( HWND_DESKTOP )
Attention cependant, avec les OS récents tu peux avoir des droits trop limités pour accéder aux fenêtres qui n'appartiennent pas à ton application (lance en admin en cas de problème).
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#5
J'ai utilisé GetDC(NULL) et GetDC(HWND_DESKTOP), ça marche bien mais c'est super long ! Avec un hdc, ça met plusieurs heures pour s'exécuter ^^'

Code:
bool Paysan::recherche_cereale()
{
    int x1=330;
    int y1=60;
    int x2=1270;
    int y2=710;
    DWORD couleur;
    HDC hdc=GetDC(NULL);
    for (x1;x1<x2;x1++)
    {
        y1=60;
        for (y1;y1<y2;y1++)
        {
            couleur=GetPixel(hdc,x1,y1);
            //cout<<couleur<<endl;
        }
    }
    return 0;
}
 

FastFrench

Membre Actif
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#6
Pas étonnant. Ca n'a pas de raisons d'être nettement plus rapide qu'en AutoIt. GetPixel n'est pas du tout approprié pour une utilisation intensive. Pour aller plus vite, tu peux t'inspirer du code que ToOnS a transmis récemment.
Ou alors, tu utilises FFFastFind.dll.

Un GetPixel s'execute en environ 15ms. Soit environ 2,5 heures dans ton exemple.
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#7
On peut utiliser FastFind en C++ ? Ah beh je vois pas pourquoi je m'emmerde avec GetPixel ou PixelSearch ^^ (pour info : PixelSearch crash quand le pixel recherchée n'est pas présent à l'écran).
FastFind est beaucoup plus rapide j'espère ?

Mais je ne sais pas comment inclure FastFind sans header, tu parles d'un header ici, faut-il que je crée un header et que je copie tous les fonctions WINAPI que tu as listé ?
 

FastFrench

Membre Actif
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#8
En principe le .h est inclus dans les dernières versions de FastFind (enfin je crois).
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#9
Arf non, moi je ne l'ai pas :(

D'ailleurs, j'ai téléchargé à peu près toutes les versions, je n'ai jamais vu de fichier .h, je pense que c'est un oubli de ta part (ou alors j'ai mon ordi qui est allergique aux headers^^').
 

FastFrench

Membre Actif
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#10
Hello,

voici le header pour la version 2.0 de Fastfind :
Code:
/*
 * Functions exported in FastFind.dll - version 2.0
 * WINAPI is defined as follows : #define WINAPI _stdcall
 * COLORREF is defined as follows : typedef DWORD COLORREF
 */

// Exclusion areas
void WINAPI AddExcludedArea(int x1, int y1, int x2, int y2);
bool WINAPI IsExcluded(int x, int y, HWND hWnd);
void WINAPI ResetExcludedAreas();

// Configuration
void WINAPI SetDebugMode(int NewMode);
void WINAPI SetHWnd(HWND NewWindowHandle, bool bClientArea);
LPCTSTR WINAPI GetLastErrorMsg();
LPCTSTR WINAPI FFVersion(void);

// Basic functions
int WINAPI GetPixel(int X, int Y, int NoSnapShot);
int WINAPI ColorPixelSearch(int &XRef, int &YRef, int ColorToFind, int NoSnapShot);
int WINAPI GetPixelFromScreen(int x, int y, int NoSnapShot); // Idem GetPixel, but with screeen coordinates

// Snapshots
int WINAPI SnapShot(int aLeft, int aTop, int aRight, int aBottom, int NoSnapShot);

// List of colors management
int WINAPI AddColor (COLORREF NewColor);
int WINAPI RemoveColor (COLORREF NewColor);
void WINAPI ResetColors ();

// Search function, for multiple colors (color list should be defined first)
int WINAPI ColorsPixelSearch(int &XRef, int &YRef, int NoSnapShot);

// ColorsSearch is close to ColorSearch, except it can look for several colors instead of only one. 
int WINAPI ColorsSearch(int SizeSearch, int &NbMatchMin, int &XRef, int &YRef, int NoSnapShot);

// Most generic search function : called in most case. 
int WINAPI GenericColorSearch(int SizeSearch, int &NbMatchMin, int &XRef, int &YRef, int ColorToFind, int ShadeVariation, int NoSnapShot);

// New vith verion 1.4 : more powerful search function : looks for 'spots' instead of pixels
int WINAPI ProgressiveSearch(int SizeSearch, int &NbMatchMin, int NbMatchMax, int &XRef, int &YRef, int ColorToFind/*-1 if several colors*/, int ShadeVariation, int NoSnapShot);

// Count pixels with a given color
int WINAPI ColorCount(int ColorToFind, int NoSnapShot, int ShadeVariation);

// SnapShot saving into bitmap file
bool WINAPI SaveBMP(int NoSnapShot, LPCSTR szFileName /* With no extension (xxx.bmp added)*/);
bool WINAPI SaveJPG(int NoSnapShot, LPCSTR szFileName /* With no extension*/, ULONG uQuality) ;
int WINAPI GetLastFileSuffix();

// Raw SnapShot rata retrieval
int * WINAPI GetRawData(int NoSnapShot, int &NbBytes);

// Detection of changes between two SnapShots
int WINAPI KeepChanges(int NoSnapShot, int NoSnapShot2, int ShadeVariation);  // ** Changed in version 2.0 : ShadeVariation added **
int WINAPI KeepColor(int NoSnapShot, int ColorToFind, int ShadeVariation);  
int WINAPI HasChanged(int NoSnapShot, int NoSnapShot2, int ShadeVariation);  // ** Changed in version 2.0 : ShadeVariation added **
int WINAPI LocalizeChanges(int NoSnapShot, int NoSnapShot2, int &xMin, int &yMin, int &xMax, int &yMax, int &nbFound, int ShadeVariation);  // ** Changed in version 2.0 : ShadeVariation added **

// Display of a SnapShot
bool WINAPI DrawSnapShot(int NoSnapShot);
bool WINAPI DrawSnapShotXY(int NoSnapShot, int X, int Y); // ** New in version 2.0 **

// Change of the color of a pixel (hyper-omptimized function)
bool WINAPI FFSetPixel(int x, int y, int Color, int NoSnapShot);

// SnapShot duplication
bool WINAPI DuplicateSnapShot(int Src, int Dst);

// Misc functions, new in version 2.0
int WINAPI ComputeMeanValues(int NoSnapShot, int &MeanRed, int &MeanGreen, int &MeanBlue);
int WINAPI ApplyFilterOnSnapShot(int NoSnapShot, int Red, int Green, int Blue);
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#11
Merci beaucoup, en espérant que ça fonctionne !


EDIT : Arf, j'ai que des "undefined reference to..." à chaque fonction que j'utilise :S
 

FastFrench

Membre Actif
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#12
C'est tout à fait normal vu que tu n'as probablement pas précisé au linker où trouver ces fonctions.

Cherche sur Internet comment utiliser une DLL depuis ton compilateur C++.
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#13
Faut que je compile la DLL pour obtenir un fichier a que je link via CodeBlocks, c'est ça ?
 

FastFrench

Membre Actif
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#14
"Compile" n'est pas vraiment le bon terme. Une des approches possibles, c'est de générer une bibliothèque d'importation à partir de la dll, et de linker avec cette bibliothèque.
Certains compilateurs ont des directives pour référencer directement une dll.

http://wiki.codeblocks.org/index.ph...w_can_I_use_a_DLL_without_DEF_or_LIB_files.3F

A ta place, je commencerais par essayer de linker directement avec la dll. Parfois ça peut passer. Sinon, il faut générer une bibliothèque d'import, cf le lien.
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#15
Alors, j'ai bien galéré, et j'ai trouvé ce qu'il fallait faire exactement :
- pour créer un fichier d'importation de bibliothèque, il faut un fichier def, je l'ai créé grâce à impdef.exe, j'obtiens :
Code:
LIBRARY     FASTFIND.DLL

EXPORTS
- ensuite, j'utilise dlltool.exe présent dans les commandes de MinGW, en réutilisant le fichier def, j'obtiens :
Code:
"C:\Program Files (x86)\CodeBlocks\MinGW\bin\dlltool" -d FastFind.def -l libFastFind.a
Un fichier a est généré, je le place dans le dossier lib de CodeBlocks et je le link, mais ça ne marche pas, j'ai un toujours un "undefined reference" :S
J'ai essayé avec FastFind64.dll, marche pas non plus.
J'ai essayé en générant un fichier lib plutôt qu'un fichier a (pour les deux DLL), marche pas non plus.
A la fin, j'avais 4 fichiers linkés...

Si tu pouvais me donner la solution directement FF, car là j'ai pas mal cherché, et j'en ai bien ch*é...
 

FastFrench

Membre Actif
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#16
Oui, mais ton .Def ne doit pas être vide. Il faut lister toutes les fonctions exportables (au moins celles que tu utilises). Sinon, ta librairie d'importation ne sert à rien.

Code:
LIBRARY	"FastFind"

EXPORTS
	SetDebugMode
	DebugTrace
	DebugError

	SetHWnd
	GetLastErrorMsg

	AddExcludedArea
	ResetExcludedAreas
	IsExcluded

	FFTest
	FFVersion

	SnapShot
	
	ProgressiveSearch
	GenericColorSearch
	ColorCount
	ColorPixelSearch
	
	LocalizeChanges
	HasChanged

	FFGetPixel
	
	AddColor
	RemoveColor
	ResetColors
	ColorsSearch
	ColorsPixelSearch

	SaveBMP
	SaveJPG
	GetLastFileSuffix

	KeepChanges
	KeepColor

	
	DrawSnapShot
	DrawSnapShotXY
	FFSetPixel

	DuplicateSnapShot
	GetRawData

	ApplyFilterOnSnapShot
	ComputeMeanValues
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#17
Oui, j'ai vu après que ça ne marchait pas car les DLL que j'utilisais étaient erronées, elle faisaient 1 Ko, j'avais pas fait gaffe^^'
J'ai téléchargé la version 2.0, j'ai pris ton fichier DEF que tu as fourni, j'ai généré un fichier a, je l'ai linké, mais ça ne marche pas toujours pas, j'ai toujours l'erreur : "undefined reference to 'ResetColors()@0'" :S Je ne comprends pas pourquoi ça ne marche pas !



Tant que j'y suis, quand je génère un fichier def à partir de la DLL 32bits, j'obtiens un fichier légèrement différent, j'ai des numéros associés à chaque fonction :

Code:
LIBRARY     FASTFIND.DLL

EXPORTS
    AddColor                       @1   
    AddExcludedArea                @2   
    ApplyFilterOnSnapShot          @3   
    ColorCount                     @4   
    ColorPixelSearch               @5   
    ColorsPixelSearch              @6   
    ColorsSearch                   @7   
    ComputeMeanValues              @8   
    DebugError                     @9   
    DebugTrace                     @10  
    DrawSnapShot                   @11  
    DrawSnapShotXY                 @12  
    DuplicateSnapShot              @13  
    FFGetPixel                     @14  
    FFSetPixel                     @15  
    FFTest                         @16  
    FFVersion                      @17  
    GenericColorSearch             @18  
    GetLastErrorMsg                @19  
    GetLastFileSuffix              @20  
    GetRawData                     @21  
    HasChanged                     @22  
    IsExcluded                     @23  
    KeepChanges                    @24  
    KeepColor                      @25  
    LocalizeChanges                @26  
    ProgressiveSearch              @27  
    RemoveColor                    @28  
    ResetColors                    @29  
    ResetExcludedAreas             @30  
    SaveBMP                        @31  
    SaveJPG                        @32  
    SetDebugMode                   @33  
    SetHWnd                        @34  
    SnapShot                       @35
Par contre, je ne peux pas générer de fichier def pour la DLL 64bits, j'ai une erreur de lecture : "Error read error: Error 0".
 

FastFrench

Membre Actif
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#18
En principe, le nom devrait suffire, le numéro doit correspondre à la position de la fonction dans la table des fonctions exportées de la DLL. Cependant, chaque environnement peut imposer ses spécificités sur le fichier .DEF. Celui que j'inclus est ce qu'utilise MSVC (Microsoft).

Probablement que l'outil que tu utilises pour générer la librairie d'import ne supporte pas les DLL 64 bits.

Au niveau du .h, essaie de remplacer les WINAPI par EXPIMP, que tu définiras ainsi:

Code:
#define EXPIMP __declspec(dllimport) _stdcall
Ca devrait le faire, enfin avec un peu de chance :roll:
 
Inscrit
15 Avril 2011
Messages
457
Reactions
1
#19
Code:
/*
 * Functions exported in FastFind.dll - version 2.0
 * EXPIMP is defined as follows : #define EXPIMP __declspec(dllimport) _stdcall
 * COLORREF is defined as follows : typedef DWORD COLORREF
 */

// Exclusion areas
void EXPIMP AddExcludedArea(int x1, int y1, int x2, int y2);
bool EXPIMP IsExcluded(int x, int y, HWND hWnd);
void EXPIMP ResetExcludedAreas();

// Configuration
void EXPIMP SetDebugMode(int NewMode);
void EXPIMP SetHWnd(HWND NewWindowHandle, bool bClientArea);
LPCTSTR EXPIMP GetLastErrorMsg();
LPCTSTR EXPIMP FFVersion(void);

// Basic functions
int EXPIMP GetPixel(int X, int Y, int NoSnapShot);
int EXPIMP ColorPixelSearch(int &XRef, int &YRef, int ColorToFind, int NoSnapShot);
int EXPIMP GetPixelFromScreen(int x, int y, int NoSnapShot); // Idem GetPixel, mais en coordonnées écran

// Snapshots
int EXPIMP SnapShot(int aLeft, int aTop, int aRight, int aBottom, int NoSnapShot);

// List of colors management
int EXPIMP AddColor (COLORREF NewColor);
int EXPIMP RemoveColor (COLORREF NewColor);
void EXPIMP ResetColors ();

// Search function, for multiple colors (color list should be defined first)
int EXPIMP ColorsPixelSearch(int &XRef, int &YRef, int NoSnapShot);

// ColorsSearch is close to ColorSearch, except it can look for several colors instead of only one.
int EXPIMP ColorsSearch(int SizeSearch, int &NbMatchMin, int &XRef, int &YRef, int NoSnapShot);

// Most generic search function : called in most case.
int EXPIMP GenericColorSearch(int SizeSearch, int &NbMatchMin, int &XRef, int &YRef, int ColorToFind, int ShadeVariation, int NoSnapShot);

// New vith verion 1.4 : more powerful search function : looks for 'spots' instead of pixels
int EXPIMP ProgressiveSearch(int SizeSearch, int &NbMatchMin, int NbMatchMax, int &XRef, int &YRef, int ColorToFind/*-1 if several colors*/, int ShadeVariation, int NoSnapShot);

// Count pixels with a given color
int EXPIMP ColorCount(int ColorToFind, int NoSnapShot, int ShadeVariation);

// SnapShot saving into bitmap file
bool EXPIMP SaveBMP(int NoSnapShot, LPCSTR szFileName /* With no extension (xxx.bmp added)*/);
bool EXPIMP SaveJPG(int NoSnapShot, LPCSTR szFileName /* With no extension*/, ULONG uQuality) ;
int EXPIMP GetLastFileSuffix();

// Raw SnapShot rata retrieval
int * EXPIMP GetRawData(int NoSnapShot, int &NbBytes);

// Detection of changes between two SnapShots
int EXPIMP KeepChanges(int NoSnapShot, int NoSnapShot2, int ShadeVariation);  // ** Changed in version 2.0 : ShadeVariation added **
int EXPIMP KeepColor(int NoSnapShot, int ColorToFind, int ShadeVariation);
int EXPIMP HasChanged(int NoSnapShot, int NoSnapShot2, int ShadeVariation);  // ** Changed in version 2.0 : ShadeVariation added **
int EXPIMP LocalizeChanges(int NoSnapShot, int NoSnapShot2, int &xMin, int &yMin, int &xMax, int &yMax, int &nbFound, int ShadeVariation);  // ** Changed in version 2.0 : ShadeVariation added **

// Display of a SnapShot
bool EXPIMP DrawSnapShot(int NoSnapShot);
bool EXPIMP DrawSnapShotXY(int NoSnapShot, int X, int Y); // ** New in version 2.0 **

// Change of the color of a pixel (hyper-omptimized function)
bool EXPIMP FFSetPixel(int x, int y, int Color, int NoSnapShot);

// SnapShot duplication
bool EXPIMP DuplicateSnapShot(int Src, int Dst);

// Misc functions, new in version 2.0
int EXPIMP ComputeMeanValues(int NoSnapShot, int &MeanRed, int &MeanGreen, int &MeanBlue);
int EXPIMP ApplyFilterOnSnapShot(int NoSnapShot, int Red, int Green, int Blue);
Marche pas non plus :/

Peut-être qu'il faut obligatoirement que j'utilise la DLL 64 bits ?
 

FastFrench

Membre Actif
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#20
Huhum

Le typedef dans un commentaire, il n'est pas très utile.

Il faut ajouter :
Code:
#define EXPIMP __declspec(dllimport) _stdcall
au début de ton code, mais pas en commentaire.
 
Haut Bas