[MFC/C++] Class: CBotEngine
Hier mal eine recht simple Klasse um das Bot schreiben zu vereinfachen. Natürlich ist es sehr primitiv aber vielleicht hilft es dem ein oder anderen.
Hier mal eine recht simple Klasse um das Bot schreiben zu vereinfachen. Natürlich ist es sehr primitiv aber vielleicht hilft es dem ein oder anderen.
#Inhalt:
[-]Klassenbeschreibung
[-]Beispielcode/Benutzung
[-]Nachwort
[-]Klassenbeschreibung
Die Klasse ist in Visual C++ (MFC) geschrieben und Unicode kompatibel.
Zur Zeit hat es nur 6 Funktionen:
SendKey(), um einen Tastendruck zu simulieren mit VKs.
SendText(), um einen ganzen Text zu senden bzw. einen CString.
TargetWindow(), um ein Fensterhandle zu holen.
MemoryRead(), um eine Adresse auszulesen.
sRead(), um aus einer ini Datei Werte zu lesen.
MouseClick(), um einen Mausklick zu simulieren.
Die Funktionen wurden in der Klasse so weit wie möglich vereinfacht, damit man sie leicht benutzten kann. Außerdem sind die Funktionen so programmiert, dass sie im Hintergrund laufen. Sprich wenn der Bot läuft, könnt ihr das Spiele Fenster minimieren und etwas anderes machen.
CBotEngine.h:
PHP Code:
#pragma once
/***************************************************************************
* CBotEngine v 1.0
* SendKey() Sendet einen Tastendruck. Benutztung mit Virtual Key Codes
* SendText() Sendet einen Text. Benutzung mit CString
* TargetWindow() Holt sich den Window Handle
* MemoryRead() Liest Speicheradresse aus
* sRead() Liest einen String aus einer INI Datei aus
* MouseClick() Maus macht einen Klick an einer bestimmten Koordinate
***************************************************************************/
class CBotEngine
{
public:
CBotEngine(void);
~CBotEngine(void);
void SendKey(unsigned int KEY, DWORD DELAY=20);
void SendText(CString strText);
void TargetWindow(CString strWnd);
int MemoryRead(unsigned address);
CString sRead(CString strIniName, CString AppName, CString KeyName);
void MouseClick(int xPos, int yPos, DWORD DELAY=100);
CWnd *pWnd;
HWND hWnd;
DWORD procID;
};
PHP Code:
#include "StdAfx.h"
#include "BotEngine.h"
#define BUFSIZE MAX_PATH
CBotEngine::CBotEngine(void)
{
}
CBotEngine::~CBotEngine(void)
{
}
void CBotEngine::SendKey(unsigned int KEY, DWORD DELAY)
{
LPARAM pmLparam = (::MapVirtualKey(KEY,0)<<16);
pWnd->PostMessage(WM_KEYDOWN,0,pmLparam);
pWnd->PostMessage(WM_CHAR,0,pmLparam);
Sleep(DELAY);
pWnd->PostMessage(WM_KEYUP,0,pmLparam);
}
void CBotEngine::TargetWindow(CString strWnd)
{
if (pWnd = CWnd::FindWindowExW(NULL,NULL,NULL,strWnd)) {
hWnd = HWND(pWnd->GetSafeHwnd());
GetWindowThreadProcessId(hWnd,&procID);
}else{
AfxMessageBox(_T("Fenster nicht gefunden!"));
}
}
int CBotEngine::MemoryRead(unsigned address)
{
int i;
DWORD numBytesRead;
GetWindowThreadProcessId(hWnd,&procID);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
ReadProcessMemory(hProc, (LPCVOID)address, &i, sizeof(i), &numBytesRead);
CloseHandle(hProc);
return i;
}
CString CBotEngine::sRead(CString strIniName, CString AppName, CString KeyName)
{
CString strBuf;
TCHAR cDic[BUFSIZE];
GetCurrentDirectoryW(BUFSIZE,cDic);
CString sDic = CString(cDic);
sDic.Format(_T("%s\\%s"),cDic,strIniName);
GetPrivateProfileString(AppName,KeyName,_T(""),strBuf.GetBuffer(254),254,sDic);
return strBuf;
}
void CBotEngine::MouseClick(int xPos, int yPos, DWORD DELAY)
{
pWnd->SendMessage(WM_LBUTTONDOWN,MK_LBUTTON,MAKELPARAM(xPos,yPos));
Sleep(DELAY);
pWnd->SendMessage(WM_LBUTTONUP,MK_LBUTTON,MAKELPARAM(xPos,yPos));
}
void CBotEngine::SendText(CString strText)
{
unsigned int *iText;
iText = new unsigned int[strText.GetLength()];
for (int i =0;i <= strText.GetLength();i++)
{
iText[i] = strText[i];
pWnd->PostMessage(WM_KEYDOWN,iText[i],0);
Sleep(70);
}
}
[-]Beispielcode/Benutzung
Ihr müsst als erstes die CBotEngine.h und CBotEngine.cpp in euer Projekt einbinden. Im Anhang hab ich diese nochmal gepackt und dort ist auch eine VKC.h die nochmal die Virutal Key Codes beinhaltet, da (bei mir jedenfalls) in MFC nicht alle Codes definiert sind. Nachdem ihr die Header eingebunden habt, braucht ihr nur euer Objekt erstellen und könnt dann die Funktionen nutzen.
Beispielcode:
Fensterhandle holen und Key Senden, Text Senden
PHP Code:
CBotEngine MyBot; /* Objekt wird erstellt */
CString WindowName = _T("MeinSpiel"); /* CString Variable mit Namen des Spiels wird erstellt */
CString CustomText = _("/giveup"); /* CString Variable mit einem Text wird erstellt */
MyBot.TargetWindow(WindowName); /* CBotFunktion wird aufgerufen und die Variable WindowName übergeben, jetzt haben wir das Handle um an das Fenster senden zu können */
MyBot.SendKey(VK_I); /* Simuliert den Tastendruck, der Taste I und sendet ihn an das Spielefenster. Zum Beispiel um das Inventar zu öffnen */
Sleep(200); /* Damit die nächste Taste nicht zu schnell hintereinander kommt, brauchen wir hier ein Sleep um eine verzögerung rein zu bringen */
MyBot.SendKey(VK_RETURN); /* Drückt die Enter Taste um z.B. den Chat zu öffnen */
Sleep(200);
MyBot.SendText(CustomText); /*Sendet den Inhalt der Variable Custom Text an die Funktion. Das heißt in userem Fall es wird "/giveup" in den Chat eingegeben */
Sleep(200);
MyBot.SendKey(VK_RETURN) /* Es wird nochmal Enter gedrückt. Text im Chat wird also abgeschickt */
Beispielcode #2:
Werte aus einer INI Datei Lesen.
Sagen wir unsere INI Datei (settings.ini) ist so aufgebaut:
Code:
[SETTINGS] Sprache=0 AnzahldRunden=40 Verkaufen=1 [MEMORY] posx=0x41000 posy=0x41004
PHP Code:
CBotEngine rd; // Unser Objekt
CString ininame = _T("settings.ini"); //Name der Ini datei
CString section[2] = {_T("SETTINGS"),_T("MEMORY")};
CString key[5] = {_T("Sprache"),_T("AnzahldRunden"),_T("Verkaufen"),_T("posx"),_T("posy")};
m_strSprache = rd.sRead(ininame,section[1],key[1]);
m_strRunden = rd.sRead(ininame,section[1],key[2]);
m_strVerkauf = rd.sRead(ininame,section[1],key[3]);
m_strPosx = rd.sRead(ininame,section[2],key[1]);
m_strPosy = rd.sRead(ininame,section[2],key[2]);
[-]Nachwort
Die Klasse sollte eigentlich bei allen Spielen Funktionieren. Ich hoffe ich konnte euch damit etwas Arbeit ersparen. Auch wenn diese Klasse nicht das Gelbe vom Ei ist.
Für Verbesserungsvorschläge bin ich offen :)
So far,
Adroxxx