经常上hf平台,挤不进去自己想进去的房间,花了一天多时间研究了一下,因此有了以下的文章.

 

 
  
  1. /*  
  2.     witten by       :       edmonddonteszhang@gmail.com (applebomb) 
  3.     history         :       2012/6/2 (ver 1) 
  4.     information :       一直在玩浩方DOTA IMBA, 总是进不了450人房间, 一气之下花了时间研究 
  5.                                     怎么搞自动挤房间. 因此有了下面的程序 
  6.                                     浩方版本: 5.8.1.516-20120528 
  7.  
  8.     how to use  :       打开电信 DOTA IMBA 房间, 运行程序进行自动挤房间  
  9.  
  10.     attention!! :       花时间自己写的同学注意两点, 在这两点上浪费了一天时间.  
  11.                                     第一: WM_NOTIFY 的消息结构是发送给父窗口而非控件本身, 不过对于ListView控件 
  12.                                           来说, 似乎用WM_NOTIFY发送双击动作结构体 不起作用 
  13.                                                 { 如果有成功的同学请邮件告诉我方法, 谢谢! } 
  14.                                     第二: 运行程序时候需要以Administrator身份, 否则用 GetLastError() = Access Denied 
  15.      
  16.     how to do       :   step 1. 找出浩方窗口 
  17.                                     step 2. 找出登录列表 
  18.                                     step 3. openProcess 浩方进程, 在里面分配几个获取信息的变量 
  19.                                     step 4. 发送消息让取得信息 
  20.                                     step 5. ReadProcessMemory 读取 step4得到的信息 
  21.                                     step 6. 获取房间在控件中的相对坐标 
  22.                                     step 7. 发送信息点击登陆房间 
  23.                                     step 8. 如果弹出 Type: "#32770", Name: "浩方电竞平台" 的窗口, 则登录不成功 
  24.                                     step 9. 如果看不见登录列表, 则登录成功 
  25. */ 
  26.  
  27. #include <stdio.h> 
  28. #include <Windows.h> 
  29. #include <WinDef.h> 
  30. #include <CommCtrl.h> 
  31. #include <WinUser.h> 
  32.  
  33. /* funciton declare */ 
  34. BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lparam);  /* 枚举浩方主进程 */ 
  35. BOOL CALLBACK EnumChildWindowsProc(HWND hwnd, LPARAM lparam); /* 枚举窗口子进程 */ 
  36.  
  37. int main (int argc, const char *argv[]) 
  38.     ::EnumWindows((WNDENUMPROC)EnumWindowsProc, 0); // 查找浩方主进程 
  39.     getchar();  
  40.     return 0; 
  41.  
  42. /* 
  43.     查找浩方主进程 
  44. */ 
  45. BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lparam) 
  46.     char programName[256]; 
  47.     ::GetWindowTextA(hwnd, programName, 256-1); 
  48.     if (strstr(programName, "浩方电竞平台")!=NULL) 
  49.     { 
  50.         printf ("Found main program window. \n"); 
  51.         ::EnumChildWindows(hwnd, (WNDENUMPROC)EnumChildWindowsProc, 0); /* 找到主窗口, 枚举找出ListView控件*/ 
  52.     } 
  53.     return true
  54.  
  55. /* 
  56.     查找ListView控件 
  57. */ 
  58. BOOL CALLBACK EnumChildWindowsProc(HWND hwnd, LPARAM lparam) 
  59.     char hwndName[256]; 
  60.     ::GetClassNameA(hwnd, hwndName, 256-1); //hwnd 正在枚举的控件 
  61.       
  62.     if (strcmp(hwndName,"SysListView32") == 0) { 
  63.         int nID = ::GetDlgCtrlID(hwnd); 
  64.         printf("nID : %d\n",nID);  
  65.          
  66.         if (nID == 257)  /*这里我是找出ListView的控件ID = 257 (还有id = 340, 513, 12001 这三个没有用)*/ 
  67.         { 
  68.             int find = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0,0); 
  69.              
  70.             //打开浩方进程 
  71.             DWORD ProcessID; 
  72.             HANDLE handle; 
  73.             ::GetWindowThreadProcessId(hwnd, &ProcessID); 
  74.             handle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, ProcessID); 
  75.              
  76.             LVITEM *_lvi, lvi; /* 指向一条ListView 记录*/ 
  77.             WCHAR *_item, *_subitem; /* */ 
  78.             WCHAR item[512], subitem[512]; 
  79.             PPOINT ppoint; 
  80.             POINT pt; 
  81.              
  82.             /* 在浩方进程分配获取信息空间 */ 
  83.             _lvi = (LVITEM*)VirtualAllocEx(handle, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE); 
  84.             _item = (WCHAR*)VirtualAllocEx(handle, NULL, 512, MEM_COMMIT, PAGE_READWRITE); 
  85.             _subitem = (WCHAR*)VirtualAllocEx(handle, NULL, 512, MEM_COMMIT, PAGE_READWRITE); 
  86.             ppoint = (PPOINT)VirtualAllocEx(handle, NULL, sizeof(POINT), MEM_COMMIT, PAGE_READWRITE); 
  87.        
  88.             int roomindex = 0;  /* 从0开始枚举房间 */ 
  89.             bool getinflag =false/* 登陆成功标志 */ 
  90.             while (!getinflag) 
  91.             { 
  92.                 lvi.iSubItem=0; /* Listview中第一项房间名 */ 
  93.                 lvi.cchTextMax=512; /*Number of TCHARs in the buffer pointed to by pszText, including the terminating NULL.*/ 
  94.                 lvi.pszText=(LPWSTR)_item; /* 将浩方进程里面将要存放房间名称的地址传递给lvi */ 
  95.                  
  96.                 WriteProcessMemory(handle, _lvi, &lvi, sizeof(LVITEM), NULL); /* 将定义好的lvi结构写到上面在浩方分配的内存里 */ 
  97.                 SendMessage(hwnd, LVM_GETITEMTEXT, (WPARAM)roomindex, (LPARAM)_lvi); /* 发送消息将结果写在 _item指定的内存里*/ 
  98.  
  99.                 lvi.iSubItem=1; /*人数*/ 
  100.                 lvi.pszText=(LPWSTR)_subitem; 
  101.                 WriteProcessMemory(handle, _lvi, &lvi, sizeof(LVITEM), NULL); 
  102.                 SendMessage(hwnd, LVM_GETITEMTEXT, (WPARAM)roomindex, (LPARAM)_lvi); 
  103.  
  104.                 // 将浩方进程里取得的结果读回登陆器进程内存 
  105.                 ReadProcessMemory(handle, _item, item, 512, NULL); 
  106.                 ReadProcessMemory(handle, _subitem, subitem, 512, NULL); 
  107.     
  108.                 // 比较当前房间是否是需要进入的房间 
  109.                 wchar_t *pRoomName = wcsstr(item, L"IMBA"); /* 电信 IMBA */ 
  110.                 wchar_t *pRoomCont = wcsstr(subitem, L"/450");  /* 450人 */ 
  111.    
  112.                 if (pRoomName && pRoomCont){ 
  113.                     printf ("find the room."); //找到合适的房间, 尝试登陆 
  114.  
  115.                     //选择房间 
  116.                     lvi.state = LVIS_SELECTED; 
  117.                     lvi.stateMask = LVIS_SELECTED; 
  118.                     WriteProcessMemory(handle, _lvi, &lvi, sizeof(LVITEM), NULL); 
  119.                     ::SendMessage(hwnd, LVM_SETITEMSTATE, (WPARAM)roomindex, (LPARAM)_lvi ); 
  120.  
  121.                     /* 取得房间一栏在浩方里面的相对位置, LVM_GETITEMPOSITION 消息比较简单,  
  122.                      不需要用到WriteProcessMemory 写入控制信息 */ 
  123.                     ::SendMessage(hwnd, LVM_GETITEMPOSITION, roomindex, (LPARAM)ppoint); 
  124.                     ::ReadProcessMemory(handle, ppoint, &pt, sizeof(POINT), NULL); 
  125.  
  126.                     // 模拟双击房间, postmessage 直接返回, sendmessage 等待结果再返回 
  127.                     PostMessage(hwnd, WM_LBUTTONDBLCLK, MK_LBUTTON, MAKELPARAM(pt.x, pt.y)); 
  128.            
  129.                     // 检查是弹出"人满不能进入, 或者登陆上了房间" 
  130.                     int waittime = 0; /* 超时从新尝试另一个房间 */ 
  131.                     while(1) 
  132.                     { 
  133.                         /* 不能进入房间, 这里参考了  
  134.                             http://blog.csdn.net/courage3000/article/details/7526475 检查代码 
  135.                         */ 
  136.                         HWND hRenMan = FindWindowA("#32770""浩方电竞平台"); 
  137.                         if (hRenMan) {   
  138.                             printf("fail to login in. find next room.\n");         
  139.                             SendMessage(hRenMan, WM_CLOSE, 0, 0); 
  140.                             break;        
  141.                         }else
  142.                          if (!IsWindowVisible(hwnd)) 
  143.                          {           
  144.                              getinflag = true;   
  145.                              break
  146.                          } // !iswindowvisible 
  147.                         } // if hRenMan 
  148.                          
  149.                         waittime++; // 超时尝试登陆另一个房间 
  150.                         if (waittime > 10) break
  151.                         Sleep(1000); 
  152.                        
  153.                     } // while(1) 
  154.                 } //if pRoomName && pRoomCont 
  155.                  
  156.                 if (roomindex++ >= find) /*不能登陆成功重新尝试*/ 
  157.                     roomindex =0; 
  158.             } 
  159.              
  160.             VirtualFreeEx(handle, _lvi, 0, MEM_RELEASE); // 释放内存  
  161.             VirtualFreeEx(handle, _item, 0, MEM_RELEASE);  
  162.             VirtualFreeEx(handle, _subitem, 0, MEM_RELEASE); 
  163.             VirtualFreeEx(handle, ppoint, 0, MEM_RELEASE); 
  164.         }        
  165.     } 
  166.     return true
  167.  
  168.  
  169. /* 
  170. * subprogram : 用鼠标找出鼠标位置的子窗口句柄 
  171. */ 
  172. void subprogram_findWNDbyMouse() 
  173. {/* 
  174.      
  175.     POINT pt; 
  176.     ::GetCursorPos(&pt);     
  177.     HWND wfp =  ::WindowFromPoint(pt); 
  178.     if (wfp != NULL && ::GetParent(wfp) == hwnd) 
  179.     { 
  180.         printf ("mouse point at: %d, %d",pt.x,pt.y); 
  181.      
  182.         printf ("mouse point: find window : "); 
  183.          
  184.         char lpsubWinName[256], plsubWinText[256]; 
  185.         ::GetClassNameA(wfp, lpsubWinName, 256 - 1); 
  186.         ::GetWindowTextA(wfp, plsubWinText, 256-1); 
  187.         printf (" %s    %s\n", lpsubWinName, plsubWinText); 
  188.     } 
  189. */