|
@@ -8,6 +8,9 @@
|
|
// #pragma comment(lib, "d3d11.lib")
|
|
// #pragma comment(lib, "d3d11.lib")
|
|
// #pragma comment(lib, "dxgi.lib")
|
|
// #pragma comment(lib, "dxgi.lib")
|
|
|
|
|
|
|
|
+int frameWidth = 2;
|
|
|
|
+int titleBarHeight = 27;
|
|
|
|
+
|
|
namespace GAssist
|
|
namespace GAssist
|
|
{
|
|
{
|
|
int frameWidth = 2;
|
|
int frameWidth = 2;
|
|
@@ -271,7 +274,7 @@ namespace GAssist
|
|
TCHAR szGameRoleName[MAX_PATH] = { 0 };
|
|
TCHAR szGameRoleName[MAX_PATH] = { 0 };
|
|
// 清空队列;
|
|
// 清空队列;
|
|
vtGWnd.clear();
|
|
vtGWnd.clear();
|
|
- for ( std::vector<DWORD>::const_iterator it = vtPid.begin(); it != vtPid.end(); it++ )
|
|
|
|
|
|
+ for (std::vector<DWORD>::const_iterator it = vtPid.begin(); it != vtPid.end(); it++)
|
|
{
|
|
{
|
|
// 取得第一个窗口句柄;
|
|
// 取得第一个窗口句柄;
|
|
for (HWND hCurWnd = ::GetTopWindow(NULL); hCurWnd != NULL; hCurWnd = ::GetNextWindow(hCurWnd, GW_HWNDNEXT)) {
|
|
for (HWND hCurWnd = ::GetTopWindow(NULL); hCurWnd != NULL; hCurWnd = ::GetNextWindow(hCurWnd, GW_HWNDNEXT)) {
|
|
@@ -530,7 +533,7 @@ namespace GAssist
|
|
#else
|
|
#else
|
|
POINT ptScreen;// = { x,y };
|
|
POINT ptScreen;// = { x,y };
|
|
::GetCursorPos(&ptScreen);
|
|
::GetCursorPos(&ptScreen);
|
|
-
|
|
|
|
|
|
+
|
|
mouse_event(MOUSEEVENTF_RIGHTDOWN, ptScreen.x, ptScreen.y, 0, 0);
|
|
mouse_event(MOUSEEVENTF_RIGHTDOWN, ptScreen.x, ptScreen.y, 0, 0);
|
|
mouse_event(MOUSEEVENTF_RIGHTUP, ptScreen.x, ptScreen.y, 0, 0);
|
|
mouse_event(MOUSEEVENTF_RIGHTUP, ptScreen.x, ptScreen.y, 0, 0);
|
|
#endif
|
|
#endif
|
|
@@ -1193,11 +1196,11 @@ namespace GAssist
|
|
return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
|
|
return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
- BOOL CropPicture(HWND hWnd, CRect rc, const char *szSaveName)
|
|
|
|
|
|
+ BOOL CropPicture(HWND hWnd, CRect rc, const char* szSaveName)
|
|
{
|
|
{
|
|
GAssist::SaveHwndToBmpFile(hWnd, g_strAppdir + _T("Game.bmp"));
|
|
GAssist::SaveHwndToBmpFile(hWnd, g_strAppdir + _T("Game.bmp"));
|
|
cv::Mat srcImg, tempImg, matchImg;
|
|
cv::Mat srcImg, tempImg, matchImg;
|
|
- if (!OpenImage(g_strAppdir + _T("Game.bmp"), srcImg) )
|
|
|
|
|
|
+ if (!OpenImage(g_strAppdir + _T("Game.bmp"), srcImg))
|
|
{
|
|
{
|
|
if (srcImg.data) srcImg.release();
|
|
if (srcImg.data) srcImg.release();
|
|
return FALSE;
|
|
return FALSE;
|
|
@@ -1214,7 +1217,7 @@ namespace GAssist
|
|
cv::Mat src, dest, matchImg;
|
|
cv::Mat src, dest, matchImg;
|
|
src = cv::imread(szp1);
|
|
src = cv::imread(szp1);
|
|
dest = cv::imread(szp2);
|
|
dest = cv::imread(szp2);
|
|
-
|
|
|
|
|
|
+
|
|
cv::matchTemplate(src, dest, matchImg, cv::TM_CCOEFF_NORMED);
|
|
cv::matchTemplate(src, dest, matchImg, cv::TM_CCOEFF_NORMED);
|
|
// 归一化到0~1
|
|
// 归一化到0~1
|
|
//cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
|
|
//cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
|
|
@@ -1246,7 +1249,8 @@ namespace GAssist
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-namespace GameAssist {
|
|
|
|
|
|
+namespace GameAssist
|
|
|
|
+{
|
|
void SetGameForeground(HWND hWnd)
|
|
void SetGameForeground(HWND hWnd)
|
|
{
|
|
{
|
|
if (!IsWindow(hWnd))
|
|
if (!IsWindow(hWnd))
|
|
@@ -1256,6 +1260,11 @@ namespace GameAssist {
|
|
::SetForegroundWindow(hWnd); // 窗口前置才能单击成功;
|
|
::SetForegroundWindow(hWnd); // 窗口前置才能单击成功;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ bool IsGameForeground(HWND hWnd)
|
|
|
|
+ {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
BOOL GamePos2Screen(HWND hWnd, POINT& pt, bool bOffset)
|
|
BOOL GamePos2Screen(HWND hWnd, POINT& pt, bool bOffset)
|
|
{
|
|
{
|
|
if (!::IsWindow(hWnd)) return FALSE;
|
|
if (!::IsWindow(hWnd)) return FALSE;
|
|
@@ -1508,4 +1517,610 @@ namespace GameAssist {
|
|
if (bShift)
|
|
if (bShift)
|
|
keybd_event(VK_SHIFT, 0x2A, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
|
|
keybd_event(VK_SHIFT, 0x2A, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ CString GetClipboradString()
|
|
|
|
+ {
|
|
|
|
+ if (OpenClipboard(NULL))
|
|
|
|
+ {
|
|
|
|
+ HANDLE hData = GetClipboardData(CF_TEXT);
|
|
|
|
+ if (hData)
|
|
|
|
+ {
|
|
|
|
+ char* lpBuffer = (char*)GlobalLock(hData);
|
|
|
|
+ //memcpy(pString, lpBuffer, len);
|
|
|
|
+ CString str(lpBuffer);
|
|
|
|
+ GlobalUnlock(hData);
|
|
|
|
+ CloseClipboard();
|
|
|
|
+
|
|
|
|
+ return str;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return CString();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ BOOL SetClipboardString(LPCTSTR lpString)
|
|
|
|
+ {
|
|
|
|
+ if (lpString == NULL || lpString[0] == '\0')
|
|
|
|
+ return FALSE;
|
|
|
|
+
|
|
|
|
+ BOOL bRet = FALSE;
|
|
|
|
+ if (!OpenClipboard(NULL))
|
|
|
|
+ return FALSE;
|
|
|
|
+
|
|
|
|
+ HGLOBAL hClipString;
|
|
|
|
+ EmptyClipboard();
|
|
|
|
+ hClipString = GlobalAlloc(GMEM_DDESHARE, _tcslen(lpString) + 1);
|
|
|
|
+ if (!hClipString)
|
|
|
|
+ goto end;
|
|
|
|
+
|
|
|
|
+ /*char* lpBuffer = (char*)GlobalLock(hClipString);
|
|
|
|
+ if (!lpBuffer)
|
|
|
|
+ goto end;*/
|
|
|
|
+
|
|
|
|
+ //bRet = TRUE;
|
|
|
|
+ //_tcscpy_s(lpBuffer, _tcslen(lpString) + 1, lpString);
|
|
|
|
+
|
|
|
|
+ end:
|
|
|
|
+ if (hClipString)
|
|
|
|
+ {
|
|
|
|
+ GlobalUnlock(hClipString);
|
|
|
|
+ SetClipboardData(CF_TEXT, hClipString);
|
|
|
|
+ CloseClipboard();
|
|
|
|
+ }
|
|
|
|
+ return bRet;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 返回第一个找到的进程pid
|
|
|
|
+ DWORD GetProcessId(LPCTSTR lpProcessName)
|
|
|
|
+ {
|
|
|
|
+ DWORD dwProcessId = 0;
|
|
|
|
+ PROCESSENTRY32 pe32 = { 0 };
|
|
|
|
+
|
|
|
|
+ HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
|
|
+ if (hProcessSnap == NULL) return 0;
|
|
|
|
+
|
|
|
|
+ // 遍历进程;
|
|
|
|
+ pe32.dwSize = sizeof(PROCESSENTRY32);
|
|
|
|
+ for (BOOL bRet = Process32First(hProcessSnap, &pe32); bRet; bRet = Process32Next(hProcessSnap, &pe32)) {
|
|
|
|
+ if (_tcscmp(lpProcessName, pe32.szExeFile) == 0) {
|
|
|
|
+ dwProcessId = pe32.th32ProcessID;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ CloseHandle(hProcessSnap);
|
|
|
|
+
|
|
|
|
+ return dwProcessId;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void GetAllProcessId(std::vector<DWORD>& vtPid, LPCTSTR lpProcessName)
|
|
|
|
+ {
|
|
|
|
+ vtPid.clear();
|
|
|
|
+ PROCESSENTRY32 pe32 = { 0 };
|
|
|
|
+
|
|
|
|
+ HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
|
|
+ if (hProcessSnap == NULL) return;
|
|
|
|
+
|
|
|
|
+ // 遍历进程;
|
|
|
|
+ pe32.dwSize = sizeof(PROCESSENTRY32);
|
|
|
|
+ for (BOOL bRet = Process32First(hProcessSnap, &pe32); bRet; bRet = Process32Next(hProcessSnap, &pe32)) {
|
|
|
|
+ if (_tcscmp(lpProcessName, pe32.szExeFile) == 0) {
|
|
|
|
+ vtPid.push_back(pe32.th32ProcessID);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ CloseHandle(hProcessSnap);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ HWND GetProcessMainWnd(const DWORD& dwTagetProcessId, LPCTSTR lpTagetWndName)
|
|
|
|
+ {
|
|
|
|
+ DWORD dwCurPorcessId = 0;
|
|
|
|
+ HWND hTagetProcessWnd = NULL;
|
|
|
|
+ TCHAR szWndName[MAX_PATH] = { 0 };
|
|
|
|
+ TCHAR szClassName[MAX_PATH] = { 0 };
|
|
|
|
+
|
|
|
|
+ // 取得第一个窗口句柄;
|
|
|
|
+ for (HWND hCurWnd = ::GetTopWindow(NULL); hCurWnd != NULL; hCurWnd = ::GetNextWindow(hCurWnd, GW_HWNDNEXT)) {
|
|
|
|
+ // 重置为0;
|
|
|
|
+ dwCurPorcessId = 0;
|
|
|
|
+ // 通过窗口句柄反查进程pid;
|
|
|
|
+ DWORD dwThreadId = ::GetWindowThreadProcessId(hCurWnd, &dwCurPorcessId);
|
|
|
|
+ if (dwThreadId != 0) {
|
|
|
|
+ // 判断当前进程id是否和目标进程id相同;
|
|
|
|
+ if (dwCurPorcessId == dwTagetProcessId) {
|
|
|
|
+ if (lpTagetWndName == NULL) {
|
|
|
|
+ hTagetProcessWnd = hCurWnd;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ // 获取窗口名称;
|
|
|
|
+ ::GetWindowText(hCurWnd, szWndName, sizeof(szWndName) / sizeof(TCHAR));
|
|
|
|
+ // 获取窗口类名;
|
|
|
|
+ ::GetClassName(hCurWnd, szClassName, sizeof(szClassName) / sizeof(TCHAR));
|
|
|
|
+#ifdef _DEBUG
|
|
|
|
+ TCHAR szLogMsg[MAX_PATH] = { 0 };
|
|
|
|
+ _stprintf_s(szLogMsg, _T("类名:%s, 窗口名:%s,窗口地址:%p \n"), szClassName, szWndName, hCurWnd);
|
|
|
|
+ OutputDebugString(szLogMsg);
|
|
|
|
+#endif
|
|
|
|
+ if (_tcsstr(szWndName, lpTagetWndName) != NULL) {
|
|
|
|
+ hTagetProcessWnd = hCurWnd;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 当前窗口有可能不是进程父窗口;
|
|
|
|
+ HWND hParentWnd = hTagetProcessWnd;
|
|
|
|
+ while (hParentWnd) {
|
|
|
|
+ hParentWnd = ::GetParent(hTagetProcessWnd);
|
|
|
|
+ if (hParentWnd == NULL)
|
|
|
|
+ break;
|
|
|
|
+ hTagetProcessWnd = hParentWnd;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return hTagetProcessWnd;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ HWND GetProcessMainWnd(LPCTSTR lpProcessName, LPCTSTR lpTagetWndName)
|
|
|
|
+ {
|
|
|
|
+ HWND hTagetWnd = NULL;
|
|
|
|
+ DWORD dwProcessId = 0;
|
|
|
|
+ if ((dwProcessId = GetProcessId(lpProcessName)) != 0) {
|
|
|
|
+ hTagetWnd = GetProcessMainWnd(dwProcessId, lpTagetWndName);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return hTagetWnd;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void GetAllProcessMainWnd(const std::vector<DWORD>& vtPid, std::vector<GameWndInfo>& vtGWnd, LPCTSTR lpTagetWndName)
|
|
|
|
+ {
|
|
|
|
+ DWORD dwCurPorcessId = 0;
|
|
|
|
+ HWND hTagetProcessWnd = NULL;
|
|
|
|
+ TCHAR szWndName[MAX_PATH] = { 0 };
|
|
|
|
+ TCHAR szClassName[MAX_PATH] = { 0 };
|
|
|
|
+ // 游戏窗口信息;
|
|
|
|
+ TCHAR szGameName[MAX_PATH] = { 0 };
|
|
|
|
+ TCHAR szGameRelease[MAX_PATH] = { 0 };
|
|
|
|
+ TCHAR szGameVersion[MAX_PATH] = { 0 };
|
|
|
|
+ TCHAR szGameZoon[MAX_PATH] = { 0 };
|
|
|
|
+ TCHAR szGameServer[MAX_PATH] = { 0 };
|
|
|
|
+ TCHAR szGameRoleName[MAX_PATH] = { 0 };
|
|
|
|
+ // 清空队列;
|
|
|
|
+ vtGWnd.clear();
|
|
|
|
+ for (std::vector<DWORD>::const_iterator it = vtPid.begin(); it != vtPid.end(); it++)
|
|
|
|
+ {
|
|
|
|
+ // 取得第一个窗口句柄;
|
|
|
|
+ for (HWND hCurWnd = ::GetTopWindow(NULL); hCurWnd != NULL; hCurWnd = ::GetNextWindow(hCurWnd, GW_HWNDNEXT)) {
|
|
|
|
+ // 重置为0;
|
|
|
|
+ dwCurPorcessId = 0;
|
|
|
|
+ // 通过窗口句柄反查进程pid;
|
|
|
|
+ DWORD dwThreadId = ::GetWindowThreadProcessId(hCurWnd, &dwCurPorcessId);
|
|
|
|
+ if (dwThreadId != 0) {
|
|
|
|
+ // 判断当前进程id是否和目标进程id相同;
|
|
|
|
+ if (dwCurPorcessId == *it) {
|
|
|
|
+ if (lpTagetWndName == NULL) {
|
|
|
|
+ hTagetProcessWnd = hCurWnd;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ // 获取窗口名称;
|
|
|
|
+ ::GetWindowText(hCurWnd, szWndName, sizeof(szWndName) / sizeof(TCHAR));
|
|
|
|
+ // 获取窗口类名;
|
|
|
|
+ ::GetClassName(hCurWnd, szClassName, sizeof(szClassName) / sizeof(TCHAR));
|
|
|
|
+#ifdef _DEBUG
|
|
|
|
+ TCHAR szLogMsg[MAX_PATH] = { 0 };
|
|
|
|
+ _stprintf_s(szLogMsg, _T("类名:%s, 窗口名:%s,窗口地址:%p \n"), szClassName, szWndName, hCurWnd);
|
|
|
|
+ OutputDebugString(szLogMsg);
|
|
|
|
+#endif
|
|
|
|
+ if (_tcsstr(szWndName, lpTagetWndName) != NULL) {
|
|
|
|
+ _stscanf_s(szWndName, _T("%[^ ] %[^ ] %[^ ] %[^ ] %[^ ] %[^ ]"), szGameName, MAX_PATH, szGameRelease, MAX_PATH, szGameVersion, MAX_PATH, szGameZoon, MAX_PATH, szGameServer, MAX_PATH, szGameRoleName, MAX_PATH);
|
|
|
|
+ hTagetProcessWnd = hCurWnd;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 当前窗口有可能不是进程父窗口;
|
|
|
|
+ HWND hParentWnd = hTagetProcessWnd;
|
|
|
|
+ while (hParentWnd) {
|
|
|
|
+ hParentWnd = ::GetParent(hTagetProcessWnd);
|
|
|
|
+ if (hParentWnd == NULL)
|
|
|
|
+ break;
|
|
|
|
+ hTagetProcessWnd = hParentWnd;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (hTagetProcessWnd)
|
|
|
|
+ {
|
|
|
|
+ GameWndInfo gameInfo;
|
|
|
|
+ gameInfo.hWnd = hTagetProcessWnd;
|
|
|
|
+ gameInfo.lProcId = *it;
|
|
|
|
+ gameInfo.strGameZoon = szGameZoon;
|
|
|
|
+ gameInfo.strGameServer = szGameServer;
|
|
|
|
+ gameInfo.strGameRoleName = szGameRoleName;
|
|
|
|
+ vtGWnd.push_back(gameInfo);
|
|
|
|
+ ZeroMemory(szGameZoon, MAX_PATH);
|
|
|
|
+ ZeroMemory(szGameServer, MAX_PATH);
|
|
|
|
+ ZeroMemory(szGameRoleName, MAX_PATH);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+namespace GameGlobal {
|
|
|
|
+ int frameWidth = 2;
|
|
|
|
+ int titleBarHeight = 27;
|
|
|
|
+
|
|
|
|
+ TCHAR g_szCurModuleFileName[MAX_PATH];
|
|
|
|
+ TCHAR g_szCurModuleDir[MAX_PATH];
|
|
|
|
+ TCHAR g_szCurModulePath[MAX_PATH];
|
|
|
|
+ TCHAR g_szFna[_MAX_FNAME];
|
|
|
|
+ TCHAR g_szExt[_MAX_EXT];
|
|
|
|
+ TCHAR g_szAssistConfig[MAX_PATH];
|
|
|
|
+ std::string g_strAppdir;
|
|
|
|
+ std::string g_strGameDir;
|
|
|
|
+ TCHAR g_szGameApp[MAX_PATH];
|
|
|
|
+ int nGameWndType;
|
|
|
|
+
|
|
|
|
+ void Init()
|
|
|
|
+ {
|
|
|
|
+ TCHAR szDrive[_MAX_DRIVE] = { 0 };
|
|
|
|
+ TCHAR szDir[_MAX_DIR] = { 0 };
|
|
|
|
+ TCHAR szFna[_MAX_FNAME] = { 0 };
|
|
|
|
+ TCHAR szExt[_MAX_EXT] = { 0 };
|
|
|
|
+ DWORD dwRet = ::GetModuleFileName(NULL, g_szCurModuleFileName, sizeof(g_szCurModuleFileName) / sizeof(TCHAR));
|
|
|
|
+
|
|
|
|
+ _tsplitpath_s(g_szCurModuleFileName, szDrive, szDir, g_szFna, g_szExt);
|
|
|
|
+ _tcscat_s(g_szCurModuleDir, MAX_PATH, szDrive);
|
|
|
|
+ _tcscat_s(g_szCurModuleDir, MAX_PATH, szDir);
|
|
|
|
+
|
|
|
|
+ g_strAppdir = g_szCurModuleDir;
|
|
|
|
+ _stprintf_s(g_szAssistConfig, _T("%s%s"), g_szCurModuleDir, _T("Assist.ini"));
|
|
|
|
+
|
|
|
|
+ TCHAR szValue[MAX_PATH] = { 0 };
|
|
|
|
+ GetPrivateProfileString(_T("Assist"), _T("GamePath"), _T(""), szValue, MAX_PATH, g_szAssistConfig);
|
|
|
|
+ g_strGameDir = szValue;
|
|
|
|
+ GetPrivateProfileString(_T("Assist"), _T("GameApp"), _T(""), g_szGameApp, MAX_PATH, g_szAssistConfig);
|
|
|
|
+
|
|
|
|
+ // 读取窗口类型;
|
|
|
|
+ _stprintf_s(szValue, _T("%s%s"), g_szGameApp, _T("save\\config.ini"));
|
|
|
|
+ int ScreenWidth = GetPrivateProfileInt(_T("SysCfg"), _T("ScreenWidth"), 640, szValue);
|
|
|
|
+ if (ScreenWidth == 640)
|
|
|
|
+ nGameWndType = GW_SMALL;
|
|
|
|
+ else if (ScreenWidth == 800)
|
|
|
|
+ nGameWndType = GW_LARGE;
|
|
|
|
+ else
|
|
|
|
+ nGameWndType = GW_FULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ std::string BuildImgPath(HWND hWnd, LPCTSTR lpName)
|
|
|
|
+ {
|
|
|
|
+ TCHAR szName[MAX_PATH] = { 0 };
|
|
|
|
+ _stprintf_s(szName, _T("%s%p-%s.bmp"), GameGlobal::g_szCurModuleDir, hWnd, lpName);
|
|
|
|
+ return std::string(szName);
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+namespace ImgAssist
|
|
|
|
+{
|
|
|
|
+ std::string CaptureGameWnd(HWND hWnd)
|
|
|
|
+ {
|
|
|
|
+ TCHAR szName[MAX_PATH] = {0};
|
|
|
|
+ _stprintf_s(szName, _T("%s%p.bmp"), GameGlobal::g_szCurModuleDir, hWnd);
|
|
|
|
+ CaptureGameWnd(hWnd, szName);
|
|
|
|
+
|
|
|
|
+ return std::string(szName);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void CaptureGameWnd(HWND hWnd, std::string strSavePath)
|
|
|
|
+ {
|
|
|
|
+ HDC hDC = ::GetWindowDC(hWnd);
|
|
|
|
+ ASSERT(hDC);
|
|
|
|
+ HDC hMemDC = ::CreateCompatibleDC(hDC);
|
|
|
|
+ ASSERT(hMemDC);
|
|
|
|
+
|
|
|
|
+ RECT rc;
|
|
|
|
+ ::GetWindowRect(hWnd, &rc);
|
|
|
|
+ HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, rc.right - rc.left, rc.bottom - rc.top);
|
|
|
|
+
|
|
|
|
+ ASSERT(hBitmap);
|
|
|
|
+ HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemDC, hBitmap);
|
|
|
|
+
|
|
|
|
+ BOOL bRet = FALSE;
|
|
|
|
+ BOOL bProcessed = FALSE;
|
|
|
|
+ // 针对win10 DWM虚拟缩放时的处理
|
|
|
|
+ if (GetDeviceCaps(hDC, LOGPIXELSX) != 96)
|
|
|
|
+ {
|
|
|
|
+ DEVMODE curDevMode;
|
|
|
|
+ memset(&curDevMode, 0, sizeof(curDevMode));
|
|
|
|
+ curDevMode.dmSize = sizeof(DEVMODE);
|
|
|
|
+ BOOL bEnumRet = ::EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &curDevMode);
|
|
|
|
+ if (bEnumRet < curDevMode.dmPelsWidth)
|
|
|
|
+ {
|
|
|
|
+ bProcessed = TRUE;
|
|
|
|
+ //::SetStretchBltMode(hMemDC, STRETCH_HALFTONE);
|
|
|
|
+ //bRet = ::StretchBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, 0, 0, curDevMode.dmPelsWidth, curDevMode.dmPelsHeight, SRCCOPY | CAPTUREBLT);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ::PrintWindow(hWnd, hMemDC, 0);
|
|
|
|
+ BITMAP bitmap = { 0 };
|
|
|
|
+ ::GetObject(hBitmap, sizeof(BITMAP), &bitmap);
|
|
|
|
+ BITMAPINFOHEADER bi = { 0 };
|
|
|
|
+ BITMAPFILEHEADER bf = { 0 };
|
|
|
|
+ CONST int nBitCount = 24;
|
|
|
|
+ bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
|
+ bi.biWidth = bitmap.bmWidth;
|
|
|
|
+ bi.biHeight = bitmap.bmHeight;
|
|
|
|
+ bi.biPlanes = 1;
|
|
|
|
+ bi.biBitCount = nBitCount;
|
|
|
|
+ bi.biCompression = BI_RGB;
|
|
|
|
+ DWORD dwSize = ((bitmap.bmWidth * nBitCount + 31) / 32) * 4 * bitmap.bmHeight;
|
|
|
|
+ HANDLE hDib = GlobalAlloc(GHND, dwSize + sizeof(BITMAPINFOHEADER));
|
|
|
|
+ if (hDib == NULL)
|
|
|
|
+ return;
|
|
|
|
+ LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
|
|
|
|
+ //memcpy(lpbi, &bi, sizeof(BITMAPINFOHEADER));
|
|
|
|
+ *lpbi = bi;
|
|
|
|
+ ::GetDIBits(hMemDC, hBitmap, 0, bitmap.bmHeight, (BYTE*)lpbi + sizeof(BITMAPINFOHEADER), (BITMAPINFO*)lpbi, DIB_RGB_COLORS);
|
|
|
|
+
|
|
|
|
+ CFile file;
|
|
|
|
+ CFileException fep;
|
|
|
|
+ if (file.Open(strSavePath.c_str(), CFile::modeCreate | CFile::modeWrite, &fep)) {
|
|
|
|
+ bf.bfType = 0x4d42;
|
|
|
|
+ dwSize += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
|
|
|
+ bf.bfSize = dwSize;
|
|
|
|
+ bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
|
|
|
+ file.Write((BYTE*)&bf, sizeof(BITMAPFILEHEADER));
|
|
|
|
+ file.Write((BYTE*)lpbi, dwSize);
|
|
|
|
+ file.Close();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ GlobalUnlock(hDib);
|
|
|
|
+ GlobalFree(hDib);
|
|
|
|
+ ::SelectObject(hMemDC, hOldBmp);
|
|
|
|
+ ::DeleteObject(hBitmap);
|
|
|
|
+ ::DeleteObject(hMemDC);
|
|
|
|
+ ::ReleaseDC(hWnd, hDC);
|
|
|
|
+
|
|
|
|
+ Sleep(30);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ BOOL OpenImage(std::string strImag, cv::Mat& img)
|
|
|
|
+ {
|
|
|
|
+ if (!PathFileExists(strImag.c_str()))
|
|
|
|
+ return FALSE;
|
|
|
|
+
|
|
|
|
+ if (img.data != NULL)
|
|
|
|
+ img.release();
|
|
|
|
+
|
|
|
|
+ img = cv::imread(strImag.c_str(), cv::IMREAD_COLOR);
|
|
|
|
+ if (img.data == NULL)
|
|
|
|
+ return FALSE;
|
|
|
|
+
|
|
|
|
+ return TRUE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ BOOL SetImgThreshold(cv::Mat& srcImg, cv::Mat& thresholdImg, long nThresholdVal, long nMaxThresholdVal, int type)
|
|
|
|
+ {
|
|
|
|
+ if (srcImg.data == NULL)
|
|
|
|
+ return FALSE;
|
|
|
|
+
|
|
|
|
+ if (thresholdImg.data && srcImg.data != thresholdImg.data)
|
|
|
|
+ thresholdImg.release();
|
|
|
|
+
|
|
|
|
+ switch (type)
|
|
|
|
+ {
|
|
|
|
+ case 0://全局阀值;
|
|
|
|
+ {
|
|
|
|
+ // 转成灰阶图;
|
|
|
|
+ cv::cvtColor(srcImg, thresholdImg, cv::COLOR_BGR2GRAY);
|
|
|
|
+ // 再高斯模糊处理(滤波);
|
|
|
|
+ cv::GaussianBlur(thresholdImg, thresholdImg, cv::Size(5, 5), 0, 0);
|
|
|
|
+ // 二值化;//全局化指定的阀值与返回值相等;
|
|
|
|
+ double dRetVal = cv::threshold(thresholdImg, thresholdImg, nThresholdVal, nMaxThresholdVal, cv::THRESH_BINARY);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case 1://自适应阀值;
|
|
|
|
+ {
|
|
|
|
+ // 转成灰阶图;
|
|
|
|
+ cv::cvtColor(srcImg, thresholdImg, cv::COLOR_BGR2GRAY);
|
|
|
|
+ // 再高斯模糊处理(滤波);
|
|
|
|
+ cv::GaussianBlur(thresholdImg, thresholdImg, cv::Size(3, 3), 0, 0);
|
|
|
|
+ // 自适应阀值;
|
|
|
|
+ cv::medianBlur(thresholdImg, thresholdImg, 3);
|
|
|
|
+ // 局部二值化;//blocksize一般取3、5、7
|
|
|
|
+ cv::adaptiveThreshold(thresholdImg, thresholdImg, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 3, 4.5);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case 2:// otsu阀值;
|
|
|
|
+ {
|
|
|
|
+ cv::cvtColor(srcImg, thresholdImg, cv::COLOR_BGR2GRAY);
|
|
|
|
+ // 高斯模糊;
|
|
|
|
+ cv::GaussianBlur(thresholdImg, thresholdImg, cv::Size(3, 3), 0, 0);
|
|
|
|
+ cv::threshold(thresholdImg, thresholdImg, nThresholdVal, nMaxThresholdVal, cv::THRESH_BINARY | cv::THRESH_OTSU);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return TRUE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ BOOL GetImgMatchtemplate(HWND hWnd, std::string strTempImg, RECT& rc, double lowestMatchValue)
|
|
|
|
+ {
|
|
|
|
+ std::string strImage = CaptureGameWnd(hWnd);
|
|
|
|
+ cv::Mat srcImg, tempImg, matchImg;
|
|
|
|
+ if (!OpenImage(strImage, srcImg) || !OpenImage(strTempImg, tempImg))
|
|
|
|
+ {
|
|
|
|
+ if (srcImg.data) srcImg.release();
|
|
|
|
+ if (tempImg.data) tempImg.release();
|
|
|
|
+ return FALSE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ cv::matchTemplate(srcImg, tempImg, matchImg, cv::TM_CCOEFF_NORMED);
|
|
|
|
+ // 归一化到0~1
|
|
|
|
+ //cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
|
|
|
|
+
|
|
|
|
+ double lv_nMinVal = 0.0;
|
|
|
|
+ double lv_nMaxVal = 0.0;
|
|
|
|
+ cv::Point lv_nMinLoc = cv::Point(0, 0);
|
|
|
|
+ cv::Point lv_nMaxLoc = cv::Point(0, 0);
|
|
|
|
+ cv::Point lv_MatchLoc = cv::Point(0, 0);
|
|
|
|
+ cv::minMaxLoc(matchImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
|
|
|
|
+
|
|
|
|
+ cv::Rect roi = cv::Rect(lv_nMaxLoc.x, lv_nMaxLoc.y, tempImg.cols, tempImg.rows);
|
|
|
|
+ cv::Mat roiImg = srcImg(roi);
|
|
|
|
+ cv::imwrite(GameGlobal::BuildImgPath(hWnd, _T("match.bmp")), roiImg);
|
|
|
|
+
|
|
|
|
+ rc.left = lv_nMaxLoc.x - frameWidth;
|
|
|
|
+ rc.top = lv_nMaxLoc.y - titleBarHeight;
|
|
|
|
+ rc.right = rc.left + tempImg.cols;
|
|
|
|
+ rc.bottom = rc.top + tempImg.rows;
|
|
|
|
+
|
|
|
|
+ srcImg.release();
|
|
|
|
+ tempImg.release();
|
|
|
|
+ matchImg.release();
|
|
|
|
+ roiImg.release();
|
|
|
|
+
|
|
|
|
+ // 是否大于最低匹配度;
|
|
|
|
+ return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ BOOL GetImgMatchtemplate(std::string strSrcImg, std::string strTempImg, RECT& rc, double lowestMatchValue)
|
|
|
|
+ {
|
|
|
|
+ cv::Mat srcImg, tempImg, matchImg;
|
|
|
|
+ if (!OpenImage(strSrcImg, srcImg) || !OpenImage(strTempImg, tempImg))
|
|
|
|
+ {
|
|
|
|
+ if (srcImg.data) srcImg.release();
|
|
|
|
+ if (tempImg.data) tempImg.release();
|
|
|
|
+ return FALSE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ cv::matchTemplate(srcImg, tempImg, matchImg, cv::TM_CCOEFF_NORMED);
|
|
|
|
+ // 归一化到0~1
|
|
|
|
+ //cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
|
|
|
|
+
|
|
|
|
+ double lv_nMinVal = 0.0;
|
|
|
|
+ double lv_nMaxVal = 0.0;
|
|
|
|
+ cv::Point lv_nMinLoc = cv::Point(0, 0);
|
|
|
|
+ cv::Point lv_nMaxLoc = cv::Point(0, 0);
|
|
|
|
+ cv::Point lv_MatchLoc = cv::Point(0, 0);
|
|
|
|
+ cv::minMaxLoc(matchImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
|
|
|
|
+
|
|
|
|
+ cv::Rect roi = cv::Rect(lv_nMaxLoc.x, lv_nMaxLoc.y, tempImg.cols, tempImg.rows);
|
|
|
|
+ cv::Mat roiImg = srcImg(roi);
|
|
|
|
+ //cv::imwrite("G:\\bin\\GameAssist\\match.bmp", roiImg);
|
|
|
|
+
|
|
|
|
+ rc.left = lv_nMaxLoc.x - frameWidth;
|
|
|
|
+ rc.top = lv_nMaxLoc.y - titleBarHeight;
|
|
|
|
+ rc.right = rc.left + tempImg.cols;
|
|
|
|
+ rc.bottom = rc.top + tempImg.rows;
|
|
|
|
+
|
|
|
|
+ srcImg.release();
|
|
|
|
+ tempImg.release();
|
|
|
|
+ matchImg.release();
|
|
|
|
+ roiImg.release();
|
|
|
|
+
|
|
|
|
+ // 是否大于最低匹配度;
|
|
|
|
+ return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ BOOL IsMatchIcon(HWND hWnd, std::string strTempImg, RECT srcRect, RECT& matchRect, double lowestMatchValue)
|
|
|
|
+ {
|
|
|
|
+ std::string strImg = CaptureGameWnd(hWnd);
|
|
|
|
+ cv::Mat srcImg, tempImg, matchImg;
|
|
|
|
+ if (!OpenImage(strImg, srcImg) || !OpenImage(strTempImg, tempImg))
|
|
|
|
+ {
|
|
|
|
+ if (srcImg.data) srcImg.release();
|
|
|
|
+ if (tempImg.data) tempImg.release();
|
|
|
|
+ return FALSE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 指定源图片区域来做模块比较,提高效率;
|
|
|
|
+ cv::Mat imgROI;
|
|
|
|
+ imgROI = srcImg(cv::Rect(srcRect.left, srcRect.top, srcRect.right - srcRect.left, srcRect.bottom - srcRect.top));
|
|
|
|
+ cv::imwrite(GameGlobal::BuildImgPath(hWnd, _T("roi")), imgROI);
|
|
|
|
+ /*
|
|
|
|
+ m_ImgROI = srcImg([&]()-> cv::Rect {
|
|
|
|
+ // 注意是x,y,w=cols,h=rows
|
|
|
|
+ return cv::Rect(srcRect.left, srcRect.top, srcRect.right - srcRect.left, srcRect.bottom - srcRect.top);
|
|
|
|
+ }());
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ cv::matchTemplate(imgROI, tempImg, matchImg, cv::TM_CCOEFF_NORMED);
|
|
|
|
+ // 归一化到0~1
|
|
|
|
+ //cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
|
|
|
|
+
|
|
|
|
+ double lv_nMinVal = 0.0;
|
|
|
|
+ double lv_nMaxVal = 0.0;
|
|
|
|
+ cv::Point lv_nMinLoc = cv::Point(0, 0);
|
|
|
|
+ cv::Point lv_nMaxLoc = cv::Point(0, 0);
|
|
|
|
+ cv::Point lv_MatchLoc = cv::Point(0, 0);
|
|
|
|
+ cv::minMaxLoc(matchImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
|
|
|
|
+
|
|
|
|
+ cv::Rect roi = cv::Rect(lv_nMaxLoc.x, lv_nMaxLoc.y, tempImg.cols, tempImg.rows);
|
|
|
|
+ cv::Mat roiImg = imgROI(roi);
|
|
|
|
+ cv::imwrite(GameGlobal::BuildImgPath(hWnd, _T("match")), roiImg);
|
|
|
|
+
|
|
|
|
+ matchRect.left = srcRect.left + lv_nMaxLoc.x - frameWidth;
|
|
|
|
+ matchRect.top = srcRect.top + lv_nMaxLoc.y - titleBarHeight;
|
|
|
|
+ matchRect.right = matchRect.left + tempImg.cols;
|
|
|
|
+ matchRect.bottom = matchRect.top + tempImg.rows;
|
|
|
|
+
|
|
|
|
+ imgROI.release();
|
|
|
|
+ srcImg.release();
|
|
|
|
+ tempImg.release();
|
|
|
|
+ matchImg.release();
|
|
|
|
+ roiImg.release();
|
|
|
|
+
|
|
|
|
+ // 是否大于最低匹配度;
|
|
|
|
+ return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ BOOL CropPicture(HWND hWnd, CRect rc, const char* szSaveName)
|
|
|
|
+ {
|
|
|
|
+ std::string strImg = CaptureGameWnd(hWnd);
|
|
|
|
+ cv::Mat srcImg, tempImg, matchImg;
|
|
|
|
+ if (!OpenImage(strImg, srcImg))
|
|
|
|
+ {
|
|
|
|
+ if (srcImg.data) srcImg.release();
|
|
|
|
+ return FALSE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 指定源图片区域来做模块比较,提高效率;
|
|
|
|
+ cv::Mat imgROI;
|
|
|
|
+ imgROI = srcImg(cv::Rect(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top));
|
|
|
|
+ cv::imwrite(szSaveName, imgROI);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ BOOL IsSimilarPicture(const char* szp1, const char* szp2, double lowestMatchValue)
|
|
|
|
+ {
|
|
|
|
+ cv::Mat src, dest, matchImg;
|
|
|
|
+ src = cv::imread(szp1);
|
|
|
|
+ dest = cv::imread(szp2);
|
|
|
|
+
|
|
|
|
+ cv::matchTemplate(src, dest, matchImg, cv::TM_CCOEFF_NORMED);
|
|
|
|
+ // 归一化到0~1
|
|
|
|
+ //cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
|
|
|
|
+
|
|
|
|
+ double lv_nMinVal = 0.0;
|
|
|
|
+ double lv_nMaxVal = 0.0;
|
|
|
|
+ cv::Point lv_nMinLoc = cv::Point(0, 0);
|
|
|
|
+ cv::Point lv_nMaxLoc = cv::Point(0, 0);
|
|
|
|
+ cv::Point lv_MatchLoc = cv::Point(0, 0);
|
|
|
|
+ cv::minMaxLoc(matchImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
|
|
|
|
+
|
|
|
|
+ src.release();
|
|
|
|
+ matchImg.release();
|
|
|
|
+ dest.release();
|
|
|
|
+
|
|
|
|
+ // 是否大于最低匹配度;
|
|
|
|
+ return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
|
|
|
|
+ }
|
|
|
|
+
|
|
};
|
|
};
|