最近迷上了魔兽真三国无双,但是一次一次的挤房间然我很不爽。
本程序将自动尝试进入浩方真三的上海菜鸟房
需要进浩方然后选 竞技-真三-上海专区
日期:2011年11月22日
编程思路:
- 用SPYXX分析窗口结构,取得父窗体以及那个ListView窗体的句柄。
- 发送LVM_GETITEMTEXT判断房间人数是否大于240,否则继续下一个房间,不尝试进入。
- 用LVM_GETITEMTEXT消息取得Item的文本,是否包含 "积分菜鸟",不包含继续下一个房间,不尝试进入。
- 如果满足2和3 ,就 用LVM_GETITEMPOSITION消息取得ListView控件的Item坐标
- 用WM_LBUTTONDBLCLK消息模拟鼠标双击
- 是否出现人满的那个提示窗口,出现则关闭他,继续下一个房间。 未出现则判断ListView窗口是否可见,不可见判定进入房间成功,程序退出, 上面两种情况必须出现其中一种 如果到了最后一个房间则又从头开始
要点:
- 鼠标点的构造
- 跨进程编程
- 利用EnumWindows和StrStr函数来锁定窗口
#pragma comment(lib,"shlwapi.lib")
#pragma comment(lib,"shlwapi.lib")
#include
#include
#include
#include
HWND hTop; //电竞平台最顶层窗口句柄
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
char pszWindowText[300];
GetWindowText(hwnd,pszWindowText,300);
if(StrStr(pszWindowText,"浩方电竞平台") != NULL){
hTop = hwnd;
return FALSE;
}
return TRUE;
}
//取得ListView的句柄
HWND GetHandleOfListView()
{
HWND h;
EnumWindows(EnumWindowsProc,0);
if(hTop == 0){
MessageBox(0,"发生错误,请登录浩方,定位到\n竞技-真三-上海专区"," ",0);
ExitProcess(0);
}
h= FindWindowEx(hTop,NULL,"#32770",NULL); //其下只有一个子窗口
h = FindWindowEx(h,NULL,"#32770",NULL); //第一个子窗口
h = FindWindowEx(h,NULL,"#32770",NULL); //继续
h = FindWindowEx(h,NULL,"SysListView32",NULL); //终于找到了
return h;
}
//用鼠标点生成鼠标双击消息的LPARAM
LONG makeLPARAM(LONG x,LONG y)
{
y = y<<16;
return y|x;
}
int main()
{ //from:起始值 to:最大值 index:现在值
int index=0,from=0,to=0;
char *b= NULL;
char itemBuf[512];
char *pszItemText; //
LVITEM *pListViewItem = NULL; //用指针来保存ListView的一个Item结构的地址
LVITEM lv;
PPOINT pPoint;
HANDLE hProcess; //浩方的进程句柄
HWND hRenMan; //人数已满的那个窗口的句柄
DWORD dwProcessId; //浩方进程的ID号
POINT pt;
//获取ListView的句柄
HWND h = GetHandleOfListView();
SendMessage(h,LVM_GETITEMCOUNT,0,0);
_asm mov [to],eax
_asm mov edi,to
_asm sub edi,1
_asm mov [to],edi
GetWindowThreadProcessId(hTop,&dwProcessId); //浩方进程ID
hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessId);//得到进程句柄
//在浩方进程里面分配内存
pPoint = (PPOINT)VirtualAllocEx(hProcess,NULL,sizeof(POINT),MEM_COMMIT,PAGE_READWRITE);
pListViewItem = (LVITEM*)VirtualAllocEx(hProcess,NULL,sizeof(LVITEM),MEM_COMMIT,PAGE_READWRITE);
pszItemText = (char*)VirtualAllocEx(hProcess,NULL,512,MEM_COMMIT,PAGE_READWRITE);
lv.cchTextMax = 512;
//把在浩方进程里面分配存放ItemText的内存空间的地址的值传递给lv.pszText
lv.pszText = pszItemText;
lable:
//取得房间人数
lv.iSubItem = 1; //第二列是 1 ,第一列是 0
//为浩方进程里的 存放LVITEM(ListViewItem)结构 的内存块赋值
WriteProcessMemory(hProcess,pListViewItem,&lv,sizeof(LVITEM),NULL);
//读取 第index行, 第2列 的字符串 返回的值存放在浩方进程的内存空间
SendMessage(h,LVM_GETITEMTEXT,index,(WPARAM)pListViewItem);
//从pszItemText地址开始,读取512个内存单位(字节),放在itemBuf里面
ReadProcessMemory(hProcess,pszItemText,itemBuf,512,NULL);
b=strtok(itemBuf,"/"); //从 **/250 中截取出**
if(atoi(b)<240 240="" index="" if="" index="">to) index=from;
goto lable;
}
//读取房间名称
lv.iSubItem = 0;
WriteProcessMemory(hProcess,pListViewItem,&lv,sizeof(LVITEM),NULL);
SendMessage(h,LVM_GETITEMTEXT,index,(WPARAM)pListViewItem);
ReadProcessMemory(hProcess,pszItemText,itemBuf,512,NULL);
// StrStr 成功的话返回 第一次出现 "积分菜鸟" 的内存地址,失败就返回NULL
if(StrStr(itemBuf,"积分菜鸟") == NULL){
_asm mov edi,index
_asm add edi,1
_asm mov [index],edi
if(index>to) index=from;
goto lable;
}
printf("尝试进入\t%s\n",itemBuf);
//读取坐标
SendMessage(h,LVM_GETITEMPOSITION,index,(LPARAM)(POINT FAR *)pPoint);
ReadProcessMemory(hProcess,pPoint,&pt,sizeof(POINT),NULL);
//发送鼠标双击消息
PostMessage(h,WM_LBUTTONDBLCLK,1,makeLPARAM(pt.x,pt.y));
while(1){
Sleep(1000);
hRenMan = FindWindow("#32770","浩方电竞平台");
if(hRenMan){ //人满继续下一个房间
printf("失败..\n");
SendMessage(hRenMan,WM_CLOSE,0,0);
index++;
if(index>to) index=from;
goto lable;
}
//如果没有出现人满那个窗口,就判断 那个 ListView窗口是否Visible,不存在就认为是进入了房间,
//然后 释放系统资源,退出程序
if(IsWindowVisible(h) == FALSE){
VirtualFreeEx(hProcess,pPoint,0,MEM_RELEASE); //释放内存
VirtualFreeEx(hProcess,pListViewItem,0,MEM_RELEASE);
VirtualFreeEx(hProcess,pszItemText,0,MEM_RELEASE);
CloseHandle(hProcess);
break;
}
}
return 0;
}