Assist.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281
  1. #include "StdAfx.h"
  2. #include "Assist.h"
  3. #include <D3D9.h>
  4. //#include <D3dx9tex.h>
  5. //#pragma comment(lib, "D3dx9.lib")
  6. // #pragma comment(lib, "d3d11.lib")
  7. // #pragma comment(lib, "dxgi.lib")
  8. namespace GAssist
  9. {
  10. int frameWidth = 2;
  11. int titleBarHeight = 25;
  12. TCHAR g_szCurModuleFileName[MAX_PATH];
  13. TCHAR g_szCurModuleDir[MAX_PATH];
  14. TCHAR g_szCurModulePath[MAX_PATH];
  15. TCHAR g_szFna[_MAX_FNAME];
  16. TCHAR g_szExt[_MAX_EXT];
  17. TCHAR g_szAssistConfig[MAX_PATH];
  18. std::string g_strAppdir;
  19. std::string g_strGameDir;
  20. TCHAR g_szGameApp[MAX_PATH];
  21. std::map<byte, byte> vsKey;
  22. std::vector<GWnd> g_vtGWnd;
  23. int nGameWndType;
  24. void Init()
  25. {
  26. TCHAR szDrive[_MAX_DRIVE] = { 0 };
  27. TCHAR szDir[_MAX_DIR] = { 0 };
  28. TCHAR szFna[_MAX_FNAME] = { 0 };
  29. TCHAR szExt[_MAX_EXT] = { 0 };
  30. DWORD dwRet = ::GetModuleFileName(NULL, g_szCurModuleFileName, sizeof(g_szCurModuleFileName) / sizeof(TCHAR));
  31. _tsplitpath_s(g_szCurModuleFileName, szDrive, szDir, g_szFna, g_szExt);
  32. _tcscat_s(g_szCurModuleDir, MAX_PATH, szDrive);
  33. _tcscat_s(g_szCurModuleDir, MAX_PATH, szDir);
  34. g_strAppdir = g_szCurModuleDir;
  35. _stprintf_s(g_szAssistConfig, _T("%s%s"), g_szCurModuleDir, _T("Assist.ini"));
  36. // 插入map;
  37. // https://blog.csdn.net/xiadasong007/article/details/5026948?utm_source=blogxgwz0;
  38. vsKey.insert(std::pair<byte, byte>(VK_F1, 0x3B));
  39. vsKey.insert(std::pair<byte, byte>(VK_F2, 0x3C));
  40. vsKey.insert(std::pair<byte, byte>(VK_F3, 0x3D));
  41. vsKey.insert(std::pair<byte, byte>(VK_F4, 0x3E));
  42. vsKey.insert(std::pair<byte, byte>(VK_F5, 0x3F));
  43. vsKey.insert(std::pair<byte, byte>(VK_F6, 0x40));
  44. vsKey.insert(std::pair<byte, byte>(VK_F7, 0x41));
  45. vsKey.insert(std::pair<byte, byte>(VK_F8, 0x42));
  46. vsKey.insert(std::pair<byte, byte>(VK_F9, 0x43));
  47. vsKey.insert(std::pair<byte, byte>(VK_F10, 0x44));
  48. vsKey.insert(std::pair<byte, byte>(VK_F11, 0x57));
  49. vsKey.insert(std::pair<byte, byte>(VK_F12, 0x58));
  50. vsKey.insert(std::pair<byte, byte>(VK_NUMLOCK, 0x45));
  51. vsKey.insert(std::pair<byte, byte>(VK_SCROLL, 0x46));
  52. vsKey.insert(std::pair<byte, byte>(VK_LSHIFT, 0x2A));
  53. vsKey.insert(std::pair<byte, byte>(VK_RSHIFT, 0x36));
  54. vsKey.insert(std::pair<byte, byte>(VK_LCONTROL, 0x1D));
  55. vsKey.insert(std::pair<byte, byte>(VK_RCONTROL, 0x58));
  56. vsKey.insert(std::pair<byte, byte>(VK_LMENU, 0x38));
  57. vsKey.insert(std::pair<byte, byte>(VK_RMENU, 0x58));
  58. vsKey.insert(std::pair<byte, byte>(VK_BACK, 0x0E)); // V;
  59. vsKey.insert(std::pair<byte, byte>(VK_TAB, 0x0F)); // V;
  60. vsKey.insert(std::pair<byte, byte>(VK_RETURN, 0x1C)); // V;
  61. vsKey.insert(std::pair<byte, byte>(VK_SHIFT, 0x2F)); // V;
  62. vsKey.insert(std::pair<byte, byte>(VK_CONTROL, 0x2F)); // V;
  63. vsKey.insert(std::pair<byte, byte>(VK_MENU, 0x2F)); // Alt;
  64. vsKey.insert(std::pair<byte, byte>(VK_PAUSE, 0x2F)); // V;
  65. vsKey.insert(std::pair<byte, byte>(VK_CAPITAL, 0x3A)); // V;
  66. vsKey.insert(std::pair<byte, byte>(VK_ESCAPE, 0x01)); // V;
  67. vsKey.insert(std::pair<byte, byte>(VK_SPACE, 0x39)); // 空格;
  68. // 方向键;
  69. vsKey.insert(std::pair<byte, byte>(VK_END, 0x0E)); // 空格;
  70. vsKey.insert(std::pair<byte, byte>(VK_HOME, 0x0E)); // 空格;
  71. vsKey.insert(std::pair<byte, byte>(VK_LEFT, 0x0E)); // 空格;
  72. vsKey.insert(std::pair<byte, byte>(VK_UP, 0x0E)); // 空格;
  73. vsKey.insert(std::pair<byte, byte>(VK_RIGHT, 0x0E)); // 空格;
  74. vsKey.insert(std::pair<byte, byte>(VK_DOWN, 0x0E)); // 空格;
  75. // 系统功能键;
  76. vsKey.insert(std::pair<byte, byte>(VK_PRINT, 0x54)); // 空格;
  77. vsKey.insert(std::pair<byte, byte>(VK_SNAPSHOT, 0x0E)); // 空格;
  78. vsKey.insert(std::pair<byte, byte>(VK_INSERT, 0x0E)); // 空格;
  79. vsKey.insert(std::pair<byte, byte>(VK_DELETE, 0x0E)); // 空格;
  80. vsKey.insert(std::pair<byte, byte>(VK_LWIN, 0x0E)); // 空格;
  81. vsKey.insert(std::pair<byte, byte>(VK_RWIN, 0x0E)); // 空格;
  82. // 小键盘;
  83. vsKey.insert(std::pair<byte, byte>(VK_NUMPAD0, 0x52));
  84. vsKey.insert(std::pair<byte, byte>(VK_NUMPAD1, 0x4F));
  85. vsKey.insert(std::pair<byte, byte>(VK_NUMPAD2, 0x50));
  86. vsKey.insert(std::pair<byte, byte>(VK_NUMPAD3, 0x51));
  87. vsKey.insert(std::pair<byte, byte>(VK_NUMPAD4, 0x4B));
  88. vsKey.insert(std::pair<byte, byte>(VK_NUMPAD5, 0x4C));
  89. vsKey.insert(std::pair<byte, byte>(VK_NUMPAD6, 0x4D));
  90. vsKey.insert(std::pair<byte, byte>(VK_NUMPAD7, 0x47));
  91. vsKey.insert(std::pair<byte, byte>(VK_NUMPAD8, 0x48));
  92. vsKey.insert(std::pair<byte, byte>(VK_NUMPAD9, 0x49));
  93. vsKey.insert(std::pair<byte, byte>(VK_MULTIPLY, 0x37));
  94. vsKey.insert(std::pair<byte, byte>(VK_ADD, 0x4E));
  95. vsKey.insert(std::pair<byte, byte>(VK_SEPARATOR, 0x0E));
  96. vsKey.insert(std::pair<byte, byte>(VK_SUBTRACT, 0x4A));
  97. vsKey.insert(std::pair<byte, byte>(VK_DECIMAL, 0x0E));
  98. vsKey.insert(std::pair<byte, byte>(VK_DIVIDE, 0x0E));
  99. }
  100. void GetGameConfig()
  101. {
  102. TCHAR szValue[MAX_PATH] = { 0 };
  103. GetPrivateProfileString(_T("Assist"), _T("GamePath"), _T(""), szValue, MAX_PATH, g_szAssistConfig);
  104. g_strGameDir = szValue;
  105. GetPrivateProfileString(_T("Assist"), _T("GameApp"), _T(""), g_szGameApp, MAX_PATH, g_szAssistConfig);
  106. // 读取窗口类型;
  107. _stprintf_s(szValue, _T("%s%s"), g_szGameApp, _T("save\\config.ini"));
  108. int ScreenWidth = GetPrivateProfileInt(_T("SysCfg"), _T("ScreenWidth"), 640, szValue);
  109. if (ScreenWidth == 640)
  110. nGameWndType = GW_SMALL;
  111. else if (ScreenWidth == 800)
  112. nGameWndType = GW_LARGE;
  113. else
  114. nGameWndType = GW_FULL;
  115. }
  116. void ShowLog(const TCHAR* format, ...)
  117. {
  118. return;
  119. // 获取今年年份;
  120. __time64_t gmt = time(NULL);// 获取当前日历时间(1900-01-01开始的Unix时间戳);
  121. struct tm gmtm = { 0 };
  122. localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;
  123. // 格式化前设置语言区域;
  124. TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL));
  125. _tsetlocale(LC_CTYPE, _T("chs"));//设定中文;
  126. // 格式化日志内容;
  127. va_list args = NULL;
  128. int len = 0;
  129. TCHAR* buffer = NULL;
  130. va_start(args, format);
  131. // _vscprintf doesn't count. terminating '\0'
  132. len = _vsctprintf(format, args) + 1;
  133. buffer = (TCHAR*)malloc(len * sizeof(TCHAR) + 8);
  134. _tcscat_s(buffer, len * sizeof(TCHAR) + 8, _T("\n"));
  135. _vstprintf_s(buffer, len, format, args);
  136. // 将日志内容输入到文件中;
  137. OutputDebugString(buffer);
  138. // 关闭文件,释放资源并设置回原语言区域;
  139. free(buffer);
  140. _tsetlocale(LC_CTYPE, old_locale);
  141. free(old_locale);//还原区域设定;
  142. }
  143. // 根据路径名查找进程,返回进程ID;
  144. DWORD FindProcess(IN LPCSTR lpProName)
  145. {
  146. DWORD dwProcessID = 0;
  147. PROCESSENTRY32 pe32 = { 0 };
  148. HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  149. if (hProcessSnap == NULL)
  150. {
  151. return 0;
  152. }
  153. pe32.dwSize = sizeof(PROCESSENTRY32);
  154. if (Process32First(hProcessSnap, &pe32)) {
  155. do {
  156. if (_tcscmp(lpProName, pe32.szExeFile) == 0) {
  157. dwProcessID = pe32.th32ProcessID;
  158. break;
  159. }
  160. } while (Process32Next(hProcessSnap, &pe32));
  161. }
  162. CloseHandle(hProcessSnap);
  163. return dwProcessID;
  164. }
  165. // 注意:一个进程可能拥有多个独立的窗口句柄;
  166. HWND GetProMainHwnd(DWORD dwProcessId)
  167. {
  168. DWORD dwPID = 0;
  169. HWND hwndRet = NULL;
  170. TCHAR szName[MAX_PATH] = { 0 };
  171. TCHAR szClass[MAX_PATH] = { 0 };
  172. TCHAR szLogMsg[MAX_PATH] = { 0 };
  173. // 取得第一个窗口句柄
  174. HWND hwndWindow = ::GetTopWindow(NULL);
  175. // 遍历出结果窗口;
  176. while (hwndWindow) {
  177. dwPID = 0;
  178. // 通过窗口句柄取得进程ID
  179. DWORD dwTheardID = ::GetWindowThreadProcessId(hwndWindow, &dwPID);
  180. if (dwTheardID != 0) {
  181. // 判断和参数传入的进程ID是否相等
  182. if (dwPID == dwProcessId) {
  183. // 进程ID相等,则记录窗口句柄
  184. hwndRet = hwndWindow;
  185. // 获取窗口类名,标题名;
  186. ::GetWindowText(hwndRet, szName, sizeof(szName) / sizeof(TCHAR));
  187. ::GetClassName(hwndRet, szClass, sizeof(szClass) / sizeof(TCHAR)); // 窗口类
  188. TRACE3(_T("类名:%s 标题:%s 地址%p\n"), szClass, szName, hwndRet);
  189. // 是否找到目前窗口;
  190. if (_tcsstr(szName, _T("大话水浒")))
  191. break;
  192. }
  193. }
  194. // 取得下一个窗口句柄
  195. hwndWindow = ::GetNextWindow(hwndWindow, GW_HWNDNEXT);
  196. }
  197. // 上面取得的窗口,不一定是最上层的窗口,需要通过GetParent获取最顶层窗口
  198. HWND hwndWindowParent = NULL;
  199. // 循环查找父窗口,以便保证返回的句柄是最顶层的窗口句柄
  200. while (hwndRet != NULL) {
  201. ::GetWindowText(hwndRet, szName, sizeof(szName) / sizeof(TCHAR));
  202. ::GetClassName(hwndRet, szClass, sizeof(szClass) / sizeof(TCHAR)); // 窗口类
  203. //TRACE3(_T("%s %s %s"), szClass, szName, "\n");
  204. _stprintf_s(szLogMsg, _T("类名:%s, 窗口名:%s,窗口地址:%p \n"), szClass, szName, hwndRet);
  205. OutputDebugString(szLogMsg);
  206. hwndWindowParent = ::GetParent(hwndRet);
  207. if (hwndWindowParent == NULL) {
  208. break;
  209. }
  210. hwndRet = hwndWindowParent;
  211. }
  212. // 返回窗口句柄
  213. return hwndRet;
  214. }
  215. DWORD GetProcessId(LPCTSTR lpProcessName /* = _T("Game.exe") */)
  216. {
  217. DWORD dwProcessId = 0;
  218. PROCESSENTRY32 pe32 = { 0 };
  219. HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  220. if (hProcessSnap == NULL) return 0;
  221. // 遍历进程;
  222. pe32.dwSize = sizeof(PROCESSENTRY32);
  223. for (BOOL bRet = Process32First(hProcessSnap, &pe32); bRet; bRet = Process32Next(hProcessSnap, &pe32)) {
  224. if (_tcscmp(lpProcessName, pe32.szExeFile) == 0) {
  225. dwProcessId = pe32.th32ProcessID;
  226. break;
  227. }
  228. }
  229. CloseHandle(hProcessSnap);
  230. return dwProcessId;
  231. }
  232. void GetAllProcessId(std::vector<DWORD>& vtPid, LPCTSTR lpProcessName)
  233. {
  234. vtPid.clear();
  235. PROCESSENTRY32 pe32 = { 0 };
  236. HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  237. if (hProcessSnap == NULL) return;
  238. // 遍历进程;
  239. pe32.dwSize = sizeof(PROCESSENTRY32);
  240. for (BOOL bRet = Process32First(hProcessSnap, &pe32); bRet; bRet = Process32Next(hProcessSnap, &pe32)) {
  241. if (_tcscmp(lpProcessName, pe32.szExeFile) == 0) {
  242. vtPid.push_back(pe32.th32ProcessID);
  243. }
  244. }
  245. CloseHandle(hProcessSnap);
  246. }
  247. HWND GetProcessMainWnd(const DWORD& dwTagetProcessId, LPCTSTR lpTagetWndName /* = _T("大话水浒") */)
  248. {
  249. DWORD dwCurPorcessId = 0;
  250. HWND hTagetProcessWnd = NULL;
  251. TCHAR szWndName[MAX_PATH] = { 0 };
  252. TCHAR szClassName[MAX_PATH] = { 0 };
  253. // 取得第一个窗口句柄;
  254. for (HWND hCurWnd = ::GetTopWindow(NULL); hCurWnd != NULL; hCurWnd = ::GetNextWindow(hCurWnd, GW_HWNDNEXT)) {
  255. // 重置为0;
  256. dwCurPorcessId = 0;
  257. // 通过窗口句柄反查进程pid;
  258. DWORD dwThreadId = ::GetWindowThreadProcessId(hCurWnd, &dwCurPorcessId);
  259. if (dwThreadId != 0) {
  260. // 判断当前进程id是否和目标进程id相同;
  261. if (dwCurPorcessId == dwTagetProcessId) {
  262. if (lpTagetWndName == NULL) {
  263. hTagetProcessWnd = hCurWnd;
  264. break;
  265. }
  266. else {
  267. // 获取窗口名称;
  268. ::GetWindowText(hCurWnd, szWndName, sizeof(szWndName) / sizeof(TCHAR));
  269. // 获取窗口类名;
  270. ::GetClassName(hCurWnd, szClassName, sizeof(szClassName) / sizeof(TCHAR));
  271. #ifdef _DEBUG
  272. TCHAR szLogMsg[MAX_PATH] = { 0 };
  273. _stprintf_s(szLogMsg, _T("类名:%s, 窗口名:%s,窗口地址:%p \n"), szClassName, szWndName, hCurWnd);
  274. OutputDebugString(szLogMsg);
  275. #endif
  276. if (_tcsstr(szWndName, lpTagetWndName) != NULL) {
  277. hTagetProcessWnd = hCurWnd;
  278. break;
  279. }
  280. }
  281. }
  282. }
  283. }
  284. // 当前窗口有可能不是进程父窗口;
  285. HWND hParentWnd = hTagetProcessWnd;
  286. while (hParentWnd) {
  287. hParentWnd = ::GetParent(hTagetProcessWnd);
  288. if (hParentWnd == NULL)
  289. break;
  290. hTagetProcessWnd = hParentWnd;
  291. }
  292. return hTagetProcessWnd;
  293. }
  294. void GetAllProcessMainWnd(const std::vector<DWORD>& vtPid, std::vector<GWnd>& vtGWnd)
  295. {
  296. // 删除已失效的进程;
  297. for (std::vector<GWnd>::iterator it = vtGWnd.begin(); it != vtGWnd.end();)
  298. {
  299. BOOL bExit = FALSE;
  300. for (std::vector<DWORD>::const_iterator it_pid = vtPid.begin(); it_pid != vtPid.end(); it_pid++ )
  301. {
  302. if (*it_pid == it->lProcId)
  303. bExit = TRUE;
  304. }
  305. if (!bExit)
  306. {
  307. it = vtGWnd.erase(it);
  308. }
  309. else
  310. {
  311. it++;
  312. }
  313. }
  314. for ( std::vector<DWORD>::const_iterator it = vtPid.begin(); it != vtPid.end(); it++ )
  315. {
  316. HWND hGWnd = GetProcessMainWnd(*it);
  317. }
  318. }
  319. HWND GetProcessMainWnd(LPCTSTR lpProcessName /* = _T("Game.exe") */, LPCTSTR lpTagetWndName /* = _T("大话水浒") */)
  320. {
  321. HWND hTagetWnd = NULL;
  322. DWORD dwProcessId = 0;
  323. if ((dwProcessId = GetProcessId(lpProcessName)) != 0) {
  324. hTagetWnd = GetProcessMainWnd(dwProcessId, lpTagetWndName);
  325. }
  326. return hTagetWnd;
  327. }
  328. std::vector<GameHwnd> g_vtGameHwnd;
  329. BOOL CALLBACK EnumChildWindowCallBack(HWND hWnd, LPARAM lParam)
  330. {
  331. DWORD dwPid = 0;
  332. GetWindowThreadProcessId(hWnd, &dwPid); // 获得找到窗口所属的进程
  333. if (dwPid == lParam) // 判断是否是目标进程的窗口
  334. {
  335. TCHAR szName[MAX_PATH] = { 0 };
  336. TCHAR szClass[MAX_PATH] = { 0 };
  337. TCHAR szLogMsg[MAX_PATH] = { 0 };
  338. ::GetWindowText(hWnd, szName, sizeof(szName) / sizeof(TCHAR));
  339. ::GetClassName(hWnd, szClass, sizeof(szClass) / sizeof(TCHAR)); // 窗口类
  340. DWORD dwId = ::GetDlgCtrlID(hWnd);
  341. //TRACE3(_T("%s %s %s"), szClass, szName, "\n");
  342. _stprintf_s(szLogMsg, _T("类名:%s, 窗口名:%s,ID:%d,窗口地址:%p \n"), szClass, szName, dwId, hWnd);
  343. OutputDebugString(szLogMsg);
  344. GameHwnd ghwnd;
  345. ghwnd.dwId = dwId;
  346. ghwnd.hwnd = hWnd;
  347. ghwnd.strWinText = szName;
  348. ghwnd.strClassName = szClass;
  349. g_vtGameHwnd.push_back(ghwnd);
  350. _tprintf_s(_T("0x%08X "), hWnd); // 输出窗口信息
  351. TCHAR buf[MAX_PATH];
  352. SendMessage(hWnd, WM_GETTEXT, MAX_PATH, (LPARAM)buf);
  353. _tprintf_s(_T("%s/n"), buf);
  354. EnumChildWindows(hWnd, EnumChildWindowCallBack, lParam); // 递归查找子窗口
  355. }
  356. return TRUE;
  357. }
  358. // nStartCount:启动进程数量;
  359. void StartGame(std::string strGameDir)
  360. {
  361. if (!PathFileExists(strGameDir.c_str()))
  362. return;
  363. SetCurrentDirectory(strGameDir.c_str());
  364. ShellExecute(NULL, "open", GAssist::g_szGameApp, NULL, NULL, SW_SHOWNORMAL);//SW_HIDE无用,因为会自动结;
  365. Sleep(1500); // Main.exe设置了陷阱(自己再开启了一个进程,结束上一个进程),需要等1.5秒;
  366. DWORD dwProcId = GAssist::FindProcess(_T("Main.exe"));
  367. if (dwProcId <= 0)
  368. return;
  369. EnumWindows(GAssist::EnumChildWindowCallBack, dwProcId);
  370. if (GAssist::g_vtGameHwnd.size()) {
  371. int nStatus = 0;
  372. GAssist::GameHwnd* gp = NULL;
  373. GAssist::GameHwnd* gbmin = NULL;
  374. GAssist::GameHwnd* gbentry = NULL;
  375. for (std::vector<GAssist::GameHwnd>::iterator it = GAssist::g_vtGameHwnd.begin(); it != GAssist::g_vtGameHwnd.end(); it++)
  376. {
  377. if (nStatus >= 3)
  378. break;
  379. if (_tcsicmp(it->strWinText.c_str(), _T("最小化")) == 0)
  380. {
  381. gbmin = &*it;
  382. nStatus++;
  383. }
  384. if (_tcsicmp(it->strWinText.c_str(), _T("大话水浒")) == 0)
  385. {
  386. gp = &*it;
  387. nStatus++;
  388. }
  389. if (_tcsicmp(it->strWinText.c_str(), _T("进入游戏")) == 0)
  390. {
  391. gbentry = &*it;
  392. nStatus++;
  393. }
  394. }
  395. if (gp && gbentry && gbmin) {
  396. // 发送点击事件;
  397. // 先最小化;
  398. ::SendMessage(gp->hwnd, WM_COMMAND, gbmin->dwId, NULL);
  399. // 再进入;
  400. ::SendMessage(gp->hwnd, WM_COMMAND, gbentry->dwId, NULL);
  401. }
  402. }
  403. }
  404. // 使用WM_LBUTTONDBLCLK完全无效;
  405. void MouseClick(HWND hwnd, POINT pt, BOOL bClientRect)
  406. {
  407. if (!IsWindow(hwnd))
  408. return;
  409. ::ShowWindow(hwnd, SW_SHOWNORMAL);
  410. ::SetForegroundWindow(hwnd); // 窗口前置才能单击成功;
  411. #if 0 // 使用Post或Send的方式,鼠标是不会显示出来的;
  412. ::PostMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
  413. ::PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
  414. #else// 建议使用这种方式,可以看到鼠标;
  415. POINT ptScreen = pt;
  416. if (bClientRect)
  417. ClientToScreen(hwnd, &ptScreen);
  418. ::SetCursorPos(ptScreen.x, ptScreen.y); // 必须将鼠标定位到目标单击点;
  419. mouse_event(MOUSEEVENTF_LEFTDOWN, ptScreen.x, ptScreen.y, 0, 0);
  420. Sleep(10);
  421. mouse_event(MOUSEEVENTF_LEFTUP, ptScreen.x, ptScreen.y, 0, 0);
  422. #endif
  423. }
  424. void MouseDbClick(HWND hwnd, POINT pt)
  425. {
  426. if (!IsWindow(hwnd))
  427. return;
  428. ::ShowWindow(hwnd, SW_SHOWNORMAL);
  429. ::SetForegroundWindow(hwnd); // 窗口前置才能单击成功;
  430. #if 1 // 使用Post或Send的方式,鼠标是不会显示出来的;
  431. Sleep(200); // Sleep后才生效;
  432. ::PostMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
  433. ::PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
  434. ::PostMessage(hwnd, WM_LBUTTONDBLCLK, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
  435. ::PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
  436. #else// 建议使用这种方式,可以看到鼠标;
  437. POINT ptScreen = pt;
  438. ClientToScreen(hwnd, &ptScreen);
  439. ::SetCursorPos(ptScreen.x, ptScreen.y); // 必须将鼠标定位到目标单击点;
  440. mouse_event(MOUSEEVENTF_LEFTDOWN, ptScreen.x, ptScreen.y, 0, 0);
  441. mouse_event(MOUSEEVENTF_LEFTUP, ptScreen.x, ptScreen.y, 0, 0);
  442. mouse_event(MOUSEEVENTF_LEFTDOWN, ptScreen.x, ptScreen.y, 0, 0);
  443. mouse_event(MOUSEEVENTF_LEFTUP, ptScreen.x, ptScreen.y, 0, 0);
  444. #endif
  445. }
  446. void MouseRClick(HWND hwnd, POINT pt, BOOL bClientRect)
  447. {
  448. if (!IsWindow(hwnd))
  449. return;
  450. ::ShowWindow(hwnd, SW_SHOWNORMAL);
  451. ::SetForegroundWindow(hwnd); // 窗口前置才能单击成功;
  452. #if 0 // 使用Post或Send的方式,鼠标是不会显示出来的;
  453. ::PostMessage(hwnd, WM_RBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
  454. ::PostMessage(hwnd, WM_RBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
  455. #else// 建议使用这种方式,可以看到鼠标;
  456. POINT ptScreen = pt;
  457. if (bClientRect)
  458. ClientToScreen(hwnd, &ptScreen);
  459. ::SetCursorPos(ptScreen.x, ptScreen.y); // 必须将鼠标定位到目标单击点;
  460. mouse_event(MOUSEEVENTF_RIGHTDOWN, ptScreen.x, ptScreen.y, 0, 0);
  461. Sleep(10);
  462. mouse_event(MOUSEEVENTF_RIGHTUP, ptScreen.x, ptScreen.y, 0, 0);
  463. #endif
  464. }
  465. void MouseRClick(HWND hwnd, unsigned int x, unsigned int y)
  466. {
  467. if (!IsWindow(hwnd))
  468. return;
  469. ::ShowWindow(hwnd, SW_SHOWNORMAL);
  470. ::SetForegroundWindow(hwnd); // 窗口前置才能单击成功;
  471. #if 0
  472. ::PostMessage(hwnd, WM_RBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
  473. ::PostMessage(hwnd, WM_RBUTTONUP, 0, MAKELPARAM(x, y));
  474. #else
  475. POINT ptScreen = { x,y };
  476. ClientToScreen(hwnd, &ptScreen);
  477. ::SetCursorPos(ptScreen.x, ptScreen.y);
  478. mouse_event(MOUSEEVENTF_RIGHTDOWN, ptScreen.x, ptScreen.y, 0, 0);
  479. mouse_event(MOUSEEVENTF_RIGHTUP, ptScreen.x, ptScreen.y, 0, 0);
  480. #endif
  481. Sleep(200);
  482. }
  483. void MouseRClick(HWND hwnd)
  484. {
  485. if (!IsWindow(hwnd))
  486. return;
  487. ::ShowWindow(hwnd, SW_SHOWNORMAL);
  488. ::SetForegroundWindow(hwnd); // 窗口前置才能单击成功;
  489. #if 0
  490. ::PostMessage(hwnd, WM_RBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
  491. ::PostMessage(hwnd, WM_RBUTTONUP, 0, MAKELPARAM(x, y));
  492. #else
  493. POINT ptScreen;// = { x,y };
  494. ::GetCursorPos(&ptScreen);
  495. mouse_event(MOUSEEVENTF_RIGHTDOWN, ptScreen.x, ptScreen.y, 0, 0);
  496. mouse_event(MOUSEEVENTF_RIGHTUP, ptScreen.x, ptScreen.y, 0, 0);
  497. #endif
  498. Sleep(200);
  499. }
  500. void MouseClick(HWND hwnd, unsigned int x, unsigned int y)
  501. {
  502. if (!IsWindow(hwnd))
  503. return;
  504. ::ShowWindow(hwnd, SW_SHOWNORMAL);
  505. ::SetForegroundWindow(hwnd); // 窗口前置才能单击成功;
  506. #if 0
  507. ::PostMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
  508. ::PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(x, y));
  509. #else
  510. POINT ptScreen = { x,y };
  511. ClientToScreen(hwnd, &ptScreen);
  512. ::SetCursorPos(ptScreen.x, ptScreen.y);
  513. mouse_event(MOUSEEVENTF_LEFTDOWN, ptScreen.x, ptScreen.y, 0, 0);
  514. mouse_event(MOUSEEVENTF_LEFTUP, ptScreen.x, ptScreen.y, 0, 0);
  515. #endif
  516. Sleep(200);
  517. }
  518. void MouseMove(HWND hwnd, POINT pt)
  519. {
  520. if (!IsWindow(hwnd))
  521. return;
  522. ::PostMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
  523. Sleep(200);
  524. }
  525. void MouseMove(HWND hwnd, POINT ptStart, POINT ptEnd)
  526. {
  527. if (!IsWindow(hwnd))
  528. return;
  529. //::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, lparam);
  530. ::PostMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(ptStart.x, ptStart.y));
  531. Sleep(200);
  532. #if 1
  533. // 计算个中间点;
  534. POINT ptMid = { (ptStart.x + ptEnd.x) / 2, (ptStart.y + ptEnd.y) / 2 };
  535. ::PostMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(ptMid.x, ptMid.y));
  536. Sleep(200);
  537. #endif
  538. //::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, lparam);
  539. ::PostMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(ptEnd.x, ptEnd.y));
  540. Sleep(200);
  541. }
  542. // 最后一步直接单击;
  543. void MouseMoveEx(HWND hwnd, POINT ptStart, POINT ptEnd)
  544. {
  545. if (!IsWindow(hwnd))
  546. return;
  547. //::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, lparam);
  548. ::PostMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(ptStart.x, ptStart.y));
  549. Sleep(200);
  550. #if 1
  551. // 计算个中间点;
  552. POINT ptMid = { (ptStart.x + ptEnd.x) / 2, (ptStart.y + ptEnd.y) / 2 };
  553. ::PostMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(ptMid.x, ptMid.y));
  554. Sleep(200);
  555. #endif
  556. //::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, lparam);
  557. ::PostMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(ptEnd.x, ptEnd.y));
  558. Sleep(200);
  559. MouseClick(hwnd, ptEnd);
  560. }
  561. void DragMouse(HWND hwnd, POINT ptStart, POINT ptEnd)
  562. {
  563. if (!IsWindow(hwnd))
  564. return;
  565. ::ShowWindow(hwnd, SW_SHOWNORMAL);
  566. ::SetForegroundWindow(hwnd);
  567. #if 0
  568. MouseClick(hwnd, ptStart);
  569. // 按下鼠标左键;
  570. ::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(ptStart.x, ptStart.y));
  571. //Sleep(200);
  572. ::SendMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(ptEnd.x, ptEnd.y));
  573. Sleep(200);
  574. #endif
  575. #if 1
  576. POINT ptScreen = ptStart;
  577. ClientToScreen(hwnd, &ptScreen);
  578. ::SetCursorPos(ptScreen.x, ptScreen.y);
  579. ::PostMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(ptStart.x, ptStart.y));
  580. Sleep(1200);
  581. ::PostMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(ptEnd.x, ptEnd.y));
  582. Sleep(200);
  583. ::PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(ptEnd.x, ptEnd.y));
  584. #endif
  585. #if 0
  586. // 能成功拖动游戏里的东西。
  587. POINT ptSStart = ptStart;
  588. POINT ptSEnd = ptEnd;
  589. ClientToScreen(hwnd, &ptSStart);
  590. ClientToScreen(hwnd, &ptSEnd);
  591. ::SetCursorPos(ptSStart.x, ptSStart.y);
  592. mouse_event(MOUSEEVENTF_LEFTDOWN, ptSStart.x, ptSStart.y, 0, 0);
  593. Sleep(1200);//必须暂停1秒左右,拖动才有效;
  594. // MOUSEEVENTF_ABSOLUTE 使用绝对鼠标位置;
  595. mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, ptSEnd.x, ptSEnd.y, 0, 0);
  596. Sleep(500);
  597. mouse_event(MOUSEEVENTF_LEFTUP, ptSEnd.x, ptSEnd.y, 0, 0);
  598. #endif
  599. }
  600. void SendKey(HWND hwnd, DWORD key, BOOL bCtrl /* = FALSE */, BOOL bAtl /* = FALSE */, BOOL bShift /* = FALSE */)
  601. {
  602. if (!IsWindow(hwnd))
  603. return;
  604. ::ShowWindow(hwnd, SW_SHOWNORMAL);
  605. ::SetForegroundWindow(hwnd);
  606. if (bCtrl)
  607. keybd_event(VK_CONTROL, 0x1D, KEYEVENTF_EXTENDEDKEY | 0, 0);
  608. if (bAtl)
  609. keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
  610. if (bShift)
  611. keybd_event(VK_SHIFT, 0x2A, KEYEVENTF_EXTENDEDKEY | 0, 0);
  612. Sleep(120); // 注意:有些电脑能响应Ctrl+V,有些不行,则需要加大CTRL与V之间的时间间隔;
  613. // key down;
  614. keybd_event(key, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
  615. // key up;
  616. keybd_event(key, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  617. Sleep(120);
  618. if (bCtrl)
  619. keybd_event(VK_CONTROL, 0x1D, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  620. if (bAtl)
  621. keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  622. if (bShift)
  623. keybd_event(VK_SHIFT, 0x2A, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  624. }
  625. BOOL SetClipboardString(const char* lpString)
  626. {
  627. if (lpString == NULL || lpString[0] == '\0')
  628. return FALSE;
  629. if (OpenClipboard(NULL))
  630. {
  631. HGLOBAL hClipString;
  632. EmptyClipboard();
  633. hClipString = GlobalAlloc(GMEM_DDESHARE, _tcslen(lpString) + 1);
  634. char* lpBuffer = (char*)GlobalLock(hClipString);
  635. _tcscpy_s(lpBuffer, _tcslen(lpString) + 1, lpString);
  636. GlobalUnlock(hClipString);
  637. SetClipboardData(CF_TEXT, hClipString);
  638. CloseClipboard();
  639. return TRUE;
  640. }
  641. return FALSE;
  642. }
  643. CString GetClipboradString(/*char *pString, const int len*/)
  644. {
  645. if (OpenClipboard(NULL))
  646. {
  647. HANDLE hData = GetClipboardData(CF_TEXT);
  648. if (hData)
  649. {
  650. char* lpBuffer = (char*)GlobalLock(hData);
  651. //memcpy(pString, lpBuffer, len);
  652. CString str(lpBuffer);
  653. GlobalUnlock(hData);
  654. CloseClipboard();
  655. return str;
  656. }
  657. }
  658. return CString();
  659. }
  660. // 截图;
  661. HBITMAP CopyDC2Bitmap(HWND hWnd, LPRECT lpRect)
  662. {
  663. if (!lpRect || IsRectEmpty(lpRect))
  664. return NULL;
  665. HDC hWndDC = ::GetWindowDC(hWnd);
  666. //HDC hWndDC = ::GetDC(hWnd);
  667. // 创建兼容DC;
  668. HDC hMemDC = CreateCompatibleDC(hWndDC);
  669. CRect rc(lpRect->top, lpRect->left, lpRect->right, lpRect->bottom);
  670. //::ClientToScreen(hWnd, &rc);
  671. HBITMAP hOldBitmap, hMenBitmap;
  672. int top = 0, left = 0, right = 0, bottom = 0;
  673. int nWidth = 0, nHeight = 0;
  674. top = lpRect->top;
  675. left = lpRect->left;
  676. right = lpRect->right;
  677. bottom = lpRect->bottom;
  678. nWidth = right - left;
  679. nHeight = bottom - top;
  680. // 创建兼容DC;
  681. hMenBitmap = CreateCompatibleBitmap(hWndDC, nWidth, nHeight);
  682. hOldBitmap = (HBITMAP)SelectObject(hMemDC, hMenBitmap);
  683. ::PrintWindow(hWnd, hMemDC, 0);
  684. // 将窗口DC内存复制到兼容DC上;
  685. StretchBlt(hMemDC, 0, 0, nWidth, nHeight, hWndDC, left, top, nWidth, nHeight, SRCCOPY);
  686. //BitBlt(hMemDC, 0, 0, nWidth, nHeight, hWndDC, left, top, SRCCOPY);
  687. hMenBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
  688. DeleteDC(hMemDC);
  689. DeleteObject(hOldBitmap);
  690. return hMenBitmap;
  691. }
  692. BOOL SaveBitmap(HBITMAP hBitmpa, std::string strSavePath)
  693. {
  694. //把位图的信息保存到bmpinfo;
  695. BITMAP bmpinfo;
  696. GetObject(hBitmpa, sizeof(BITMAP), &bmpinfo);
  697. DWORD dwBmBitsSize = ((bmpinfo.bmWidth * 32 + 31) / 32) * 4 * bmpinfo.bmHeight;
  698. //位图文件头 14字节
  699. BITMAPFILEHEADER bf;
  700. bf.bfType = 0x4D42;
  701. //BM
  702. bf.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize;
  703. bf.bfReserved1 = 0;
  704. bf.bfReserved2 = 0;
  705. bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
  706. //位图信息头
  707. BITMAPINFOHEADER bi;
  708. bi.biSize = sizeof(BITMAPINFOHEADER);
  709. bi.biWidth = bmpinfo.bmWidth;
  710. bi.biHeight = bmpinfo.bmHeight;
  711. bi.biPlanes = 1;
  712. bi.biBitCount = 32;
  713. bi.biCompression = BI_RGB;
  714. bi.biSizeImage = 0;
  715. bi.biXPelsPerMeter = 0;
  716. bi.biYPelsPerMeter = 0;
  717. bi.biClrUsed = 8;
  718. bi.biClrImportant = 0;
  719. //位图数据;
  720. char* context = new char[dwBmBitsSize];
  721. HDC dc = ::GetDC(NULL);
  722. GetDIBits(dc, hBitmpa, 0, bi.biHeight, context, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
  723. FILE* f = fopen(strSavePath.c_str(), "wb");
  724. fwrite((char*)&bf, sizeof(BITMAPFILEHEADER), 1, f);
  725. fwrite((char*)&bi, sizeof(BITMAPINFOHEADER), 1, f);
  726. fwrite(context, dwBmBitsSize, 1, f);
  727. fclose(f);
  728. delete context;
  729. ::ReleaseDC(NULL, dc);
  730. return 0;
  731. }
  732. BOOL IsWin10DpiScaleEanbled()
  733. {
  734. SetProcessDPIAware();
  735. HDC hDC = GetDC(NULL);
  736. int dpi_x = GetDeviceCaps(hDC, LOGPIXELSX);//96 是100%、120 是125%、144 是150%、168 是175%
  737. int dpi_y = GetDeviceCaps(hDC, LOGPIXELSY);
  738. int dpi1 = GetDeviceCaps(hDC, HORZRES);
  739. int dpi2 = GetDeviceCaps(hDC, DESKTOPHORZRES);
  740. BOOL bRet = FALSE;
  741. BOOL bProcessed = FALSE;
  742. if (GetDeviceCaps(hDC, LOGPIXELSX) != 96)
  743. {
  744. DEVMODE curDevMode;
  745. memset(&curDevMode, 0, sizeof(curDevMode));
  746. curDevMode.dmSize = sizeof(DEVMODE);
  747. BOOL bEnumRet = ::EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &curDevMode);
  748. if (bEnumRet < curDevMode.dmPelsWidth)
  749. {
  750. bProcessed = TRUE;
  751. //::SetStretchBltMode(hMemDC, STRETCH_HALFTONE);
  752. //bRet = ::StretchBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, 0, 0, curDevMode.dmPelsWidth, curDevMode.dmPelsHeight, SRCCOPY | CAPTUREBLT);
  753. }
  754. }
  755. ReleaseDC(NULL, hDC);
  756. return TRUE;
  757. }
  758. void SaveHwndToBmpFile(HWND hWnd, std::string strSavePath) {
  759. HDC hDC = ::GetWindowDC(hWnd);
  760. ASSERT(hDC);
  761. HDC hMemDC = ::CreateCompatibleDC(hDC);
  762. ASSERT(hMemDC);
  763. RECT rc;
  764. ::GetWindowRect(hWnd, &rc);
  765. HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, rc.right - rc.left, rc.bottom - rc.top);
  766. ASSERT(hBitmap);
  767. HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemDC, hBitmap);
  768. BOOL bRet = FALSE;
  769. BOOL bProcessed = FALSE;
  770. // 针对win10 DWM虚拟缩放时的处理
  771. if (GetDeviceCaps(hDC, LOGPIXELSX) != 96)
  772. {
  773. DEVMODE curDevMode;
  774. memset(&curDevMode, 0, sizeof(curDevMode));
  775. curDevMode.dmSize = sizeof(DEVMODE);
  776. BOOL bEnumRet = ::EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &curDevMode);
  777. if (bEnumRet < curDevMode.dmPelsWidth)
  778. {
  779. bProcessed = TRUE;
  780. //::SetStretchBltMode(hMemDC, STRETCH_HALFTONE);
  781. //bRet = ::StretchBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, 0, 0, curDevMode.dmPelsWidth, curDevMode.dmPelsHeight, SRCCOPY | CAPTUREBLT);
  782. }
  783. }
  784. ::PrintWindow(hWnd, hMemDC, 0);
  785. BITMAP bitmap = { 0 };
  786. ::GetObject(hBitmap, sizeof(BITMAP), &bitmap);
  787. BITMAPINFOHEADER bi = { 0 };
  788. BITMAPFILEHEADER bf = { 0 };
  789. CONST int nBitCount = 24;
  790. bi.biSize = sizeof(BITMAPINFOHEADER);
  791. bi.biWidth = bitmap.bmWidth;
  792. bi.biHeight = bitmap.bmHeight;
  793. bi.biPlanes = 1;
  794. bi.biBitCount = nBitCount;
  795. bi.biCompression = BI_RGB;
  796. DWORD dwSize = ((bitmap.bmWidth * nBitCount + 31) / 32) * 4 * bitmap.bmHeight;
  797. HANDLE hDib = GlobalAlloc(GHND, dwSize + sizeof(BITMAPINFOHEADER));
  798. LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
  799. *lpbi = bi;
  800. ::GetDIBits(hMemDC, hBitmap, 0, bitmap.bmHeight, (BYTE*)lpbi + sizeof(BITMAPINFOHEADER), (BITMAPINFO*)lpbi, DIB_RGB_COLORS);
  801. CFile file;
  802. CFileException fep;
  803. if (file.Open(strSavePath.c_str(), CFile::modeCreate | CFile::modeWrite, &fep)) {
  804. bf.bfType = 0x4d42;
  805. dwSize += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
  806. bf.bfSize = dwSize;
  807. bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
  808. file.Write((BYTE*)&bf, sizeof(BITMAPFILEHEADER));
  809. file.Write((BYTE*)lpbi, dwSize);
  810. file.Close();
  811. }
  812. GlobalUnlock(hDib);
  813. GlobalFree(hDib);
  814. ::SelectObject(hMemDC, hOldBmp);
  815. ::DeleteObject(hBitmap);
  816. ::DeleteObject(hMemDC);
  817. ::ReleaseDC(hWnd, hDC);
  818. Sleep(30);
  819. }
  820. // #include <D3D9.h>
  821. // #include <D3dx9tex.h>
  822. // #pragma comment(lib, "D3dx9.lib")
  823. //#include <d3d9helper>
  824. BOOL ScreenShot(LPDIRECT3DDEVICE9 lpDevice, HWND hWnd, TCHAR* fileName)
  825. {
  826. HRESULT hr;
  827. // Get adapter display mode
  828. D3DDISPLAYMODE mode;
  829. if (FAILED(hr = lpDevice->GetDisplayMode(0, &mode)))
  830. return hr;
  831. // Create the surface to hold the screen image data
  832. LPDIRECT3DSURFACE9 surf;
  833. if (FAILED(hr = lpDevice->CreateOffscreenPlainSurface(mode.Width,
  834. mode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL))) //注意第四个参数不能是D3DPOOL_DEFAULT
  835. {
  836. return hr;
  837. }
  838. // Get the screen data
  839. if (FAILED(hr = lpDevice->GetFrontBufferData(0, surf)))
  840. {
  841. surf->Release();
  842. return hr;
  843. }
  844. // area to capture
  845. RECT* rect = NULL;
  846. WINDOWINFO windowInfo;
  847. windowInfo.cbSize = sizeof(WINDOWINFO);
  848. if (hWnd) // capture window
  849. {
  850. GetWindowInfo(hWnd, &windowInfo);
  851. rect = &windowInfo.rcWindow;
  852. }
  853. // Save the screen date to file
  854. //hr = D3DXSaveSurfaceToFile(fileName, D3DXIFF_BMP, surf, NULL, rect);
  855. surf->Release();
  856. return hr;
  857. }
  858. // 判断窗口是否被遮住;
  859. bool IsCoveredByOtherWindow(HWND hWnd)
  860. {
  861. RECT rcTarget;
  862. GetWindowRect(hWnd, &rcTarget);
  863. bool isChild = (WS_CHILD == (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD));
  864. if (GetDesktopWindow() == hWnd)
  865. hWnd = GetWindow(GetTopWindow(hWnd), GW_HWNDLAST);
  866. do
  867. {
  868. HWND hCurWnd = hWnd;
  869. while (NULL != (hWnd = GetNextWindow(hWnd, GW_HWNDPREV)))
  870. {
  871. //过滤了非窗口,没有显示的,无效的,非windows工具栏,置顶的窗口。如果不过滤非工具栏的句柄,那么会得到一些奇怪的窗口,会很难判断是否被遮住。
  872. //if ( IsWindow(hWnd) && IsWindowVisible(hWnd) && IsWindowEnabled(hWnd) && !(GetWindowLong(hWnd,GWL_EXSTYLE)& WS_EX_TOOLWINDOW) && !(GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_TOPMOST))
  873. if (::IsWindowVisible(hWnd))
  874. {
  875. RECT rcWnd;
  876. GetWindowRect(hWnd, &rcWnd);
  877. if (!((rcWnd.right < rcTarget.left) || (rcWnd.left > rcTarget.right) ||
  878. (rcWnd.bottom < rcTarget.top) || (rcWnd.top > rcTarget.bottom)))
  879. {
  880. return true;
  881. }
  882. }
  883. }
  884. if (isChild)
  885. {
  886. hWnd = GetParent(hCurWnd);
  887. isChild = (WS_CHILD == (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD));
  888. }
  889. else
  890. {
  891. break;
  892. }
  893. } while (true);
  894. return false;
  895. }
  896. BOOL OpenImage(std::string strImag, cv::Mat& img)
  897. {
  898. if (!PathFileExists(strImag.c_str()))
  899. return FALSE;
  900. if (img.data != NULL)
  901. img.release();
  902. img = cv::imread(strImag.c_str(), cv::IMREAD_COLOR);
  903. if (img.data == NULL)
  904. return FALSE;
  905. return TRUE;
  906. }
  907. BOOL SetImgThreshold(cv::Mat& srcImg, cv::Mat& thresholdImg, long nThresholdVal, long nMaxThresholdVal, int type)
  908. {
  909. if (srcImg.data == NULL)
  910. return FALSE;
  911. if (thresholdImg.data && srcImg.data != thresholdImg.data)
  912. thresholdImg.release();
  913. switch (type)
  914. {
  915. case 0://全局阀值;
  916. {
  917. // 转成灰阶图;
  918. cv::cvtColor(srcImg, thresholdImg, cv::COLOR_BGR2GRAY);
  919. // 再高斯模糊处理(滤波);
  920. cv::GaussianBlur(thresholdImg, thresholdImg, cv::Size(5, 5), 0, 0);
  921. // 二值化;//全局化指定的阀值与返回值相等;
  922. double dRetVal = cv::threshold(thresholdImg, thresholdImg, nThresholdVal, nMaxThresholdVal, cv::THRESH_BINARY);
  923. }
  924. break;
  925. case 1://自适应阀值;
  926. {
  927. // 转成灰阶图;
  928. cv::cvtColor(srcImg, thresholdImg, cv::COLOR_BGR2GRAY);
  929. // 再高斯模糊处理(滤波);
  930. cv::GaussianBlur(thresholdImg, thresholdImg, cv::Size(3, 3), 0, 0);
  931. // 自适应阀值;
  932. cv::medianBlur(thresholdImg, thresholdImg, 3);
  933. // 局部二值化;//blocksize一般取3、5、7
  934. cv::adaptiveThreshold(thresholdImg, thresholdImg, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 3, 4.5);
  935. }
  936. break;
  937. case 2:// otsu阀值;
  938. {
  939. cv::cvtColor(srcImg, thresholdImg, cv::COLOR_BGR2GRAY);
  940. // 高斯模糊;
  941. cv::GaussianBlur(thresholdImg, thresholdImg, cv::Size(3, 3), 0, 0);
  942. cv::threshold(thresholdImg, thresholdImg, nThresholdVal, nMaxThresholdVal, cv::THRESH_BINARY | cv::THRESH_OTSU);
  943. }
  944. break;
  945. default:
  946. break;
  947. }
  948. return TRUE;
  949. }
  950. BOOL GetImgMatchtemplate(HWND hWnd, std::string strTempImg, RECT& rc, double lowestMatchValue)
  951. {
  952. GAssist::SaveHwndToBmpFile(hWnd, g_strAppdir + _T("Game.bmp"));
  953. cv::Mat srcImg, tempImg, matchImg;
  954. if (!OpenImage(g_strAppdir + _T("Game.bmp"), srcImg) || !OpenImage(strTempImg, tempImg))
  955. {
  956. if (srcImg.data) srcImg.release();
  957. if (tempImg.data) tempImg.release();
  958. return FALSE;
  959. }
  960. cv::matchTemplate(srcImg, tempImg, matchImg, cv::TM_CCOEFF_NORMED);
  961. // 归一化到0~1
  962. //cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
  963. double lv_nMinVal = 0.0;
  964. double lv_nMaxVal = 0.0;
  965. cv::Point lv_nMinLoc = cv::Point(0, 0);
  966. cv::Point lv_nMaxLoc = cv::Point(0, 0);
  967. cv::Point lv_MatchLoc = cv::Point(0, 0);
  968. cv::minMaxLoc(matchImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
  969. cv::Rect roi = cv::Rect(lv_nMaxLoc.x, lv_nMaxLoc.y, tempImg.cols, tempImg.rows);
  970. cv::Mat roiImg = srcImg(roi);
  971. cv::imwrite(g_strAppdir + _T("match.bmp"), roiImg);
  972. rc.left = lv_nMaxLoc.x - frameWidth;
  973. rc.top = lv_nMaxLoc.y - titleBarHeight;
  974. rc.right = rc.left + tempImg.cols;
  975. rc.bottom = rc.top + tempImg.rows;
  976. srcImg.release();
  977. tempImg.release();
  978. matchImg.release();
  979. roiImg.release();
  980. // 是否大于最低匹配度;
  981. return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
  982. }
  983. BOOL GetImgMatchtemplate(std::string strSrcImg, std::string strTempImg, RECT& rc, double lowestMatchValue)
  984. {
  985. cv::Mat srcImg, tempImg, matchImg;
  986. if (!OpenImage(strSrcImg, srcImg) || !OpenImage(strTempImg, tempImg))
  987. {
  988. if (srcImg.data) srcImg.release();
  989. if (tempImg.data) tempImg.release();
  990. return FALSE;
  991. }
  992. cv::matchTemplate(srcImg, tempImg, matchImg, cv::TM_CCOEFF_NORMED);
  993. // 归一化到0~1
  994. //cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
  995. double lv_nMinVal = 0.0;
  996. double lv_nMaxVal = 0.0;
  997. cv::Point lv_nMinLoc = cv::Point(0, 0);
  998. cv::Point lv_nMaxLoc = cv::Point(0, 0);
  999. cv::Point lv_MatchLoc = cv::Point(0, 0);
  1000. cv::minMaxLoc(matchImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
  1001. cv::Rect roi = cv::Rect(lv_nMaxLoc.x, lv_nMaxLoc.y, tempImg.cols, tempImg.rows);
  1002. cv::Mat roiImg = srcImg(roi);
  1003. cv::imwrite("G:\\bin\\GameAssist\\match.bmp", roiImg);
  1004. rc.left = lv_nMaxLoc.x - frameWidth;
  1005. rc.top = lv_nMaxLoc.y - titleBarHeight;
  1006. rc.right = rc.left + tempImg.cols;
  1007. rc.bottom = rc.top + tempImg.rows;
  1008. srcImg.release();
  1009. tempImg.release();
  1010. matchImg.release();
  1011. roiImg.release();
  1012. // 是否大于最低匹配度;
  1013. return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
  1014. }
  1015. BOOL IsMatchIcon(HWND hWnd, std::string strTempImg, RECT srcRect, RECT& matchRect, double lowestMatchValue)
  1016. {
  1017. GAssist::SaveHwndToBmpFile(hWnd, g_strAppdir + _T("Game.bmp"));
  1018. cv::Mat srcImg, tempImg, matchImg;
  1019. if (!OpenImage(g_strAppdir + _T("Game.bmp"), srcImg) || !OpenImage(strTempImg, tempImg))
  1020. {
  1021. if (srcImg.data) srcImg.release();
  1022. if (tempImg.data) tempImg.release();
  1023. return FALSE;
  1024. }
  1025. // 指定源图片区域来做模块比较,提高效率;
  1026. cv::Mat imgROI;
  1027. imgROI = srcImg(cv::Rect(srcRect.left, srcRect.top, srcRect.right - srcRect.left, srcRect.bottom - srcRect.top));
  1028. cv::imwrite("roi.bmp", imgROI);
  1029. /*
  1030. m_ImgROI = srcImg([&]()-> cv::Rect {
  1031. // 注意是x,y,w=cols,h=rows
  1032. return cv::Rect(srcRect.left, srcRect.top, srcRect.right - srcRect.left, srcRect.bottom - srcRect.top);
  1033. }());
  1034. */
  1035. cv::matchTemplate(imgROI, tempImg, matchImg, cv::TM_CCOEFF_NORMED);
  1036. // 归一化到0~1
  1037. //cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
  1038. double lv_nMinVal = 0.0;
  1039. double lv_nMaxVal = 0.0;
  1040. cv::Point lv_nMinLoc = cv::Point(0, 0);
  1041. cv::Point lv_nMaxLoc = cv::Point(0, 0);
  1042. cv::Point lv_MatchLoc = cv::Point(0, 0);
  1043. cv::minMaxLoc(matchImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
  1044. cv::Rect roi = cv::Rect(lv_nMaxLoc.x, lv_nMaxLoc.y, tempImg.cols, tempImg.rows);
  1045. cv::Mat roiImg = imgROI(roi);
  1046. cv::imwrite("match.bmp", roiImg);
  1047. matchRect.left = srcRect.left + lv_nMaxLoc.x - frameWidth;
  1048. matchRect.top = srcRect.top + lv_nMaxLoc.y - titleBarHeight;
  1049. matchRect.right = matchRect.left + tempImg.cols;
  1050. matchRect.bottom = matchRect.top + tempImg.rows;
  1051. imgROI.release();
  1052. srcImg.release();
  1053. tempImg.release();
  1054. matchImg.release();
  1055. roiImg.release();
  1056. // 是否大于最低匹配度;
  1057. return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
  1058. }
  1059. BOOL CropPicture(HWND hWnd, CRect rc, const char *szSaveName)
  1060. {
  1061. GAssist::SaveHwndToBmpFile(hWnd, g_strAppdir + _T("Game.bmp"));
  1062. cv::Mat srcImg, tempImg, matchImg;
  1063. if (!OpenImage(g_strAppdir + _T("Game.bmp"), srcImg) )
  1064. {
  1065. if (srcImg.data) srcImg.release();
  1066. return FALSE;
  1067. }
  1068. // 指定源图片区域来做模块比较,提高效率;
  1069. cv::Mat imgROI;
  1070. imgROI = srcImg(cv::Rect(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top));
  1071. cv::imwrite(szSaveName, imgROI);
  1072. }
  1073. BOOL IsSimilarPicture(const char* szp1, const char* szp2, double lowestMatchValue)
  1074. {
  1075. cv::Mat src, dest, matchImg;
  1076. src = cv::imread(szp1);
  1077. dest = cv::imread(szp2);
  1078. cv::matchTemplate(src, dest, matchImg, cv::TM_CCOEFF_NORMED);
  1079. // 归一化到0~1
  1080. //cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
  1081. double lv_nMinVal = 0.0;
  1082. double lv_nMaxVal = 0.0;
  1083. cv::Point lv_nMinLoc = cv::Point(0, 0);
  1084. cv::Point lv_nMaxLoc = cv::Point(0, 0);
  1085. cv::Point lv_MatchLoc = cv::Point(0, 0);
  1086. cv::minMaxLoc(matchImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
  1087. src.release();
  1088. matchImg.release();
  1089. dest.release();
  1090. // 是否大于最低匹配度;
  1091. return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
  1092. }
  1093. void ZhiYeDaTiaoZhan()
  1094. {
  1095. // 判断当前地图是否在应天府;
  1096. //// 是:打开世界地图,寻路到NPC;
  1097. //// 否:退出
  1098. // 对话NPC,进入地图;
  1099. }
  1100. }