Pārlūkot izejas kodu

重新归类。

Jeff 4 gadi atpakaļ
vecāks
revīzija
b55acdfd4a

+ 621 - 6
GameAssist/GameAssist/Assist.cpp

@@ -8,6 +8,9 @@
 // #pragma comment(lib, "d3d11.lib")
 // #pragma comment(lib, "dxgi.lib")
 
+int frameWidth = 2;
+int titleBarHeight = 27;
+
 namespace GAssist
 {
 	int frameWidth = 2;
@@ -271,7 +274,7 @@ namespace GAssist
 		TCHAR szGameRoleName[MAX_PATH] = { 0 };
 		// 清空队列;
 		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)) {
@@ -530,7 +533,7 @@ namespace GAssist
 #else
 		POINT ptScreen;// = { x,y };
 		::GetCursorPos(&ptScreen);
-		
+
 		mouse_event(MOUSEEVENTF_RIGHTDOWN, ptScreen.x, ptScreen.y, 0, 0);
 		mouse_event(MOUSEEVENTF_RIGHTUP, ptScreen.x, ptScreen.y, 0, 0);
 #endif
@@ -1193,11 +1196,11 @@ namespace GAssist
 		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"));
 		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();
 			return FALSE;
@@ -1214,7 +1217,7 @@ namespace GAssist
 		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);
@@ -1246,7 +1249,8 @@ namespace GAssist
 
 }
 
