La fonction la plus simple permet de trouver le pixel d'une couleur donnée - comme PixelSearch - mais au lieu de renvoyer le 1er trouvé, il retourne le plus proche d'un point donné.
Ca permet d'aller bien plus loin :
- recherche du 'spot' le plus proche (carré de NxN contenant au moins P pixels respectant les critères de couleur mentionnés)
- gère une liste contenant jusqu'à 1024 couleurs (recherche les pixels ayant l'une des couleurs dans cette liste)
- gère jusqu'à 1024 rectangles d'exclusion. On peut ainsi définir très précisément la zone de recherche que l'on veut (avec un rectangle global auquel se substituent tous les rectangles d'exclusion).
- possibilité d'avoir un 'shade variation' (même principe qu'avec PixelSearch, pris en compte sur chacune des couleurs).
- permet de travailler sur plusieurs 'SnapShots' (captures) en mémoire. Il est possible de conserver jusqu'à 1024 captures simultanément (bien entendu, chaque capture consomme de la mémoire, aussi n'utilisez que les "slots" dont vous avez besoin).
- fonctionne sur tout l'écran ou en précisant un handle de fenêtre.
- inclut également des fonctions pour identifier ce qui change entre deux SnapShots (rectangle minimum contenant tous les changements + nombre de pixels différents). Pratique pour détecter les mouvements à l'écran, les objets qui changent d'état...
- un système de traces assez sophistiqué est inclus dans cet UDF. Vous pouvez choisir le type de traces que vous voulez, avec notamment la possibilité de visualiser à l'écran les zones détectées (pratique en cours de développement) et enregistrer le détail des opérations dans un fichier de traces.
- pour encore plus de performance, vous pouvez capturer le contenu d'un écran en mémoire (SnapShot, prend environ le même temps qu'un PixelSearch ou un PixelGetColor) puis effectuer toutes les recherches que vous voulez dans cette capture (fonctions très rapides).
Sont inclus dans l'archive la dll (écrite en Visual C++ 2010), le Wrapper AutoIt, et une démonstration.
Voici le détail des fonctions exposées dans la dll :
► Afficher le texte.h
Code : Tout sélectionner
// Exclusion Area mngt
bool WINAPI IsExcluded(int x, int y, HWND hWnd);
void WINAPI ResetExcludedAreas();
// Color Mngt
int WINAPI AddColor (COLORREF NewColor);
int WINAPI RemoveColor (COLORREF NewColor);
void WINAPI ResetColors ();
// Configuration
void WINAPI SetDebugMode(int NewMode);
void WINAPI SetHWnd(HWND NewWindowHandle);
LPCTSTR WINAPI GetLastErrorMsg();
LPCTSTR WINAPI FFversion();
// Snapshots
int WINAPI SnapShot(int aLeft, int aTop, int aRight, int aBottom, int NoSnapShot);
// Fonctions de recherche
// =================
// Recherche d'un pixel unique, avec plusieurs couleurs
int WINAPI ColorsPixelSearch(int &XRef, int &YRef, int NoSnapShot);
// Recherche d'une zone de SizeSearchxSizeSearch contenant au moins NbMatchMin pixels, la plus proche possible de (XRef, YRef)
int WINAPI ColorsSearch(int SizeSearch, int &NbMatchMin, int &XRef, int &YRef, int NoSnapShot);
// Recherche du pixel le plus proche de XRef, YRef, ayant la couleur ColorToFind
int WINAPI ColorPixelSearch(int &XRef, int &YRef, int ColorToFind, int NoSnapShot);
// Fonction la plus générique pour les recherches, exposant toutes les variantes possibles
int WINAPI GenericColorSearch(int SizeSearch, int &NbMatchMin, int &XRef, int &YRef, int ColorToFind, int ShadeVariation, int NoSnapShot);
// Cette fonction compte le nombre de pixels proche de la couleur indiquée
int WINAPI ColorCount(int ColorToFind, int NoSnapShot, int ShadeVariation);
// Détection des changements
// =====================
// Indique simplement si deux Captures sont différentes (au moins un pixel différent)
int WINAPI HasChanged(int NoSnapShot, int NoSnapShot2);
// Précise quel est le rectangle minimum contenant tous les changements, ainsi que le nombre de pixels ayant changé entre les deux captures
int WINAPI LocalizeChanges(int NoSnapShot, int NoSnapShot2, int &xMin, int &yMin, int &xMax, int &yMax, int &nbFound);
► Afficher le texteFonctions Autoit définies dans cet UDF FastFind.au3
Code : Tout sélectionner
; Initialisation de l'udf. Est appelé automatiquement quand FastFind.au3 est inclus.
Func InitFFDll()
; Fermeture de l'udf, libération de la mémoire, déchargement de la dll, fermeture du fichier de trace...
Func CloseFFDll()
; Détermine le mode de debuggage.
; ---------------------------------------------------------------------
; Les 4 bits de poids faible déterminent les canaux de debuggage activés, ils ont la signification suivante :
; 0x00 = sans debug,
; 0x01 = Informations envoyées vers la console (RequireAdmin),
; 0x02 = Information debug envoyées vers un fichier (trace.txt)
; 0x04 = Affichage graphique des points / zones détectés
; 0x08 = Affichage de MessageBox (bloquant)
; A noter qu'en cas d'erreur, une MessageBox sera affichée dans la DLL si DebugMode>0
; Les 4 bits suivants permettent de filtrer selon la provenance du message de debug
; 0x0010 // Exclut les traces internes de la DLL
; 0x0020 // Exclut les traces internes détaillées de la DLL
; 0x0040 // Exclut les traces externes (celles de l'application)
; 0x0080 // Message d'erreur (prioritaire)
;
; Les erreurs (graves) sont affichées sur tous les canaux disponibles (fichier, console et MessageBos) si $DebugMode > 0
;
; Proto fonction C : void SetDebugMode(int NewMode)
Func FFSetDebugMode($DebugMode)
; La DLL expose également ses fonction de débuggage, permettant à l'application AutoIt d'en tirer parti
Func FFTrace($DebugString)
; Cette fonction permet de traiter les erreurs (le texte apparait dans le fichier de traces, la console et une MessageBox si $DebugMode>0)
Func FFTraceError($DebugString)
; Fixe la fenêtre courante à utiliser
; -----------------------------------
; Par défaut, c'est tout l'écran qui est utilisé. Il est possible de choisir une fenêtre en particulier.
; Ce choix n'a d'influence directe que sur "SnapShot". Pour les autres opérations, c'est la fenêtre
; courante au moment de la prise du SnapShot qui compte.
; Si $WindowsHandle = 0, c'est tout l'écran - GetDesktopWindow()
;
; Proto fonction C : void SetHWnd(HWND NewWindowHandle);
Func FFSetWnd($WindowHandle)
; Permet d'éviter de préciser le N° du SnapShot à chaque fois, quand on travaille toujours sur le même
Func FFSetDefaultSnapShot($NewSnapShot)
; Gestion de la liste des couleurs
; ================================
; Quand un paramètre de Couleur est proposé dane une fonction, la valeur -1 signifie que toutes les couleurs de la liste sont prise en compte
; Ajoute une ou plusieurs couleurs dans la liste gérée par FastFind
; Proto fonction C : int AddColor (COLORREF NewColor)
Func FFAddColor($NewColor)
; Retire une couleur (si elle existe) de la liste des couleurs
;
; Proto fonction C : int RemoveColor (COLORREF NewColor)
Func FFRemoveColor($OldColor)
; Vide totalement la liste des couleurs
;
; Proto fonction C : int ResetColors ()
Func FFResetColors()
; Gestion des zones d'exclusion
; ================================
; Les zones d'exclusion permettent de restreindre les recherches effectuées avec toutes les fonctions
; de recherche
; Il est possible d'avoir jusqu'à 1024 rectangles d'exclusion, permettant ainsi de retirer précisément
; n'importe quelle zone des recherches. Par exemple, avec flash, le curseur de la souris apparait dans
; la capture d'écran (contrairement aux curseurs gérés par Windows). Vous pouvez donc utiliser une
; zone d'exclusion constituée d'après la position de la souris, afin que le curseur n'influe pas sur le
; résultat des recherches.
;
; Ajoute une zone d'exclusion
;
; Proto fonction C : void WINAPI AddExcludedArea(int x1, int y1, int x2, int y2)
Func FFAddExcludedArea($x1, $y1, $x2, $y2)
; Supprime la liste de toutes les zones d'exclusion
;
; Proto fonction C : void WINAPI ResetExcludedAreas()
Func FFResetExcludedAreas()
; Parcourt la liste des zones d'exclusion pour déterminer si le point passé en paramètre pour la fenêtre indiquée
; est exclu des recherches ou pas.
;
; Proto fonction C : bool WINAPI IsExcluded(int x, int y, HWND hWnd)
Func FFIsExcluded($x, $y, $hWnd)
; Fonction FFSnapShot - Cette fonction permet de faire une copie de l'écran, d'une fenêtre ou seulement d'une partie en mémoire
; - Toutes les autres fonctions de FF fonctionnant à partir de la mémoire, il faut commencer par utiliser FFSnapShot
; Il est possible d'effectuer plusieurs captures différentes, et de travailler sur n'importe laquelle par la suite.
; Certaines fonctions permettent même de comparer les captures entre elles
; En entrée :
; la zone à capturer (en coordonnées relatives aux limites de la fenêtre, si un handle de fenêtre non nul est indiqué) [optionnel, l'écran entier par défaut]
; Si la zone indiquée est 0,0,0,0 alors c'est la totalité de la fenêtre qui sera capturée
; le N° de SnapShot à utiliser (optionnel, le dernier utilisé par défaut, 0 initialement)
; un handle de fenêtre [optionnel, le même écran que la fois précédente par défaut. Initialement, tout l'écran.]
;
; Attention : les données graphiques étant conservées en mémoire, l'utilisation de cette fonction consomme de la mémoire. Il faut compter environ 1,8 Mo de RAM pour une capture 800x600.
; c'est pourquoi il faut de préférence réutiliser toujours les mêmes N° de SnapShot. Néanmoins, il est possible de mémoriser jusqu'à 1024 écrans différents.
; Valeurs de retour : En cas d'échec, renvoie 0 et positionne @Error.
; En cas de succès, renvoie 1
; Proto fonction C : int WINAPI SnapShot(int aLeft, int aTop, int aRight, int aBottom, int NoSnapShot)
Func FFSnapShot($Left=0, $Top=0, $Right=0, $Bottom=0, $NoSnapShot=$FFDefaultSnapShot, $WindowHandle=-1)
; Fonction FFNearestPixel - Cette fonction fonctionne un peu comme PixelSearch,
; sauf qu'elle renvoie non pas le premier pixel trouvé,
; mais le plus proche de PoxX/PoxY
; Valeurs de retour : En cas d'échec, renvoie 0 et positionne @Error.
; En cas de succès, un tableau de 2 éléments : 1/ coordonnée X du pixel trouvé le plus proche, 2/ coordonnée Y du pixel trouvé le plus proche
; Exemple : pour trouver le pixel de couleur 0x00AB0C45 le plus proche possible du joueur situé en 500, 500
; $Res = FFNearestPixel( 0, 0, 1023, 767, 1, 500, 500, 0x00AB0C45)
; If not @Error Then MsgBox(0, "Ressource", "Trouvée en "&$PosX&","&$PosY)
;
; Proto fonction C : int WINAPI ColorPixelSearch(int &XRef, int &YRef, int ColorToFind, int NoSnapShot)
Func FFNearestPixel($Left, $Top, $Right, $Bottom, $PosX, $PosY, $Color, $ForceNewSnap=true, $NoSnapShot=$FFLastSnap, $WindowHandle=-1)
; Fonction FFNearestSpot - Cette fonction permet de trouver, parmi toutes les zone (ou "Spots") contenant
; un nombre minimum de pixels d'une certaines couleur, celle qui est la plus proche d'un point (position du joueur par exemple).
; Valeurs de retour : En cas d'échec, renvoie 0 et positionne @Error.
; En cas de succès, un tableau de 3 éléments : 1/ coordonnée X du spot le plus proche, 2/ coordonnée Y du spot le plus proche, 3/ Nombre de pixels trouvés dans le spot le plus proche
; Par exemple, supposons que vous voulez détecter un cercle bleu (Color = 0x000000FF) partiellement occulté, de diamètre 32 pixels (disons avec au moins 45 pixels de la bonne couleur),
; le plus proche possible de la position x=198 et y=543, dans un écran complet en résolution 1024x768; alors la fonction est appelée ainsi :
; $Res = FFNearestSpot(0, 0, 1023, 767, 45, 198, 543, 0x000000FF)
; If not @Error Then MsgBox(0, "Blue Circle", "Le cercle bleu le plus proche de la position 198, 543 se trouve en "&$PosX&","&$PosY&@LF&" et contient "&$NbPixel&" pixels bleus")
;
; Proto fonction C : int WINAPI GenericColorSearch(int SizeSearch, int &NbMatchMin, int &XRef, int &YRef, int ColorToFind, int ShadeVariation, int NoSnapShot)
Func FFNearestSpot($Left, $Top, $Right, $Bottom, $SizeSearch, $NbPixel, $PosX, $PosY, $Color, $ShadeVariation=0, $ForceNewSnap=true, $NoSnapShot=$FFLastSnap, $WindowHandle=-1)
; Fonction FFColorCount - Cette fonction compte le nombre de pixels ayant la couleur indiquée, exactes ou approchées (ShadeVariation).
;
; Proto C : int WINAPI ColorCount(int ColorToFind, int NoSnapShot, int ShadeVariation)
Func FFColorCount($Left, $Top, $Right, $Bottom, $ColorToCount, $ShadeVariation=0, $ForceNewSnap=true, $NoSnapShot=$FFLastSnap, $WindowHandle=-1)
; Fonction FFIsDifferent - Cette fonction compare deux SnapShots et indique si ils ont changé.
;
; Proto C : int WINAPI HasChanged(int NoSnapShot, int NoSnapShot2)
Func FFIsDifferent($NoSnapShot1, $NoSnapShot2)
; Fonction FFLocalizeChanges - Cette fonction compare deux SnapShots et précise le nombre de pixels différent ainsi que le plus petit rectangle contenant tous les changements.
; En cas d'échec, @Error = 1 et retourne 0
; En cas de différences constatées, renvoie un tableau de 5 éléments ainsi formé :
; [0] : limite gauche du rectangle
; [1] : limite haute du rectangle
; [2] : limite droite du rectangle
; [3] : limite basse du rectangle
; [4] : Nombre de pixels ayant changé
; Proto C : int WINAPI LocalizeChanges(int NoSnapShot, int NoSnapShot2, int &xMin, int &yMin, int &xMax, int &yMax, int &nbFound)
Func FFLocalizeChanges($NoSnapShot1, $NoSnapShot2)
► Afficher le texteDémonstration AutoIt
Code : Tout sélectionner
; Demo FastFind (officielle)
#include "FastFind.au3"
#Include <WinAPI.au3>
#RequireAdmin
global const $DEBUG_DEFAULT = 3
global const $DEBUG_GRAPHIC = $DEBUG_DEFAULT + 4
global const $WINDOW_CLASS = "Notepad" ; CLASS de la fenêtre à détecter
global const $WINDOW_TITLE = "" ; TITRE de la fenêtre à détecter
FFSetDebugMode($DEBUG_GRAPHIC) ; Active le mode débug avancé, pour avoir des traces + visualisation graphique
FFSetDefaultSnapShot(0)
;MsgBox(0,"Démo FF", "Mettez une fenêtre avec des cercles bleus et rouges, puis cliquez sur un point"&@LF&"Pour lancer la recherche du cercle de chaque couleur le plus proche du point désigné par la souris")
TrayTip("Démo FastFind", "F1 pour détecter une zone bleue et F2 pour rouge, "&@LF&"F3 pour capturer la fenêtre Notepad, "&@LF&"F4 pour capturer l'écran complet, "&@LF&"F5 pour détecter les changements depuis la dernière capture, "&@LF&"F6 pour partir dans une boucle de détection périodique des changements, "&@LF&"ESC pour terminer",50000)
HotKeySet("{F1}", "DetectBleu")
HotKeySet("{F2}", "DetectBlancNoir")
HotKeySet("{F3}", "SelectWindow")
HotKeySet("{F4}", "SelectScreen")
HotKeySet("{F5}", "ShowChanges")
HotKeySet("{F6}", "PeriodicChanges")
HotKeySet("{ESC}", "TheEnd")
While (1)
Sleep(10) ; On attend, jusqu'à appui sur "ESC" pour quitter
Wend
; On cherche la zone de 43x43 la plus proche du coin sup. gauche (0,0) contenant au moins 100 pixels approchant du bleu.
; Dans un premier passage, on cherche un bleu pur (0x0000FF), et à chaque itération on augmente la tolérance sur la couleur de 5.
; On doit forcément trouver une réponse, au pire avec ShadeVariation = 255 (tous les pixels de l'écran remplissent alors la condition)
;
; Si FFSetDebugMode vaut 7 (le bit 4 est donc à un), la zone détectée est entourée l'un rectangle rouge
Func DetectBleu()
FFSetDebugMode($DEBUG_GRAPHIC)
FFTrace(@lf&" ** Detection zone proche du bleu"&@lf&"")
local $ShadeVariation=0
local $ResBleu
do
$ResBleu = FFNearestSpot(0, 0, 0, 0, 43, 100, 100, 100, 0x000000FF, $ShadeVariation, true) ; Force un nouveau snapShot à chaque passage (cf DetectBlancNoir pour optimisation simple possible)
if (Not IsArray($ResBleu)) Then $ShadeVariation += 5
until (IsArray($ResBleu) OR $ShadeVariation >250)
if (IsArray($ResBleu)) Then
local $sMsg = "Zone 43x43 contenant 100 pixels Bleus trouvée (avec ShadeVariation de "&$ShadeVariation&"): la zone la plus proche de (100,100) est en "&$ResBleu[0]&","&$ResBleu[1];
FFTrace(" ** "&$sMsg&""&@lf&"")
TrayTip("Zone trouvée", $sMsg, 2000)
Else
local $sMsg = "Aucune zone contenant du bleu trouvée"
FFTrace(" ** "&$sMsg&@lf&"")
TrayTip("Pas trouvé", $sMsg, 2000)
EndIf
EndFunc
; On cherche la zone de 10x10 la plus proche du coin sup. gauche (0,0) qui soit totalement soit blanc soit noir.
;
; Si FFSetDebugMode vaut 7 (le bit 4 est donc à un), la zone détectée est entourée l'un rectangle rouge
Func DetectBlancNoir()
FFSetDebugMode($DEBUG_GRAPHIC)
FFTrace(@lf&" ** FFNearestSpot(0, 0, 0, 0, 43, 100, 0, 0, 0x00FF0000, 0+, true)"&@lf&"")
local $ShadeVariation=0
local $ResBlancNoir
FFResetColors() ; On remet la liste des couleurs à 0
FFAddColor(0x00FFFFFF) ; On ajoute le blanc dans la liste
FFAddColor(0x00000000) ; On ajoute le noir dans la liste
local $FirstLoop = true ; Cette variable permet d'optimiser le traitement, en ne faisant une capture en mémoire de l'écran qu'au premier passage. Ainsi les recherches suivantes sont bien plus rapides.
do
; [0, 0, 0, 0] => FullScreen, 10 => Taille de la zone à trouver, 100 => Nombre de pixels dans la zone, [0, 0] Coordonnées du point de référence, -1 => Utiliser la liste de couleurs, $ShadeVariation => Tolérance sur les couleurs, true => Force un nouveau SnapShot uniquement la première fois
$ResBlancNoir = FFNearestSpot(0, 0, 0, 0, 10, 100, 0, 0, -1, $ShadeVariation, $FirstLoop) ; Ne force pas un nouveau snapShot si il y en a déjà un
$FirstLoop = false
if (Not IsArray($ResBlancNoir)) Then $ShadeVariation += 2
until (IsArray($ResBlancNoir) OR $ShadeVariation >20)
if (IsArray($ResBlancNoir)) Then
local $sMsg = "Zone 10x10 entièrement noire et blanche (donc contenant 100 pixels dans ces deux couleurs) trouvée (avec ShadeVariation de "&$ShadeVariation&"): la zone la plus proche de (0,0) est en "&$ResBlancNoir[0]&","&$ResBlancNoir[1];
FFTrace(" ** "&$sMsg&""&@lf&"")
TrayTip("Zone trouvée", $sMsg, 2000)
Else
local $sMsg = "Aucun carré de 10x10 ne contenant que du noir et du blanc n'a été trouvée"
FFTrace(" ** "&$sMsg&@lf)
TrayTip("Pas trouvé", $sMsg, 2000)
EndIf
EndFunc
Func SelectWindow()
FFTrace(@lf&" ** SelectWindow"&@lf&"")
local $hWnd = WinActivate("[CLASS:"&$WINDOW_CLASS&"; TITLE:"&$WINDOW_TITLE&"]", "") ; On tente de capturer une fenêtre
if $hWnd="" Then
$hWnd = WinGetHandle("[ACTIVE]", "") ; à défaut, on prend la fenêtre courante
EndIf
WinSetOnTop ( $hWnd, "", 1)
FFSetDebugMode($DEBUG_DEFAULT)
FFSetWnd($hWnd)
FFSnapShot()
TrayTip("Select Window","Title of the Window: "&WinGetTitle($hWnd)&" Class:"&_WinAPI_GetClassName($hWnd), 2000)
FFTrace(" ** SelectWindow => Title of the Window: "&WinGetTitle($hWnd)&" Class:"&_WinAPI_GetClassName($hWnd)&@lf)
EndFunc
; Sélectionne un écran
Func SelectScreen()
FFTrace(@lf&" ** SelectScreen"&@lf&"")
FFSetWnd(0)
FFSnapShot()
TrayTip("Select Screen","Select FullScreen", 2000)
EndFunc
Func ShowChanges()
FFTrace(@lf&" ** ShowChanges"&@lf)
FFSetDebugMode($DEBUG_DEFAULT) ; On conserve les traces, mais pas le débuggage graphique, pour ne pas créer artificiellement des changements qui seraient détectés
FFSetDefaultSnapShot(1) ; Fait un SnapShot discret sur le Slot N°1
FFSnapShot()
FFSetDebugMode($DEBUG_GRAPHIC) ; Active le mode débug avancé, pour avoir une messagebox donnant la réponse + infos graphiques
$Res = FFLocalizeChanges(0, 1) ; Cherche les différences entre les SnapShots 0 et 1
FFSetDefaultSnapShot(0) ; Revient sur le slot N°0 pour les prochains SnapShots
if @Error Then
TrayTip("ShowChanges","No change detected",2000)
FFTrace(" ** ShowChanges => No change detected !"&@lf)
Else
TrayTip("ShowChanges","Change detected : ("&$Res[0]&","&$Res[1]&","&$Res[2]&","&$Res[3]&"), "&$Res[4]&" pixels are different",2000)
FFTrace(" ** ShowChanges => Change detected : ("&$Res[0]&","&$Res[1]&","&$Res[2]&","&$Res[3]&"), "&$Res[4]&" pixels are different"&@lf)
EndIf
EndFunc
; Surveille les changements à l'écran et les affiche (trace graphique (FFSetDebugMode(4)) + TrayTip)
Func PeriodicChanges()
while 1
FFSetDebugMode($DEBUG_DEFAULT) ; désactivation du debuggage (perfs)
FFSetDefaultSnapShot(0) ; Fait un SnapShot sur le Slot N°0
FFSnapShot()
Sleep(100)
FFSetDefaultSnapShot(1) ; Fait un SnapShot sur le Slot N°1
FFSnapShot()
FFSetDebugMode($DEBUG_GRAPHIC) ; Affichage graphique de la détection
$Res = FFLocalizeChanges(0, 1) ; Cherche les différences entre les SnapShots 0 et 1
if @Error Then
FFTrace(" ** ShowChanges => No change detected !"&@lf)
Else
TrayTip("ShowChanges","Change detected : ("&$Res[0]&","&$Res[1]&","&$Res[2]&","&$Res[3]&"), "&$Res[4]&" pixels are different",2000)
FFTrace(" ** ShowChanges => Change detected : ("&$Res[0]&","&$Res[1]&","&$Res[2]&","&$Res[3]&"), "&$Res[4]&" pixels are different"&@lf)
EndIf
Wend
EndFunc
Func TheEnd()
FFTrace(" ** Bybye"&@lf&@lf)
CloseFFDll() ; Permet de tout fermer proprement, et libérer la mémoire
Exit
Endfunc
J'espère que ces fonctions vous seront utiles.
FF
[update] il y a maintenant les version 32 et 64 bits de la dll
Edit (Tlem) : Pour les nouvelles versions merci de suivre ce lien vers le site US : https://www.autoitscript.com/forum/topi ... h-library/
Vous y trouverez des exemples, commentaires et sondages concernant cet UDF.
.