daiBot
This small DLL* allows you to easily create a pixel-based bot in C# / C++ and AutoIt that runs really fast** in background-mode.
The bot uses PostMessage.
Pixel detection also works in background.
It's getting the DeviceContext and creates a DIBSection
Current main featues: getPixel, click, drag, pDrag
Going to add more features soon!
press thanks if you like my work.
This small DLL* allows you to easily create a pixel-based bot in C# / C++ and AutoIt that runs really fast** in background-mode.
The bot uses PostMessage.
Pixel detection also works in background.
It's getting the DeviceContext and creates a DIBSection
Current main featues: getPixel, click, drag, pDrag
Going to add more features soon!
press thanks if you like my work.
*Compiled with VS2015 Community x86
**Gets 26000 frames per second on my PC.. that should be fast enough
AutoIt Wrapper**Gets 26000 frames per second on my PC.. that should be fast enough
PHP Code:
;========================================================;
; daiBot wrapper for AutoIt
; Requires daiBot.dll
;
; @author Daifoku
;
; Terms of use: DO NOT remove the credits in my files.
; NO Commercial use.
; Danke.
;=========================================================;
#include <Array.au3>
Const $DEBUG = True
Global Const $tagBITMAPINFOHEADER = "struct; " & _
"dword biSize;" & _ ;The number of bytes required by the structure, minus the size of the RGBQuad data
"long biWidth;" & _ ;Specifies the width of the bitmap, in pixels
"long biHeight;" & _ ;Specifies the height of the bitmap, in pixels
"word biPlanes;" & _ ;Specifies the number of planes for the target device. This must be set to 1 ;
"word biBitCount;" & _ ;Specifies the number of bits-per-pixel
"dword biCompression;" & _ ;Specifies the type of compression for a compressed bottom-up bitmap
"dword biSizeImage;" & _ ;Specifies the size, in bytes, of the image
"long biXPelsPerMeter;" & _ ;Specifies the horizontal resolution, in pixels-per-meter, of the target device for the bitmap
"long biYPelsPerMeter;" & _ ;Specifies the vertical resolution, in pixels-per-meter, of the target device for the bitmap ;
"dword biClrUsed;" & _ ;Specifies the number of color indexes in the color table that are actually used by the bitmap
"dword biClrImportant; " & _;Specifies the number of color indexes that are required for displaying the bitmap
"endstruct"
Global $hDLL
Global $hBot
;========================================================;
; @brief
; Receives the HWND of @lpWindowName
;
; @author Daifoku
; @param windowname The window name (the windows title). If this parameter is NULL, getHandle returns the desktop handle.
; @return If the function succeeds, the return value is a handle to the window that has the specified window name.
; If the function fails, the return value is NULL
;=========================================================;
Func getHandle($windowname)
$ret = DllCall($hDLL, 'HWND:cdecl', 'getHandle', "ptr", $hBot, "wstr", $windowname)
if(@error) Then
ConsoleWrite("Error Code " & @error & " in getHandle()" & @CRLF)
Exit(-1);
EndIf
if($DEBUG) Then ConsoleWrite("getHandle returned " & $ret[0] & @CRLF)
return $ret[0]
EndFunc
;========================================================;
; Creates the Bitmap structure
; cDC, hDC, BITMAPINFO
; uses CreateDIBSection
;
; @author Daifoku;
; @param handle Handle to a window
; @return Returns a pointer to all pixels
;========================================================;
Func init($handle)
$ret = DllCall($hDLL, 'PTR:cdecl', 'init', "ptr", $hBot, "HWND", $handle)
if(@error) Then
ConsoleWrite("Error Code " & @error & " in init()" & @CRLF)
Exit(-1);
EndIf
if($DEBUG) Then ConsoleWrite("init returned " & $ret[0] & @CRLF)
return $ret[0];
EndFunc
;========================================================;
; Load all pixels into the hDC
; uses BitBlt to SRCCOPY all bits
;
; @author Daifoku
;========================================================;
Func loadBitmap()
$ret = DllCall($hDLL, 'NONE:cdecl', 'loadBitmap', "ptr", $hBot)
if(@error) Then
ConsoleWrite("Error Code " & @error & " in loadBitmap()" & @CRLF)
Exit(-1);
EndIf
EndFunc
;========================================================;
; Saves all $pixels into a bitmap
;
; @author Daifoku
; @time 2.3ms
; @param filePath relative or absolute path, e.g. "image.bmp"
;========================================================;
Func saveBitmap($file)
$ret = DllCall($hDLL, 'NONE:cdecl', 'saveBitmap', "ptr", $hBot, "str", $file)
if(@error) Then
ConsoleWrite("Error Code " & @error & " in saveBitmap()" & @CRLF)
Exit(-1);
EndIf
EndFunc
;========================================================;
; Gets the color of the pixel @x,@y
;
; @author Daifoku
; @time 0ms
; @param x x-position of the pixel
; @param y y-position of the pixel
; @return color in format RGB
;========================================================;
Func getPixel($x,$y)
$ret = DllCall($hDLL, 'int:cdecl', 'getPixel', "ptr", $hBot, "int", $x, "int" , $y)
if(@error) Then
ConsoleWrite("Error Code " & @error & " in getPixel()" & @CRLF)
Exit(-1);
EndIf
if($DEBUG) Then ConsoleWrite("getPixel returned " & Hex($ret[0],6) & @CRLF)
return $ret[0];
EndFunc
;========================================================;
; Drags the mouse from one position to another
; Simulates mouse movements (!) - no instant move
;
; @param xFrom x-pos from
; @param yFrom y-pos from
; @param xTo x-pos to
; @param yTo y-pos to
; @param speed You can adjust the movement speed. Setting a higher value increases the speed. Speed has to be greater than 0.
;========================================================;
Func click($x,$y)
$ret = DllCall($hDLL, 'NONE:cdecl', 'click', "ptr", $hBot, "int", $x, "int" , $y)
if(@error) Then
ConsoleWrite("Error Code " & @error & " in click()" & @CRLF)
Exit(-1);
EndIf
EndFunc
;========================================================;
; Drags the mouse from one position to another
; Simulates mouse movements (!) - no instant move
;
; @author Daifoku
; @param xFrom x-pos from
; @param yFrom y-pos from
; @param xTo x-pos to
; @param yTo y-pos to
; @param speed (float) You can adjust the movement speed. Setting a higher value increases the speed. Speed has to be greater than 0.
;========================================================;
Func drag($xFrom,$yFrom,$xTo,$yTo, $speed = 10)
$ret = DllCall($hDLL, 'NONE:cdecl', 'drag', "ptr", $hBot, "int", $xFrom, "int" , $yFrom, "int", $xTo, "int" , $yTo, "float" , $speed)
if(@error) Then
ConsoleWrite("Error Code " & @error & " in drag()" & @CRLF)
Exit(-1);
EndIf
EndFunc
;========================================================;
; Drags the mouse along the polygon
; Posts a MouseDown message to the specified window at position x[0],y[0]
; Moves the mouse from one coordinate to another x[i],y[i] to x[i+1],y[i+1]
; Posts a MouseUp message at position x[num-1],y[num-1]
;
; @author Daifoku
; @param x x koordinates.
; @param y y koordinates
; @param num Number of koordinates in x[],y[]
; @param speed (float) You can adjust the movement speed. Setting a higher value increases the speed.
;========================================================;
Func pDrag($xArr, $yArr, $speed = 10)
;Creating a Struture that holds our x and y values
;Why? Because we can not pass an array to DLLCall. We need to pass a pointer to the elements.
$xStruct = DllStructCreate('int[' & UBound($xArr) & ']')
$yStruct = DllStructCreate('int[' & UBound($xArr) & ']')
For $index = 1 To UBound($xArr)
DllStructSetData($xStruct,1,$xArr[$index-1],$index)
DllStructSetData($yStruct,1,$yArr[$index-1],$index)
Next
$ret = DllCall($hDLL, 'NONE:cdecl', 'pDrag', "ptr", $hBot, "ptr", DllStructGetPtr($xStruct), "ptr" , DllStructGetPtr($yStruct), "int" , UBound($xArr), "float" , $speed)
if(@error) Then
ConsoleWrite("Error Code " & @error & " in pDrag()" & @CRLF)
Exit(-1);
EndIf
EndFunc
;========================================================;
; Moves the mouse
; Does not click (Use function @drag to include MouseDown/MouseUp messages)
;
; @author Daifoku
; @param xFrom x-pos from
; @param yFrom y-pos from
; @param xTo x-pos to
; @param yTo y-pos to
; @param speed You can adjust the movement speed. Setting a higher value increases the speed. Speed has to be greater than 0.
;========================================================;
Func move($xFrom, $yFrom, $xTo, $yTo, $speed = 10)
$ret = DllCall($hDLL, 'NONE:cdecl', 'move', "ptr", $hBot, "int", $xFrom, "int" , $yFrom, "int", $xTo, "int" , $yTo, "float" , $speed)
if(@error) Then
ConsoleWrite("Error Code " & @error & " in move()" & @CRLF)
Exit(-1);
EndIf
EndFunc
;========================================================;
; Converts RGB value to Lab and calculates the euclidian distance
;
; @author Daifoku
; @brief You can use triplets or RGB as int. The following calls are equal.
; colorDistance2(0x00, 0xEE, 0xFF, 0x01, 0xCC, 0xCC)
; colorDistance(0x00EEFF, 0x01CCCC)
;========================================================;
Func colorDistance2($R1,$G1,$B1,$R2,$G2,$B2)
$ret = DllCall($hDLL, 'int:cdecl', 'colorDistance2', "ptr", $hBot, "int", $R1, "int" , $G1, "int" , $B1, "int", $R2, "int" , $G2, "int" , $B2)
if(@error) Then
ConsoleWrite("Error Code " & @error & " in colorDistance2()" & @CRLF)
Exit(-1);
EndIf
if($DEBUG) Then ConsoleWrite("colorDistance2 returned " & $ret[0] & @CRLF)
return $ret[0];
EndFunc
Func colorDistance($RGB1,$RGB2)
$ret = DllCall($hDLL, 'int:cdecl', 'colorDistance', "ptr", $hBot, "int", $RGB1, "int" , $RGB2)
if(@error) Then
ConsoleWrite("Error Code " & @error & " in colorDistance()" & @CRLF)
Exit(-1);
EndIf
if($DEBUG) Then ConsoleWrite("colorDistance returned " & $ret[0] & @CRLF)
return $ret[0];
EndFunc
;========================================================;
; Returns the BITMAPINFOHEADER struct
;
; @brief Important parameter :
; getBitmapInfo()->biWidth
; getBitmapInfo()->biHeight
; getBitmapInfo()->biSizeImage
;
; For a complete struct overview visit
; https://msdn.microsoft.com/de-de/library/windows/desktop/dd183375(v=vs.85).aspx
; https://msdn.microsoft.com/de-de/library/windows/desktop/dd183376(v=vs.85).aspx
;========================================================;
Func getBitmapInfo()
$ret = DllCall($hDLL, 'ulong_ptr:cdecl', 'getBitmapInfo', "ptr", $hBot)
if(@error) Then
ConsoleWrite("Error Code " & @error & " in colorDistance()" & @CRLF)
Exit(-1);
EndIf
$bmiStruct = DllStructCreate($tagBITMAPINFOHEADER, $ret[0])
return $bmiStruct;
EndFunc
;========================================================;
; Starts the Bot
;========================================================;
Func startBot($window)
$hDLL = DllOpen("daiBot.dll") ;load the DLL
$hBot = DllCall($hDLL, "ptr:cdecl", "GetDB")[0]; //create an instance of daiBot
$window = getHandle("BlueStacks App Player")
$pixels = init($window)
EndFunc
C Exports (If you want to write a wrapper for another language)
Code:
extern "C" {
// C-Wrapper für daiBotInterface
__declspec(dllexport) daiBotInterface* GetDB() {
return static_cast<daiBotInterface*>(new daiBot());
}
// C-Wrapper für HWND getHandle(const wchar_t * lpWindowName);
__declspec(dllexport) HWND getHandle(void* object, const wchar_t * lpWindowName) {
daiBotInterface* instance = static_cast<daiBotInterface*>(object);
return instance->getHandle(lpWindowName);
}
// C-Wrapper für daiBotInterface.init(const HWND & handle)
__declspec(dllexport) BYTE * init(void* object, int handle) {
daiBotInterface* instance = static_cast<daiBotInterface*>(object);
return instance->init((HWND)handle);
}
// C-Wrapper für daiBotInterface.loadBitmap()
__declspec(dllexport) void loadBitmap(void* object) {
daiBotInterface* instance = static_cast<daiBotInterface*>(object);
instance->loadBitmap();
}
// C-Wrapper für void saveBitmap(const char * filePath);
__declspec(dllexport) void saveBitmap(void* object, const char * filePath) {
daiBotInterface* instance = static_cast<daiBotInterface*>(object);
instance->saveBitmap(filePath);
}
// C-Wrapper für int getPixel(const int x, const int y);
__declspec(dllexport) int getPixel(void* object, int x, int y) {
daiBotInterface* instance = static_cast<daiBotInterface*>(object);
return instance->getPixel(x,y);
}
// C-Wrapper für void click(int x, int y);
__declspec(dllexport) void click(void* object, int x, int y) {
daiBotInterface* instance = static_cast<daiBotInterface*>(object);
instance->click(x, y);
}
// C-Wrapper für void drag(int xFrom, int yFrom, int xTo, int yTo, float speed);
__declspec(dllexport) void drag(void* object, int xFrom, int yFrom, int xTo, int yTo, float speed) {
daiBotInterface* instance = static_cast<daiBotInterface*>(object);
instance->drag(xFrom, yFrom, xTo, yTo, speed);
}
// C-Wrapper für void pDrag(int x[], int y[], int num, float speed);
__declspec(dllexport) void pDrag(void* object, int * x, int * y, int num, float speed) {
daiBotInterface* instance = static_cast<daiBotInterface*>(object);
instance->pDrag(x, y, num, speed);
}
// C-Wrapper für void move(int xFrom, int yFrom, int xTo, int yTo, float speed);
__declspec(dllexport) void move(void* object, int xFrom, int yFrom, int xTo, int yTo, float speed) {
daiBotInterface* instance = static_cast<daiBotInterface*>(object);
instance->move(xFrom, yFrom, xTo, yTo, speed);
}
// C-Wrapper für int colorDistance(int R_value, int G_value, int B_value, int R_value2, int G_value2, int B_value2);
__declspec(dllexport) int colorDistance2(void* object, int R_value, int G_value, int B_value, int R_value2, int G_value2, int B_value2) {
daiBotInterface* instance = static_cast<daiBotInterface*>(object);
return instance->colorDistance(R_value, G_value, B_value, R_value2, G_value2, B_value2);
}
// C-Wrapper für int colorDistance(int RGB1, int RGB2);
__declspec(dllexport) int colorDistance(void* object, int RGB1, int RGB2) {
daiBotInterface* instance = static_cast<daiBotInterface*>(object);
return instance->colorDistance(RGB1, RGB2);
}
// C-Wrapper für BITMAPINFO * getBitmapInfo();
__declspec(dllexport) BITMAPINFOHEADER * getBitmapInfo(void* object) {
daiBotInterface* instance = static_cast<daiBotInterface*>(object);
return &instance->getBitmapInfo()->bmiHeader;
}
}
Interface.h (pure virtual)
Code:
#pragma once
#ifndef DAIAPI
#ifdef DAI_EXPORTS
#define DAIAPI __declspec(dllexport)
#else
#define DAIAPI __declspec(dllimport)
#endif
#include <Windows.h>
#endif
struct daiBotInterface {
/**
Receives the HWND of @lpWindowName
@author Daifoku
@param lpWindowName The window name (the window's title). If this parameter is NULL, getHandle returns the desktop handle.
@return If the function succeeds, the return value is a handle to the window that has the specified window name.
If the function fails, the return value is NULL
*/
virtual HWND getHandle(const wchar_t * lpWindowName) = 0;
/**
Creates the Bitmap structure
cDC, hDC, BITMAPINFO
uses CreateDIBSection
@author Daifoku
@example
BYTE* pixels = NULL;
BITMAPINFO * bmi = bitmap::initDeviceContext(windowHandle, hDC, cDC, (LPVOID*) &pixels);
@param handle Handle to a window
@return Returns a pointer to all pixels
*/
virtual BYTE * init(const HWND & handle) = 0;
/**
Load all pixels into the hDC
uses BitBlt to SRCCOPY all bits
@author Daifoku
*/
virtual void loadBitmap() = 0;
/**
Saves @pixels into a bitmap
@author Daifoku
@time 2.3ms
@param filePath relative or absolute path, e.g. "image.bmp"
*/
virtual void saveBitmap(const char * filePath) = 0;
/**
Gets the color of the pixel @x,@y
@author Daifoku
@time 0ms
@param x x-position of the pixel
@param y y-position of the pixel
@return color in format RGB
*/
virtual int getPixel(const int x, const int y) = 0;
/**
Clicks at position @x,@y (relative to the client)
@param handle HWND of the window to click in
@param x x-pos
@param y y-pos
*/
virtual void click(int x, int y) = 0;
/**
Drags the mouse from one position to another
Simulates mouse movements (!) - no instant move
@param xFrom x-pos from
@param yFrom y-pos from
@param xTo x-pos to
@param yTo y-pos to
@param speed You can adjust the movement speed. Setting a higher value increases the speed. Speed has to be greater than 0.
*/
virtual void drag(int xFrom, int yFrom, int xTo, int yTo, float speed = 10) = 0;
/**
Drags the mouse along the polygon
Posts a MouseDown message to the specified window at position x[0],y[0]
Moves the mouse from one coordinate to another x[i],y[i] to x[i+1],y[i+1]
Posts a MouseUp message at position x[num-1],y[num-1]
@author Daifoku
@param x x koordinates.
@param y y koordinates
@param num Number of koordinates in x[],y[]
@param speed You can adjust the movement speed. Setting a higher value increases the speed.
*/
virtual void pDrag(int x[], int y[], int num, float speed = 10) = 0;
/**
Moves the mouse
Does not click (Use function @drag to include MouseDown/MouseUp messages)
@author Daifoku
@param xFrom x-pos from
@param yFrom y-pos from
@param xTo x-pos to
@param yTo y-pos to
@param speed You can adjust the movement speed. Setting a higher value increases the speed. Speed has to be greater than 0.
*/
virtual void move(int xFrom, int yFrom, int xTo, int yTo, float speed = 10) = 0;
/**
Converts RGB value to Lab and calculates the euclidian distance
@brief You can use triplets or RGB as int. The following calls are equal.
colorDistance(0x00, 0xEE, 0xFF, 0x01, 0xCC, 0xCC)
colorDistance(0x00EEFF, 0x01CCCC)
*/
virtual int colorDistance(int R_value, int G_value, int B_value, int R_value2, int G_value2, int B_value2) = 0;
virtual int colorDistance(int RGB1, int RGB2) = 0;
/**
Returns the BITMAPINFO struct
@brief Important parameter :
getBitmapInfo()->bmiHeader.biWidth
getBitmapInfo()->bmiHeader.biHeight
getBitmapInfo()->bmiHeader.biSizeImage
For a complete struct overview visit
https://msdn.microsoft.com/de-de/library/windows/desktop/dd183375(v=vs.85).aspx
https://msdn.microsoft.com/de-de/library/windows/desktop/dd183376(v=vs.85).aspx
*/
virtual BITMAPINFO * getBitmapInfo() = 0;
};
typedef daiBotInterface* dHANDLE;
extern "C" {
//DAIAPI dHANDLE WINAPI GetDB(VOID);
__declspec(dllexport) daiBotInterface* GetDB();
}
C++ Example
Code:
#include "stdafx.h"
#include "interface.h"
#include <iostream> //std::cout | std::cin in main()
#pragma comment(lib,"daiBot")
int main()
{
dHANDLE bot = GetDB();
//Get a Handle
//use daiBot::getHandle(NULL) to get the DesktopWindow
HWND windowHandle = FindWindow(NULL, L"BlueStacks App Player");
if (!windowHandle) return 0;
//Get the bitmap corresponding to @windowHandle
BYTE * pixels = bot->init(windowHandle);
//loading the bitmap into the context
//(Not needed here, because initDeviceContext already loads the image into the context)
//But if you want to reload the image at a different time, you have to call it like this.
bot->loadBitmap(); // 2.3 ms per run
//Analyze pixels here...
//color at position x=120,y=954
bot->getPixel(120, 954);
//Click at pos 420, 846
bot->click(420, 846);
//Drag from pos 420, 846 to 0,0
bot->drag(420, 846, 0,0, 10);
// Performing a polygon drag (pDrag).
// this drags the element at position (460,573) to position (180,758) and visits on the way the other two coordinates
// You can use as many coordinates as you like
int x[4] = { 460, 460, 180, 180 };
int y[4] = { 573, 856 , 856, 758 };
bot->pDrag(x, y, 4);
//Saving the image.
//you might want to manipulate the pixels before saving
bot->saveBitmap("image.bmp");
std::cin.get();
return 0;
}
AutoIt Example
PHP Code:
#RequireAdmin
#include "daiBot.au3"
startBot("BlueStacks App Player") ; Target BlueStacks. You always have to set a Target to work with.
loadBitmap() ; call this to refresh the image buffer
if(colorDistance(getPixel(141, 923),0x00EE00) < 100) Then ; gets the color at position (141, 923) and compares the result with 0x00EE00
ConsoleWrite("The colors match" & @CRLF) ; A difference of 0 means, that it is an exact match. All values lower than ~ 100 are nearly equal.
EndIf ;
click(425, 821) ; clicks at position (425, 821)
saveBitmap("test.bmp") ; saves the buffer to test.bmp
drag(275, 857, 275, 667) ; drags the mouse from Position (275, 857) to (275, 667)
; Performing a polygon drag (pDrag).
; this drags the element at position (460,573) to position (180,758) and visits on the way the other two coordinates
; You can use as many coordinates as you like
Local $xArr[4] = [460, 460, 180, 180]
Local $yArr[4] = [573, 856 , 856, 758]
pDrag($xArr, $yArr)
; Getting some infos about the captured window/image
$bmiStruct = getBitmapInfo() ; take a look at $tagBITMAPINFOHEADER for all values.
ConsoleWrite("Bitmap-Size: " & $bmiStruct.biWidth & " x " & -$bmiStruct.biHeight & @CRLF);
DllClose($hDLL) ; do not forget to close the DLL when you are done !
C++ Tutorial for daiBot.dll :

You can find all files in the attachements. Examples are also included (Except the c++ one..
BugFixes
-----------------------------------------------------
AutoIt Wrapper: small bug in Func startBot($window)
replace $window = getHandle("BlueStacks App Player")
with $window = getHandle($window)
.. will be fixed in the next version
Changelog
15/10/2015 17:47 Initial Release