-namespace GameAssist {
+namespace GameAssist
+{
 	void SetGameForeground(HWND hWnd)
 	{
 		if (!IsWindow(hWnd))
@@ -1256,6 +1260,11 @@ namespace GameAssist {
 		::SetForegroundWindow(hWnd); // 窗口前置才能单击成功;
 	}
 
+	bool IsGameForeground(HWND hWnd)
+	{
+		return false;
+	}
+
 	BOOL GamePos2Screen(HWND hWnd, POINT& pt, bool bOffset)
 	{
 		if (!::IsWindow(hWnd)) return FALSE;
@@ -1508,4 +1517,610 @@ namespace GameAssist {
 		if (bShift)
 			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);
+	}
+
 };

+ 63 - 3
GameAssist/GameAssist/Assist.h

@@ -87,9 +87,6 @@ namespace GAssist
 	extern HWND GetProcessMainWnd(const DWORD &dwTagetProcessId, LPCTSTR lpTagetWndName = _T("大话水浒"));
 	extern void GetAllProcessMainWnd(const std::vector<DWORD> &vtPid, std::vector<GameWndInfo> &vtGWnd, LPCTSTR lpTagetWndName = _T("大话水浒"));
 	extern HWND GetProcessMainWnd(LPCTSTR lpProcessName = _T("Game.exe"), LPCTSTR lpTagetWndName = _T("大话水浒"));
-
-
-
 	// 启动游戏;
 	extern void StartGame(std::string strGameDir, int nStartCount = 5);
 	// 单击事件;
@@ -129,9 +126,55 @@ namespace GAssist
 	BOOL IsWin10DpiScaleEanbled();
 };
 
+namespace GameGlobal {
+	enum {
+		GW_SMALL,
+		GW_LARGE,
+		GW_FULL,
+	}GAME_WND;
+	extern int titleBarHeight;
+	extern int frameWidth;
+
+	extern TCHAR g_szCurModuleFileName[MAX_PATH];
+	extern TCHAR g_szCurModuleDir[MAX_PATH];
+	extern TCHAR g_szCurModulePath[MAX_PATH];
+	extern TCHAR g_szFna[_MAX_FNAME];
+	extern TCHAR g_szExt[_MAX_EXT];
+	extern TCHAR g_szAssistConfig[MAX_PATH];
+	extern std::string g_strAppdir;
+	extern std::string g_strGameDir;
+	extern TCHAR g_szGameApp[MAX_PATH];
+	extern int nGameWndType;
+
+	void Init();
+	std::string BuildImgPath(HWND hWnd, LPCTSTR lpName);
+};
+
+namespace ImgAssist {
+	std::string CaptureGameWnd(HWND hWnd);
+	void CaptureGameWnd(HWND hWnd, std::string strSavePath);
+	BOOL OpenImage(std::string strImag, cv::Mat& img);
+	BOOL SetImgThreshold(cv::Mat& srcImg, cv::Mat& thresholdImg, long nThresholdVal, long nMaxThresholdVal, int type = 0);
+	BOOL GetImgMatchtemplate(HWND hWnd, std::string strTempImg, RECT& rc, double lowestMatchValue = 0.900);
+	BOOL GetImgMatchtemplate(std::string strSrcImg, std::string strTempImg, RECT& rc, double lowestMatchValue = 0.900);
+	BOOL IsMatchIcon(HWND hWnd, std::string strTempImg, RECT srcRect, RECT& matchRect, double lowestMatchValue = 0.900);
+	BOOL CropPicture(HWND hWnd, CRect rc, const char* szSaveName); // 剪裁图片;
+	BOOL IsSimilarPicture(const char* szp1, const char* szp2, double lowestMatchValue = 0.99);
+};
+
 // 所有坐标,都是基于游戏窗口的相对坐标值;
 // 游戏窗口:802*627
 namespace GameAssist{
+	typedef struct __GAMEWNDINFO__
+	{
+		unsigned long       lProcId;				// 进程ID;
+		HWND                hWnd;					// 进程窗口句柄;
+		std::string			strGameRoleName;		// 角色名称;
+		std::string			strGameZoon;			// 区域;
+		std::string			strGameServer;			// 服务站
+	}GameWndInfo, * pGameWndInfo;
+	extern std::vector<GameWndInfo> g_vtGameWndInfo;
+
 	// 设置游戏窗口前置;
 	void SetGameForeground(HWND hWnd);
 	// 判断游戏窗口是否前置;
@@ -156,6 +199,23 @@ namespace GameAssist{
 
 	// 发送按键;
 	void SendKey(DWORD key, BOOL bCtrl = FALSE, BOOL bAtl = FALSE, BOOL bShift = FALSE);
+
+	// 获取剪切板字符串;
+	CString GetClipboradString();
+	// 设置剪切板字符串;
+	BOOL SetClipboardString(LPCTSTR lpString);
+
+	// 根据进程名获取进程pid;
+	DWORD GetProcessId(LPCTSTR lpProcessName = _T("Game.exe"));
+	// 获取所有指定进程名的进程pid;
+	void GetAllProcessId(std::vector<DWORD>& vtPid, LPCTSTR lpProcessName = _T("Game.exe"));
+	// 根据进程pid获取进程对应程序的窗口句柄;
+	HWND GetProcessMainWnd(const DWORD& dwTagetProcessId, LPCTSTR lpTagetWndName = _T("大话水浒"));
+	// 获取指定进程名的进程主窗口;
+	HWND GetProcessMainWnd(LPCTSTR lpProcessName = _T("Game.exe"), LPCTSTR lpTagetWndName = _T("大话水浒"));
+	// 获取所有指定进程名的进程主窗口;
+	void GetAllProcessMainWnd(const std::vector<DWORD>& vtPid, std::vector<GameWndInfo>& vtGWnd, LPCTSTR lpTagetWndName = _T("大话水浒"));
+	
 };
 
 #endif // __ASSIST__

+ 80 - 0
GameAssist/GameAssist/CritSection.h

@@ -0,0 +1,80 @@
+#pragma once
+
+class ThreadSection
+{
+public:
+	ThreadSection(){
+		HRESULT hr = Init();
+		(hr);
+	}
+
+	~ThreadSection(){
+		DeleteCriticalSection(&_CriticalSection);
+	}
+
+	bool Lock()
+	{
+		bool result = false;
+		__try
+		{
+			EnterCriticalSection(&_CriticalSection);
+			result = true;
+		}
+		__except (STATUS_NO_MEMORY == GetExceptionCode())
+		{
+		}
+		return result;
+	}
+
+	bool Unlock()
+	{
+		bool result = false;
+		__try
+		{
+			LeaveCriticalSection(&_CriticalSection);
+			result = true;
+		}
+		__except (STATUS_NO_MEMORY == GetExceptionCode())
+		{
+		}
+		return result;
+	}
+
+private:
+	HRESULT Init() throw()
+	{
+		HRESULT hRes = E_FAIL;
+		__try
+		{
+			InitializeCriticalSection(&_CriticalSection);
+			hRes = S_OK;
+		}
+		__except (STATUS_NO_MEMORY == GetExceptionCode())
+		{
+			hRes = E_OUTOFMEMORY;
+		}
+		return hRes;
+	}
+
+	ThreadSection(const ThreadSection & tSection);
+	ThreadSection &operator=(const ThreadSection & tSection);
+	CRITICAL_SECTION _CriticalSection;
+};
+
+
+class AutoThreadSection
+{
+public:
+	AutoThreadSection(IN ThreadSection* pSection){
+		_pSection = pSection;
+		_pSection->Lock();
+	}
+
+	~AutoThreadSection(){
+		_pSection->Unlock();
+	}
+private:
+	AutoThreadSection(const AutoThreadSection & tSection);
+	AutoThreadSection &operator=(const AutoThreadSection & tSection);
+	ThreadSection * _pSection;
+};

+ 2 - 0
GameAssist/GameAssist/GameAssist.vcxproj

@@ -233,6 +233,7 @@
   <ItemGroup>
     <ClInclude Include="Assist.h" />
     <ClInclude Include="CAction.h" />
+    <ClInclude Include="CritSection.h" />
     <ClInclude Include="CTask.h" />
     <ClInclude Include="CVideoCapture.h" />
     <ClInclude Include="DXGICaptor.h" />
@@ -243,6 +244,7 @@
     <ClInclude Include="stdafx.h" />
     <ClInclude Include="targetver.h" />
     <ClInclude Include="VideoDXGICaptor.h" />
+    <ClInclude Include="VirturalKey.h" />
   </ItemGroup>
   <ItemGroup>
     <None Include="Assist.ini" />

+ 6 - 0
GameAssist/GameAssist/GameAssist.vcxproj.filters

@@ -89,6 +89,12 @@
     <ClInclude Include="DXGICaptor.h">
       <Filter>头文件</Filter>
     </ClInclude>
+    <ClInclude Include="VirturalKey.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="CritSection.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="Assist.ini">