浏览代码

截图:
当前窗口被遮挡住,主要使用PrintWindow函数解决。

Jeff 5 年之前
父节点
当前提交
da11a6d545
共有 3 个文件被更改,包括 302 次插入72 次删除
  1. 221 16
      GameAssist/GameAssist/Assist.cpp
  2. 39 1
      GameAssist/GameAssist/Assist.h
  3. 42 55
      GameAssist/GameAssist/GameAssistDlg.cpp

+ 221 - 16
GameAssist/GameAssist/Assist.cpp

@@ -16,12 +16,9 @@ namespace GAssist
 		}
 		pe32.dwSize = sizeof(PROCESSENTRY32);
 
-		if (Process32First(hProcessSnap, &pe32))
-		{
-			do
-			{
-				if (_tcscmp(lpProName, pe32.szExeFile) == 0)
-				{
+		if (Process32First(hProcessSnap, &pe32)) {
+			do {
+				if (_tcscmp(lpProName, pe32.szExeFile) == 0) {
 					dwProcessID = pe32.th32ProcessID;
 					break;
 				}
@@ -38,16 +35,14 @@ namespace GAssist
 		HWND hwndRet = NULL;
 		// 取得第一个窗口句柄
 		HWND hwndWindow = ::GetTopWindow(NULL);
-		while (hwndWindow)
-		{
+		// 遍历出结果窗口;
+		while (hwndWindow) {
 			dwPID = 0;
 			// 通过窗口句柄取得进程ID
 			DWORD dwTheardID = ::GetWindowThreadProcessId(hwndWindow, &dwPID);
-			if (dwTheardID != 0)
-			{
+			if (dwTheardID != 0) {
 				// 判断和参数传入的进程ID是否相等
-				if (dwPID == dwProcessId)
-				{
+				if (dwPID == dwProcessId) {
 					// 进程ID相等,则记录窗口句柄
 					hwndRet = hwndWindow;
 					break;
@@ -63,8 +58,7 @@ namespace GAssist
 		// 上面取得的窗口,不一定是最上层的窗口,需要通过GetParent获取最顶层窗口
 		HWND hwndWindowParent = NULL;
 		// 循环查找父窗口,以便保证返回的句柄是最顶层的窗口句柄
-		while (hwndRet != NULL)
-		{
+		while (hwndRet != NULL) {
 			::GetWindowText(hwndRet, szName, sizeof(szName) / sizeof(TCHAR));
 			::GetClassName(hwndRet, szClass, sizeof(szClass) / sizeof(TCHAR)); // 窗口类
 			//TRACE3(_T("%s %s %s"), szClass, szName, "\n");
@@ -72,8 +66,7 @@ namespace GAssist
 			OutputDebugString(szLogMsg);
 
 			hwndWindowParent = ::GetParent(hwndRet);
-			if (hwndWindowParent == NULL)
-			{
+			if (hwndWindowParent == NULL) {
 				break;
 			}
 			hwndRet = hwndWindowParent;
@@ -114,4 +107,216 @@ namespace GAssist
 		}  
 		return  TRUE;  
 	}  
+
+	// nStartCount:启动进程数量;
+	void StartGame(std::string strGameDir)
+	{
+		if ( !PathFileExists(strGameDir.c_str()) )
+			return;
+
+		SetCurrentDirectory(strGameDir.c_str());
+
+		ShellExecute(NULL, "open", GAssist::g_szGamePath, NULL, NULL, SW_SHOWNORMAL);//SW_HIDE无用,因为会自动结;
+		Sleep(1500); // Main.exe设置了陷阱(自己再开启了一个进程,结束上一个进程),需要等1.5秒;
+
+		DWORD dwProcId = GAssist::FindProcess(_T("Main.exe"));
+		if ( dwProcId <= 0 )
+			return;
+		
+		EnumWindows(GAssist::EnumChildWindowCallBack, dwProcId);
+		if ( GAssist::g_vtGameHwnd.size() ) {
+			int nStatus = 0;
+			GAssist::GameHwnd* gp = NULL;
+			GAssist::GameHwnd* gbmin = NULL;
+			GAssist::GameHwnd* gbentry = NULL;
+			for ( std::vector<GAssist::GameHwnd>::iterator it = GAssist::g_vtGameHwnd.begin(); it != GAssist::g_vtGameHwnd.end(); it++ )
+			{
+				if ( nStatus >= 3 )
+					break;
+
+				if ( _tcsicmp(it->strWinText.c_str(), _T("最小化")) == 0 )
+				{
+					gbmin = &*it;
+					nStatus++;
+				}
+
+				if ( _tcsicmp(it->strWinText.c_str(), _T("大话水浒")) == 0 )
+				{
+					gp = &*it;
+					nStatus++;
+				}
+
+				if ( _tcsicmp(it->strWinText.c_str(), _T("进入游戏")) == 0 )
+				{
+					gbentry = &*it;
+					nStatus++;
+				}
+			}
+
+			if ( gp && gbentry && gbmin) {
+				// 发送点击事件;
+				// 先最小化;
+				::SendMessage(gp->hwnd,WM_COMMAND,gbmin->dwId,NULL);
+				// 再进入;
+				::SendMessage(gp->hwnd,WM_COMMAND,gbentry->dwId,NULL);
+			}
+		}
+	}
+	
+	// 使用WM_LBUTTONDBLCLK完全无效;
+	void MouseClick(HWND hwnd, POINT pt)
+	{
+		if ( !IsWindow(hwnd) )
+			return;
+
+		::SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
+		::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
+		Sleep(200);
+	}
+
+	void MouseClick(HWND hwnd, unsigned int x, unsigned int y)
+	{
+		if ( !IsWindow(hwnd) )
+			return;
+
+		::SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y));
+		::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(x, y));
+		Sleep(200);
+	}
+
+	// 截图;
+	HBITMAP CopyDC2Bitmap(HWND hWnd, LPRECT lpRect)
+	{
+		if ( !lpRect || IsRectEmpty(lpRect) )
+			return NULL;
+
+		//HDC hWndDC = ::GetWindowDC(hWnd);
+		HDC hWndDC = ::GetDC(hWnd);
+		// 创建兼容DC;
+		HDC hMemDC = CreateCompatibleDC(hWndDC);
+		CRect rc(lpRect->top, lpRect->left, lpRect->right, lpRect->bottom);
+		//::ClientToScreen(hWnd, &rc);
+		HBITMAP hOldBitmap, hMenBitmap;
+		int top = 0, left = 0, right = 0, bottom = 0;
+		int nWidth = 0, nHeight = 0;
+
+		top = lpRect->top;
+		left = lpRect->left;
+		right = lpRect->right;
+		bottom = lpRect->bottom;
+
+		nWidth = right - left;
+		nHeight = bottom - top;
+
+		// 创建兼容DC;
+		hMenBitmap = CreateCompatibleBitmap(hWndDC, nWidth, nHeight);
+
+		hOldBitmap = (HBITMAP)SelectObject(hMemDC, hMenBitmap);
+		::PrintWindow(hWnd, hMemDC, 0);  
+		// 将窗口DC内存复制到兼容DC上;
+		StretchBlt(hMemDC, 0, 0, nWidth, nHeight, hWndDC, left, top, nWidth, nHeight, SRCCOPY);
+		//BitBlt(hMemDC, 0, 0, nWidth, nHeight, hWndDC, left, top, SRCCOPY);
+		hMenBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
+
+		DeleteDC(hMemDC);
+		DeleteObject(hOldBitmap);
+
+		return hMenBitmap;
+	}
+
+	BOOL SaveBitmap(HBITMAP hBitmpa, std::string strSavePath)
+	{
+		//把位图的信息保存到bmpinfo;    
+		BITMAP bmpinfo;    
+		GetObject(hBitmpa,sizeof(BITMAP),&bmpinfo);    
+		DWORD dwBmBitsSize = ((bmpinfo.bmWidth * 32+31)/32) * 4 * bmpinfo.bmHeight;     
+		//位图文件头 14字节    
+		BITMAPFILEHEADER bf;    
+		bf.bfType      = 0x4D42;                  
+		//BM    
+		bf.bfSize      = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize;     
+		bf.bfReserved1 = 0;     
+		bf.bfReserved2 = 0;     
+		bf.bfOffBits   = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);     
+		//位图信息头    
+		BITMAPINFOHEADER bi;    
+		bi.biSize          = sizeof(BITMAPINFOHEADER);    
+		bi.biWidth         = bmpinfo.bmWidth;    
+		bi.biHeight        = bmpinfo.bmHeight;    
+		bi.biPlanes        = 1;    
+		bi.biBitCount      = 32;    
+		bi.biCompression   = BI_RGB;    
+		bi.biSizeImage     = 0;    
+		bi.biXPelsPerMeter = 0;    
+		bi.biYPelsPerMeter = 0;    
+		bi.biClrUsed       = 8;    
+		bi.biClrImportant  = 0;    
+		//位图数据;    
+		char* context = new char[dwBmBitsSize];
+		HDC dc  = ::GetDC(NULL);    
+		GetDIBits(dc, hBitmpa, 0, bi.biHeight, context, (BITMAPINFO*)&bi, DIB_RGB_COLORS);    
+		FILE* f = fopen(strSavePath.c_str(),"wb");    
+		fwrite((char*)&bf,sizeof(BITMAPFILEHEADER),1,f);    
+		fwrite((char*)&bi,sizeof(BITMAPINFOHEADER),1,f);    
+		fwrite(context,dwBmBitsSize,1,f);    
+		fclose(f);    
+		delete context;    
+		::ReleaseDC(NULL,dc);    
+		return 0;    
+	}
+
+	void SaveHwndToBmpFile(HWND hWnd, LPCTSTR lpszPath) { 	
+		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); 	
+		::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)); 	
+		LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); 	
+		*lpbi = bi;  	
+		::GetDIBits(hMemDC, hBitmap, 0, bitmap.bmHeight, (BYTE*)lpbi + sizeof(BITMAPINFOHEADER), (BITMAPINFO*)lpbi, DIB_RGB_COLORS);  	
+		try 	
+		{ 		
+			CFile file; 		
+			file.Open(lpszPath, CFile::modeCreate | CFile::modeWrite); 		
+			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(); 	
+		} 	
+		catch(CFileException* e) 	
+		{ 		
+			e->ReportError(); 		
+			e->Delete(); 	
+		}  	
+		GlobalUnlock(hDib); 	
+		GlobalFree(hDib);  	
+		::SelectObject(hMemDC, hOldBmp); 	
+		::DeleteObject(hBitmap);	 	
+		::DeleteObject(hMemDC); 	
+		::ReleaseDC(hWnd, hDC); 
+	}  
+
 }

+ 39 - 1
GameAssist/GameAssist/Assist.h

@@ -6,7 +6,8 @@
 
 namespace GAssist
 {
-	const TCHAR g_szGamePath[MAX_PATH] = _T("E:\\dhsh\\shdata\\Main.exe");
+	//const TCHAR g_szGamePath[MAX_PATH] = _T("E:\\dhsh\\shdata\\Main.exe");
+	const TCHAR g_szGamePath[MAX_PATH] = _T("D:\\tools\\dhsh\\shdata\\Main.exe");
 	extern DWORD FindProcess(IN LPCSTR lpProName);
 	extern HWND GetProHwnd(DWORD dwProcessId);
 	extern BOOL CALLBACK EnumChildWindowCallBack(HWND hWnd, LPARAM lParam);
@@ -19,6 +20,43 @@ namespace GAssist
 	}GameHwnd, *pGameHwnd;
 
 	extern std::vector<GameHwnd> g_vtGameHwnd;
+
+	typedef struct __GAC__ {
+		bool				bLogin;                 // 登录状态;
+		std::string			strAccount;             // 账号;
+		std::string			strPassword;            // 密码;
+		unsigned long		lRoleNumber;            // 角色ID;
+		std::string			strRoleName;            // 角色名称;
+		std::string			strRoleType;            // 角色类型:剑客、武师、医师、道士、术士;
+		unsigned short		nRoleLevel;             // 角色等级;
+		std::string			strRoleZone;            // 角色所在区:电信一区……;
+		std::string			strRoleSuit;            // 角色所在服:忘忧谷;
+		// 关联某进程信息;
+		unsigned long       lProcId;				// 进程ID;
+		HWND                hWnd;					// 进程窗口句柄;
+		unsigned char       wndType;				// 窗口类型:0=小窗口、1=大窗口、2=全屏;
+		std::string			strWndText;				// 窗口名称;
+		__GAC__() {
+			bLogin = false;
+			lProcId = 0;
+			lRoleNumber = 0;
+			nRoleLevel = 0;
+			wndType = 0;
+		}
+	}GUserInfo, *PGUserInfo;
+	extern std::vector<GUserInfo> g_vtGUserInfo;
+
+	// 启动游戏;
+	extern void StartGame(std::string strGameDir, int nStartCount = 5);
+	// 单击事件;
+	extern void MouseClick(HWND hwnd, POINT pt);
+	extern void MouseClick(HWND hwnd, unsigned int x, unsigned int y);
+
+	// 截图;
+	HBITMAP CopyDC2Bitmap(HWND hWnd, LPRECT lpRect);
+	// 保存图片;
+	BOOL SaveBitmap(HBITMAP hBitmpa, std::string strSavePath);
+	void SaveHwndToBmpFile(HWND hWnd, LPCTSTR lpszPath);
 };
 
 #endif // __ASSIST__

+ 42 - 55
GameAssist/GameAssist/GameAssistDlg.cpp

@@ -155,6 +155,19 @@ HCURSOR CGameAssistDlg::OnQueryDragIcon()
 
 void CGameAssistDlg::OnBnClickedOpengame()
 {
+#if 1 // 获取游戏标题;
+	HWND hProWnd = GAssist::GetProHwnd(GAssist::FindProcess(_T("Game.exe")));
+	//HWND hProWnd = GAssist::GetProHwnd(5824);
+	TCHAR szWinText[MAX_PATH] = {0};
+	::GetWindowText(hProWnd, szWinText, MAX_PATH);
+
+	RECT rc = {0,0,500,500};
+	HBITMAP hb = GAssist::CopyDC2Bitmap(hProWnd, &rc);
+	GAssist::SaveBitmap(hb, "D:\\1.bmp");
+	//GAssist::SaveHwndToBmpFile(hProWnd, "D:\\2.bmp");
+	return;
+#endif
+
 	// TODO: 在此添加控件通知处理程序代码
 	if ( !PathFileExists(GAssist::g_szGamePath) )
 	{
@@ -163,7 +176,8 @@ void CGameAssistDlg::OnBnClickedOpengame()
 	}
 
 	// 设置辅助程序工作目录为游戏目录;
-	SetCurrentDirectory(_T("E:\\dhsh\\shdata\\"));
+	//SetCurrentDirectory(_T("E:\\dhsh\\shdata\\"));
+	SetCurrentDirectory(_T("D:\\tools\\dhsh\\shdata\\"));
 #if 1
 	ShellExecute(NULL, "open", GAssist::g_szGamePath, NULL, NULL, SW_SHOWNORMAL);//SW_HIDE无用,因为会自动结;
 	Sleep(500); // Main.exe设置了陷阱(自己再开启了一个进程,结束上一个进程),需要等5秒;
@@ -249,60 +263,33 @@ void CGameAssistDlg::OnBnClickedOpengame()
 					TCHAR szLogMsg[MAX_PATH] = {0};
 					_stprintf_s(szLogMsg, _T("窗口标题:%s, [%d,%d, %d,%d], width=%d, height=%d\n"), szName, rc.top, rc.left, rc.right, rc.bottom, rc.Width(), rc.Height());
 					OutputDebugString(szLogMsg);
-#if 0	// 800x600
-					// 发送按钮消息;进入游戏;
-					::SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(585, 116));
-					::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(585, 116));
-
-					// 发送按钮消息;下一步;
-					::SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(536, 481));
-					::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(536, 481));
-
-					// 发送按钮消息;电信一区;
-					::SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(229, 342));
-					::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(229, 342));
-
-					// 发送按钮消息;忘忧谷;
-					::SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(335, 244));
-					::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(335, 244));
-
-					// 发送按钮消息;下一步;
-					::SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(559, 516));
-					::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(559, 516));
-#endif
-
-#if 1	// 640x480
-					// 发送按钮消息;进入游戏;
-					::SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(440, 75));
-					::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(440, 75));
-
-					// 发送按钮消息;下一步;
-					::SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(468, 454));
-					::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(468, 454));
-
-					// 发送按钮消息;电信一区;
-					::SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(165, 241));
-					::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(165, 241));
-
-					// 发送按钮消息;忘忧谷;
-					::SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(289, 195));
-					::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(289, 195));
-
-					// 发送按钮消息;下一步;
-					::SendMessage(hwnd, WM_LBUTTONDOWN, 0, MAKELPARAM(494, 469));
-					::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(494, 469));
-#endif
-
-#if 0
-					// 发送按钮消息;
-					::SendMessage(hwnd, WM_LBUTTONDBLCLK, 0, MAKELPARAM(585, 116));
-
-					// 发送按钮消息;
-					::SendMessage(hwnd, WM_LBUTTONDBLCLK, 0, MAKELPARAM(536, 481));
-
-					// 发送按钮消息;
-					::SendMessage(hwnd, WM_LBUTTONDBLCLK, 0, MAKELPARAM(559, 516));
-#endif
+					if ( 1 )
+					{ // 800x600
+						// 发送按钮消息;进入游戏;
+						GAssist::MouseClick(hwnd, 585, 116);
+						// 发送按钮消息;下一步;
+						GAssist::MouseClick(hwnd, 536, 481);
+						// 发送按钮消息;电信一区;
+						GAssist::MouseClick(hwnd, 229, 342);
+						// 发送按钮消息;忘忧谷;
+						GAssist::MouseClick(hwnd, 335, 244);
+						// 发送按钮消息;下一步;
+						GAssist::MouseClick(hwnd, 559, 516);
+					}
+					else
+					{
+						// 640x480
+						// 发送按钮消息;进入游戏;
+						GAssist::MouseClick(hwnd, 440, 75);
+						// 发送按钮消息;下一步;
+						GAssist::MouseClick(hwnd, 468, 454);
+						// 发送按钮消息;电信一区;
+						GAssist::MouseClick(hwnd, 165, 241);
+						// 发送按钮消息;忘忧谷;
+						GAssist::MouseClick(hwnd, 289, 195);
+						// 发送按钮消息;下一步;
+						GAssist::MouseClick(hwnd, 494, 469);
+					}
 				}
 			}
 		}