Salut !
J'ai fais une petite dll pour la recherche de pixel, alors je la partage ici.
Pourquoi ?
Tout simplement parce que la fonction GetPixel est la plus utilisée des méthodes et elle est affreusement lente.
La dll est écrite en c++, donc utilisable dans (presque) tous les languages, j'ai fais un wrapper en C# pour le .net et si ça intéresse du monde, je peux aussi en faire un en AutoIt.
Les fonction :
(L'algo pour parcourir le bmp en spirale je l'ai pompé ici : Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!)
Le wrapper en C# :
(le code est aussi dans le .rar)
Pour l'utiliser, faut soit l'ajouter à son projet et changer le namespace, soit le compiler en dll et inclure la dll.
Comparatif des différentes méthodes
En gros ça teste tous les pixel de la fenêtre (taille ~ 350x350) pour voir s'ils correspondent à une couleur prédéfinie.
(J'ai pas eu le courage de laisser tourner plus longtemps avec le GetPixel, c'est teeeeellement leeent)
La méthode cool (Dedieu l'inspiration !!!) en C# est plus rapide, surement car ça ne passe pas par une dll et y'a pas tout le bordel de marshalling.
Pour me consoler je me dis que c'est moins portable que du c++ :snif1:
Download !!!
c'est en bas du post que ça s'passe ça.
Dans le .rar y'a la source de la dll + la dll compilée + un prog de test en C# & le wrapper
Et pour finir
J'suis pas bon en c++, donc si vous avez des conseils (surtout pour l'export des fonctions, j'suis une bouse) je suis preneur !
À vous de vous amuser avec la dll maintenant :)
J'ai fais une petite dll pour la recherche de pixel, alors je la partage ici.
Pourquoi ?
Tout simplement parce que la fonction GetPixel est la plus utilisée des méthodes et elle est affreusement lente.
La dll est écrite en c++, donc utilisable dans (presque) tous les languages, j'ai fais un wrapper en C# pour le .net et si ça intéresse du monde, je peux aussi en faire un en AutoIt.
Les fonction :
Code:
HBITMAP Screenshot(HWND hWnd, bool entireWindow);
[I]Bah... ça prend un screenshot. le entireWindow définit si c'est la fenêtre entière qui est capturée, ou seulement la zone client[/I]
COLORREF PixelGet(HWND hWnd, int x, int y, bool entireWindow);
[I]C'est comme le GetPixel, sauf en plus rapide et avec un autre nom (impossible de l'exporter si je laisse le même nom...)[/I]
BOOL PixelSearch(HWND hWnd, unsigned int color, int variation, LPPOINT lpPoint, bool entireWindow);
[I]Ça ça retourne la pos' du premier pixel trouvé qui correspond à la couleur[/I]
BOOL PixelSearchAll(HWND hWnd, unsigned int color, int variation, PointFoundCallback callback, bool entireWindow);
[I]Pareil, sauf que ça retourne tous les pixel[/I]
BOOL PixelSearchCenter(HWND hWnd, unsigned int color, int variation, LPPOINT lpPoint, bool entireWindow);
[I]Comme dessus, sauf que pour chercher ça part du centre de la fenêtre tourne en spirale pour chercher les pixels[/I]
BOOL PixelSearchAllCenter(HWND hWnd, unsigned int color, int variation, PointFoundCallback callback, bool entireWindow);
[I]Comme dessus.[/I]
Le wrapper en C# :
Code:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
namespace TestPixelLib
{
internal static class PixelLibWrapper
{
private const string DllName = "PixelLib.dll";
private static PointFoundCallback PixelSearchAllCallback, PixelSearchAllCenterCallback;
#region Dll imports
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void PointFoundCallback(Point value);
[DllImport(DllName, SetLastError = true, EntryPoint = "Screenshot", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr _Screenshot(IntPtr hWnd, bool entireWindow);
[DllImport(DllName, SetLastError = true, EntryPoint = "PixelGet", CallingConvention = CallingConvention.Cdecl)]
private static extern uint _GetPixel(IntPtr hWnd, int x, int y, bool entireWindow);
[DllImport(DllName, SetLastError = true, EntryPoint = "PixelSearch", CallingConvention = CallingConvention.Cdecl)]
private static extern bool _PixelSearch(IntPtr hWnd, uint color, int variation, out Point lpPoint, bool entireWindow);
[DllImport(DllName, SetLastError = true, EntryPoint = "PixelSearchAll", CallingConvention = CallingConvention.Cdecl)]
private static extern bool _PixelSearchAll(IntPtr hWnd, uint color, int variation, PointFoundCallback callback, bool entireWindow);
[DllImport(DllName, SetLastError = true, EntryPoint = "PixelSearchCenter", CallingConvention = CallingConvention.Cdecl)]
private static extern bool _PixelSearchCenter(IntPtr hWnd, uint color, int variation, out Point lpPoint, bool entireWindow);
[DllImport(DllName, SetLastError = true, EntryPoint = "PixelSearchAllCenter", CallingConvention = CallingConvention.Cdecl)]
private static extern bool _PixelSearchAllCenter(IntPtr hWnd, uint color, int variation, PointFoundCallback callback, bool entireWindow);
[DllImport("gdi32.dll", SetLastError = true)]
private static extern bool DeleteObject(IntPtr hObject);
#endregion
static PixelLibWrapper()
{
if (!File.Exists(DllName))
throw new FileNotFoundException("Cannot find a required dll", DllName);
}
/// <summary>
/// Takes a screenshot of the desired window.
/// </summary>
/// <param name="hWnd">Handle to the window, Intptr.Zero for desktop window.</param>
/// <param name="entireWindow">True for entire window, false for client area.</param>
internal static Bitmap Screenshot(IntPtr hWnd, bool entireWindow = false)
{
var hBmp = _Screenshot(hWnd, entireWindow);
var bmp = Image.FromHbitmap(hBmp);
DeleteObject(hBmp);
return bmp;
}
/// <summary>
/// Returns an 0xAARRGGBB uint (alpha is always 00 (disabled)).
/// </summary>
/// <param name="hWnd">Handle to the window, Intptr.Zero for desktop window.</param>
/// <param name="x">X coord</param>
/// <param name="y">Y coord</param>
/// <param name="entireWindow">True for entire window, false for client area.</param>
internal static uint GetPixel(IntPtr hWnd, int x, int y, bool entireWindow = false)
{
return _GetPixel(hWnd, x, y, entireWindow);
}
/// <summary>
/// Returns the first point with the desired color or a (-1;-1) point in case of failure.
/// </summary>
/// <param name="hWnd">Handle to the window, Intptr.Zero for desktop window.</param>
/// <param name="color">Wanted color, format 0x00RRGGBB.</param>
/// <param name="variation">The margin of error for color match, default is 0</param>
/// <param name="entireWindow">True for entire window, false for client area.</param>
internal static Point PixelSearch(IntPtr hWnd, uint color, int variation = 0, bool entireWindow = false)
{
Point pt;
return _PixelSearch(hWnd, color, variation, out pt, entireWindow) ? pt : new Point(-1, -1);
}
/// <summary>
/// Returns a list of point with the desired color.
/// </summary>
/// <param name="hWnd">Handle to the window, Intptr.Zero for desktop window.</param>
/// <param name="color">Wanted color, format 0x00RRGGBB.</param>
/// <param name="variation">The margin of error for color match, default is 0</param>
/// <param name="entireWindow">True for entire window, false for client area.</param>
internal static List<Point> PixelSearchAll(IntPtr hWnd, uint color, int variation = 0, bool entireWindow = false)
{
var res = new List<Point>();
PixelSearchAllCallback = res.Add;
_PixelSearchAll(hWnd, color, variation, PixelSearchAllCallback, entireWindow);
return res;
}
/// <summary>
/// Returns the first centered point with the desired color or a (-1;-1) point in case of failure.
/// </summary>
/// <param name="hWnd">Handle to the window, Intptr.Zero for desktop window.</param>
/// <param name="color">Wanted color, format 0x00RRGGBB.</param>
/// <param name="variation">The margin of error for color match, default is 0</param>
/// <param name="entireWindow">True for entire window, false for client area.</param>
internal static Point PixelSearchCenter(IntPtr hWnd, uint color, int variation = 0, bool entireWindow = false)
{
Point pt;
return _PixelSearchCenter(hWnd, color, variation, out pt, entireWindow) ? pt : new Point(-1, -1);
}
/// <summary>
/// Returns a list of point with the desired color, starts at the center.
/// </summary>
/// <param name="hWnd">Handle to the window, Intptr.Zero for desktop window.</param>
/// <param name="color">Wanted color, format 0x00RRGGBB.</param>
/// <param name="variation">The margin of error for color match, default is 0</param>
/// <param name="entireWindow">True for entire window, false for client area.</param>
internal static List<Point> PixelSearchAllCenter(IntPtr hWnd, uint color, int variation = 0, bool entireWindow = false)
{
var res = new List<Point>();
PixelSearchAllCenterCallback = res.Add;
_PixelSearchAllCenter(hWnd, color, variation, PixelSearchAllCenterCallback, entireWindow);
return res;
}
}
}
Pour l'utiliser, faut soit l'ajouter à son projet et changer le namespace, soit le compiler en dll et inclure la dll.
Comparatif des différentes méthodes
En gros ça teste tous les pixel de la fenêtre (taille ~ 350x350) pour voir s'ils correspondent à une couleur prédéfinie.
(J'ai pas eu le courage de laisser tourner plus longtemps avec le GetPixel, c'est teeeeellement leeent)
La méthode cool (Dedieu l'inspiration !!!) en C# est plus rapide, surement car ça ne passe pas par une dll et y'a pas tout le bordel de marshalling.
Pour me consoler je me dis que c'est moins portable que du c++ :snif1:
Download !!!
c'est en bas du post que ça s'passe ça.
Dans le .rar y'a la source de la dll + la dll compilée + un prog de test en C# & le wrapper
Et pour finir
J'suis pas bon en c++, donc si vous avez des conseils (surtout pour l'export des fonctions, j'suis une bouse) je suis preneur !
À vous de vous amuser avec la dll maintenant :)
À venir (un jour peut-être..)
- Le wrapper AutoIt
- Choix de la partie de la fenêtre dans laquelle on veut chercher les pixels
- Bah.. j'ai pas trop d'idées en fait