Bladeren bron

游戏辅助

sat23 5 jaren geleden
bovenliggende
commit
0f877f36ae

+ 206 - 0
GameAssist/Game.CT

@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="utf-8"?>
+<CheatTable CheatEngineTableVersion="29">
+  <CheatEntries>
+    <CheatEntry>
+      <ID>0</ID>
+      <Description>"一级基址-窗口标题"</Description>
+      <LastState RealAddress="009CAF08"/>
+      <VariableType>String</VariableType>
+      <Length>128</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>Game.exe+5CAF08</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>14</ID>
+      <Description>"二级基址-窗口标题"</Description>
+      <LastState RealAddress="0019FD48"/>
+      <VariableType>String</VariableType>
+      <Length>210</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>0019FD48</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>30</ID>
+      <Description>"一级基址 - 账号"</Description>
+      <LastState RealAddress="009F225C"/>
+      <VariableType>String</VariableType>
+      <Length>64</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>Game.exe+5F225C</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>1</ID>
+      <Description>"一级基址-角色名称"</Description>
+      <LastState RealAddress="009F2290"/>
+      <VariableType>String</VariableType>
+      <Length>20</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>Game.exe+5F2290</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>28</ID>
+      <Description>"一级基址 - 电一"</Description>
+      <LastState RealAddress="009F22A8"/>
+      <VariableType>String</VariableType>
+      <Length>14</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>Game.exe+5F22A8</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>29</ID>
+      <Description>"一级基址 - 忘忧谷"</Description>
+      <LastState RealAddress="009F22C8"/>
+      <VariableType>String</VariableType>
+      <Length>9</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>Game.exe+5F22C8</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>15</ID>
+      <Description>"一级基址 - 召唤兽名称"</Description>
+      <LastState RealAddress="009E7A16"/>
+      <VariableType>String</VariableType>
+      <Length>16</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>Game.exe+5E7A16</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>16</ID>
+      <Description>"一级基址 - 我的宠物1"</Description>
+      <LastState RealAddress="009E3F71"/>
+      <VariableType>String</VariableType>
+      <Length>12</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>Game.exe+5E3F71</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>17</ID>
+      <Description>"一级基址 - 我的宠物2"</Description>
+      <LastState RealAddress="009E6D67"/>
+      <VariableType>String</VariableType>
+      <Length>12</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>Game.exe+5E6D67</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>27</ID>
+      <Description>"一级基址 - 我的宠物1"</Description>
+      <LastState RealAddress="009E4F1E"/>
+      <VariableType>String</VariableType>
+      <Length>12</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>Game.exe+5E4F1E</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>18</ID>
+      <Description>"宠物名称1"</Description>
+      <LastState RealAddress="0CF9AD28"/>
+      <VariableType>String</VariableType>
+      <Length>9</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>0CF9AD28</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>19</ID>
+      <Description>"宠物名称2"</Description>
+      <LastState RealAddress="0CEC10C8"/>
+      <VariableType>String</VariableType>
+      <Length>9</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>0CEC10C8</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>20</ID>
+      <Description>"一级基址 - 人物ID"</Description>
+      <LastState Value="0" RealAddress="009E7750"/>
+      <VariableType>4 Bytes</VariableType>
+      <Address>Game.exe+5E7750</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>21</ID>
+      <Description>"二级基址 - 人物ID??"</Description>
+      <LastState Value="692398437" RealAddress="102EB47C"/>
+      <VariableType>4 Bytes</VariableType>
+      <Address>102EB47C</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>22</ID>
+      <Description>"?二级基址 - 人物金钱"</Description>
+      <LastState Value="0" RealAddress="04ACB838"/>
+      <VariableType>4 Bytes</VariableType>
+      <Address>04ACB838</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>25</ID>
+      <Description>"?二级基址 - 人物存银"</Description>
+      <LastState Value="0" RealAddress="04ACB83C"/>
+      <VariableType>4 Bytes</VariableType>
+      <Address>04ACB83C</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>26</ID>
+      <Description>"?二级基址 - 人物交子"</Description>
+      <LastState Value="0" RealAddress="04ACB840"/>
+      <VariableType>4 Bytes</VariableType>
+      <Address>04ACB840</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>31</ID>
+      <Description>"No description"</Description>
+      <LastState RealAddress="194186D1"/>
+      <VariableType>String</VariableType>
+      <Length>9</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>194186D1</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>32</ID>
+      <Description>"No description"</Description>
+      <LastState RealAddress="009E5D06"/>
+      <VariableType>String</VariableType>
+      <Length>9</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>Game.exe+5E5D06</Address>
+    </CheatEntry>
+    <CheatEntry>
+      <ID>33</ID>
+      <Description>"No description"</Description>
+      <LastState RealAddress="009E5AF5"/>
+      <VariableType>String</VariableType>
+      <Length>9</Length>
+      <Unicode>0</Unicode>
+      <CodePage>1</CodePage>
+      <ZeroTerminate>1</ZeroTerminate>
+      <Address>Game.exe+5E5AF5</Address>
+    </CheatEntry>
+  </CheatEntries>
+  <UserdefinedSymbols/>
+</CheatTable>

BIN
GameAssist/GameAssist-08.ncb


+ 20 - 0
GameAssist/GameAssist-08.sln

@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameAssist", "GameAssist\GameAssist.vcproj", "{A83AED38-393A-4928-BB07-3D5D03CDB242}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{A83AED38-393A-4928-BB07-3D5D03CDB242}.Debug|Win32.ActiveCfg = Debug|Win32
+		{A83AED38-393A-4928-BB07-3D5D03CDB242}.Debug|Win32.Build.0 = Debug|Win32
+		{A83AED38-393A-4928-BB07-3D5D03CDB242}.Release|Win32.ActiveCfg = Release|Win32
+		{A83AED38-393A-4928-BB07-3D5D03CDB242}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 25 - 0
GameAssist/GameAssist.sln

@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30406.217
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameAssist", "GameAssist\GameAssist.vcxproj", "{A83AED38-393A-4928-BB07-3D5D03CDB242}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{A83AED38-393A-4928-BB07-3D5D03CDB242}.Debug|Win32.ActiveCfg = Debug|Win32
+		{A83AED38-393A-4928-BB07-3D5D03CDB242}.Debug|Win32.Build.0 = Debug|Win32
+		{A83AED38-393A-4928-BB07-3D5D03CDB242}.Release|Win32.ActiveCfg = Release|Win32
+		{A83AED38-393A-4928-BB07-3D5D03CDB242}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {E02182A9-A999-4F47-9970-E7B73FC09432}
+	EndGlobalSection
+EndGlobal

+ 463 - 0
GameAssist/GameAssist/Assist.cpp

@@ -0,0 +1,463 @@
+#include "StdAfx.h"
+#include "Assist.h"
+
+#include <D3D9.h>
+//#include <D3dx9tex.h>
+//#pragma comment(lib, "D3dx9.lib")
+
+// #pragma comment(lib, "d3d11.lib")
+// #pragma comment(lib, "dxgi.lib")
+
+namespace GAssist
+{
+	// 根据路径名查找进程,返回进程ID;
+	DWORD FindProcess(IN LPCSTR lpProName)
+	{
+		DWORD dwProcessID = 0;
+		PROCESSENTRY32 pe32 = { 0 };
+
+		HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+		if (hProcessSnap == NULL)
+		{
+			return 0;
+		}
+		pe32.dwSize = sizeof(PROCESSENTRY32);
+
+		if (Process32First(hProcessSnap, &pe32)) {
+			do {
+				if (_tcscmp(lpProName, pe32.szExeFile) == 0) {
+					dwProcessID = pe32.th32ProcessID;
+					break;
+				}
+			} while (Process32Next(hProcessSnap, &pe32));
+		}
+		CloseHandle(hProcessSnap);
+
+		return dwProcessID;
+	}
+
+	HWND GetProHwnd(DWORD dwProcessId)
+	{
+		DWORD dwPID = 0;
+		HWND hwndRet = NULL;
+		TCHAR szName[MAX_PATH] = {0};
+		TCHAR szClass[MAX_PATH] = {0};
+		TCHAR szLogMsg[MAX_PATH] = {0};
+		// 取得第一个窗口句柄
+		HWND hwndWindow = ::GetTopWindow(NULL);
+		// 遍历出结果窗口;
+		while (hwndWindow) {
+			dwPID = 0;
+			// 通过窗口句柄取得进程ID
+			DWORD dwTheardID = ::GetWindowThreadProcessId(hwndWindow, &dwPID);
+			if (dwTheardID != 0) {
+				// 判断和参数传入的进程ID是否相等
+				if (dwPID == dwProcessId) {
+					// 进程ID相等,则记录窗口句柄
+					hwndRet = hwndWindow;
+					//break;	//存在Bug:有些进程有多个分离的窗口;
+					::GetWindowText(hwndRet, szName, sizeof(szName) / sizeof(TCHAR));
+					::GetClassName(hwndRet, szClass, sizeof(szClass) / sizeof(TCHAR)); // 窗口类
+					//TRACE3(_T("%s %s %s"), szClass, szName, "\n");
+					_stprintf_s(szLogMsg, _T("类名:%s, 窗口名:%s,窗口地址:%p \n"), szClass, szName, hwndRet);
+					OutputDebugString(szLogMsg);
+					if ( _tcsstr(szName, _T("大话水浒")) )
+						break;
+				}
+			}
+			// 取得下一个窗口句柄
+			hwndWindow = ::GetNextWindow(hwndWindow, GW_HWNDNEXT);
+		}
+
+		
+		// 上面取得的窗口,不一定是最上层的窗口,需要通过GetParent获取最顶层窗口
+		HWND hwndWindowParent = 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");
+			_stprintf_s(szLogMsg, _T("类名:%s, 窗口名:%s,窗口地址:%p \n"), szClass, szName, hwndRet);
+			OutputDebugString(szLogMsg);
+
+			hwndWindowParent = ::GetParent(hwndRet);
+			if (hwndWindowParent == NULL) {
+				break;
+			}
+			hwndRet = hwndWindowParent;
+		}
+		// 返回窗口句柄
+		return hwndRet;
+	}
+
+	std::vector<GameHwnd> g_vtGameHwnd;
+	BOOL CALLBACK EnumChildWindowCallBack(HWND hWnd, LPARAM lParam)  
+	{  
+		DWORD dwPid = 0;  
+		GetWindowThreadProcessId(hWnd, &dwPid); // 获得找到窗口所属的进程   
+		if (dwPid == lParam) // 判断是否是目标进程的窗口   
+		{  
+			TCHAR szName[MAX_PATH] = {0};
+			TCHAR szClass[MAX_PATH] = {0};
+			TCHAR szLogMsg[MAX_PATH] = {0};
+			::GetWindowText(hWnd, szName, sizeof(szName) / sizeof(TCHAR));
+			::GetClassName(hWnd, szClass, sizeof(szClass) / sizeof(TCHAR)); // 窗口类
+			DWORD dwId = ::GetDlgCtrlID(hWnd);
+			//TRACE3(_T("%s %s %s"), szClass, szName, "\n");
+			_stprintf_s(szLogMsg, _T("类名:%s, 窗口名:%s,ID:%d,窗口地址:%p \n"), szClass, szName, dwId, hWnd);
+			OutputDebugString(szLogMsg);
+
+			GameHwnd ghwnd;
+			ghwnd.dwId = dwId;
+			ghwnd.hwnd = hWnd;
+			ghwnd.strWinText = szName;
+			ghwnd.strClassName = szClass;
+			g_vtGameHwnd.push_back(ghwnd);
+
+			_tprintf_s(_T("0x%08X    ") , hWnd); // 输出窗口信息   
+			TCHAR buf[MAX_PATH];  
+			SendMessage(hWnd, WM_GETTEXT, MAX_PATH, (LPARAM)buf);  
+			_tprintf_s(_T("%s/n") , buf);
+			EnumChildWindows(hWnd, EnumChildWindowCallBack, lParam);    // 递归查找子窗口   
+		}  
+		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;
+		
+		::SetForegroundWindow(hwnd); // 窗口前置才能单击成功;
+		::PostMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
+		::PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
+		OutputDebugString(_T("-------------------发送MouseClick\n"));
+		Sleep(200);
+	}
+
+	void MouseClick(HWND hwnd, unsigned int x, unsigned int y)
+	{
+		if ( !IsWindow(hwnd) )
+			return;
+
+		::SendMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
+		::SendMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(x, y));
+		Sleep(200);
+	}
+
+	void MouseMove(HWND hwnd, POINT pt)
+	{
+		if ( !IsWindow(hwnd) )
+			return;
+
+		::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
+		Sleep(200);
+	}
+
+	void MouseMove(HWND hwnd, POINT ptStart, POINT ptEnd)
+	{
+		if ( !IsWindow(hwnd) )
+			return;
+
+		//::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, lparam);
+		::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(ptStart.x, ptStart.y));
+		Sleep(200);
+
+#if 1
+		// 计算个中间点;
+		POINT ptMid = { (ptStart.x + ptEnd.x) / 2, (ptStart.y + ptEnd.y) / 2};
+		::SendMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(ptMid.x, ptMid.y));
+		Sleep(200);
+#endif
+
+		//::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, lparam);
+		::SendMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(ptEnd.x, ptEnd.y));
+		Sleep(200);
+	}
+
+	// 最后一步直接单击;
+	void MouseMoveEx(HWND hwnd, POINT ptStart, POINT ptEnd)
+	{
+		if ( !IsWindow(hwnd) )
+			return;
+
+		//::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, lparam);
+		::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(ptStart.x, ptStart.y));
+		Sleep(200);
+
+#if 1
+		// 计算个中间点;
+		POINT ptMid = { (ptStart.x + ptEnd.x) / 2, (ptStart.y + ptEnd.y) / 2};
+		::SendMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(ptMid.x, ptMid.y));
+		Sleep(200);
+#endif
+
+		//::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, lparam);
+		::SendMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(ptEnd.x, ptEnd.y));
+		Sleep(200);
+		MouseClick(hwnd, ptEnd);
+	}
+
+	void DragMouse(HWND hwnd, POINT ptStart, POINT ptEnd)
+	{
+		if ( !IsWindow(hwnd) )
+			return;
+		
+#if 0
+		MouseClick(hwnd, ptStart);
+		// 按下鼠标左键;
+		::SendMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(ptStart.x, ptStart.y));
+		//Sleep(200);
+
+		::SendMessage(hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(ptEnd.x, ptEnd.y));
+		Sleep(200);
+#else
+		::PostMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(ptStart.x, ptStart.y));
+
+		::PostMessage(hwnd, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(ptEnd.x, ptEnd.y));
+
+		::PostMessage(hwnd, WM_LBUTTONUP, 0, MAKELPARAM(ptEnd.x, ptEnd.y));
+#endif
+	}
+
+	// 截图;
+	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); 
+	}  
+
+
+// 	#include <D3D9.h>
+// 	#include <D3dx9tex.h>
+// 	#pragma comment(lib, "D3dx9.lib")
+	//#include <d3d9helper>
+	BOOL ScreenShot(LPDIRECT3DDEVICE9 lpDevice, HWND hWnd, TCHAR* fileName)
+	{
+		HRESULT hr;
+		// Get adapter display mode
+		D3DDISPLAYMODE mode;
+		if (FAILED(hr = lpDevice->GetDisplayMode(0, &mode)))
+			return hr;
+
+		// Create the surface to hold the screen image data
+		LPDIRECT3DSURFACE9 surf;
+		if (FAILED(hr = lpDevice->CreateOffscreenPlainSurface(mode.Width,
+			mode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL))) //注意第四个参数不能是D3DPOOL_DEFAULT
+		{
+			return hr;
+		}
+
+		// Get the screen data
+		if (FAILED(hr = lpDevice->GetFrontBufferData(0, surf)))
+		{
+			surf->Release();
+			return hr;
+		}
+
+		// area to capture
+		RECT* rect = NULL;
+
+		WINDOWINFO windowInfo;
+		windowInfo.cbSize = sizeof(WINDOWINFO);
+
+		if (hWnd) // capture window
+		{
+			GetWindowInfo(hWnd, &windowInfo);
+			rect = &windowInfo.rcWindow;
+		}
+
+		// Save the screen date to file
+		//hr = D3DXSaveSurfaceToFile(fileName, D3DXIFF_BMP, surf, NULL, rect);
+
+		surf->Release();
+
+		return hr;
+	}
+
+
+}

+ 67 - 0
GameAssist/GameAssist/Assist.h

@@ -0,0 +1,67 @@
+#ifndef __ASSIST__
+#define __ASSIST__
+
+#pragma once
+
+
+namespace GAssist
+{
+	//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);
+
+	typedef struct __GAME_HWNINFO__{
+		DWORD			dwId;				// 控件id;
+		std::string		strWinText;			// 控件文本;
+		std::string		strClassName;		// 控件类名;
+		HWND			hwnd;				// 控件句柄;
+	}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);
+	// 移动鼠标;
+	extern void MouseMove(HWND hwnd, POINT pt);
+	extern void MouseMove(HWND hwnd, POINT ptStart, POINT ptEnd);
+	extern void MouseMoveEx(HWND hwnd, POINT ptStart, POINT ptEnd);
+	// 拖动鼠标;
+	extern void DragMouse(HWND hwnd, POINT ptStart, POINT ptEnd);
+	// 截图;
+	HBITMAP CopyDC2Bitmap(HWND hWnd, LPRECT lpRect);
+	// 保存图片;
+	BOOL SaveBitmap(HBITMAP hBitmpa, std::string strSavePath);
+	void SaveHwndToBmpFile(HWND hWnd, LPCTSTR lpszPath);
+};
+
+#endif // __ASSIST__

+ 13 - 0
GameAssist/GameAssist/Assist.ini

@@ -0,0 +1,13 @@
+[Assist]
+;·¾¶
+GamePath=D:\tools\dhsh\shdata\
+GameApp=D:\tools\dhsh\shdata\Main.exe
+
+[WinInfo]
+;E:\dhsh\shdata\save\config.ini
+;С´°¿Ú640x480
+SmallWnd=808,636
+;´ó´°¿Ú800x600
+LargeWnd=
+;È«ÆÁ
+FullWnd=

+ 427 - 0
GameAssist/GameAssist/CVideoCapture.cpp

@@ -0,0 +1,427 @@
+#include "stdafx.h"
+#include "CVideoCapture.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <process.h>
+#include <d3d11.h>
+#include <dxgi1_2.h>
+
+#pragma comment(lib, "d3d11")
+#pragma comment(lib, "dxgi")
+
+#ifndef _VIDEO_SOURCE_
+#define _VIDEO_SOURCE_
+typedef struct tDXGIVideoSource
+{
+	int		m_nLeft;//捕获区域坐标值-左
+	int		m_nTop;//捕获区域坐标值-上
+	int		m_nWidth;//捕获区域-宽度
+	int		m_nHeight;//捕获区域-高度
+
+	bool					m_bCaptureCursor;//是否抓取光标
+	bool					m_bActive;//是否激活,即是否获取到视频帧
+	HANDLE					m_hCaptureThread;//捕获线程句柄
+	HANDLE					m_hStopSignal;//线程停止信号
+
+	CRITICAL_SECTION		m_csMemLock;//数据访问互斥锁
+	void* m_memRawBuffer;//RGB数据存放缓冲区
+	int						m_nMemSize;//RGB数据缓冲区大小
+
+	ID3D11Device* m_hDevice;//设备对象
+	ID3D11DeviceContext* m_hContext;//设备上下文
+	IDXGIOutputDuplication* m_hDeskDupl;//桌面对象
+	DXGI_OUTPUT_DESC        m_dxgiOutDesc;//桌面对象描述-保存了桌面分辨率等信息
+
+	LPVideoDataRealCallback m_pVideoDataRealCalBack;//实时捕获数据回调函数
+	void* m_pVideoDataRealCalBackUser;//实时捕获数据用户接受对象
+}DXGIVideoSource, * LPDXGIVideoSource;
+#endif
+
+//申请一个视频源对象
+void DXGIAllocVideoResource(LPDXGIVideoSource* pSource);
+//释放视频源对象
+void DXGIReleaseVideoResource(LPDXGIVideoSource pSource);
+//开始捕获视频数据
+bool DXGIStartVideoCapture(LPDXGIVideoSource pSource);
+//停止捕获视频数据
+void DXGIStopVideoCapture(LPDXGIVideoSource pSource);
+//视频数据循环捕获线程
+DWORD WINAPI DXGIOnVideoCaptureThread(LPVOID param);
+//视频数据捕获函数
+bool DXGIDoVideoCapture(LPDXGIVideoSource pSource);
+//视频数据捕获函数
+bool DXGIProcessVideoCaptureData(LPDXGIVideoSource pSource);
+
+const IID IID_IDXGIDevice = { 0x54ec77fa, 0x1377, 0x44e6, { 0x8c, 0x32, 0x88, 0xfd, 0x5f, 0x44, 0xc8, 0x4c } };
+const IID IID_IDXGIAdapter = { 0x2411e7e1, 0x12ac, 0x4ccf, { 0xbd, 0x14, 0x97, 0x98, 0xe8, 0x53, 0x4d, 0xc0 } };
+const IID IID_IDXGIOutput1 = { 0x00cddea8, 0x939b, 0x4b83, { 0xa3, 0x40, 0xa6, 0x85, 0x22, 0x66, 0x66, 0xcc } };
+const IID IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } };
+const IID IID_IDXGISurface = { 0xcafcb56c, 0x6ac3, 0x4889, { 0xbf, 0x47, 0x9e, 0x23, 0xbb, 0xd2, 0x60, 0xec } };
+//#define RESET_OBJECT(A) {if (A) A->lpVtbl->Release(A); A = NULL;}
+#define RESET_OBJECT(A) {if (A) A->Release(); A = NULL;}
+
+//申请一个视频源对象
+void DXGIAllocVideoResource(LPDXGIVideoSource* ppSource)
+{
+	//参数初始化
+	*ppSource = (LPDXGIVideoSource)malloc(sizeof(DXGIVideoSource));
+	((LPDXGIVideoSource)*ppSource)->m_bActive = false;
+	((LPDXGIVideoSource)*ppSource)->m_bCaptureCursor = false;
+	((LPDXGIVideoSource)*ppSource)->m_hCaptureThread = NULL;
+	((LPDXGIVideoSource)*ppSource)->m_hStopSignal = CreateEvent(NULL, TRUE, FALSE, NULL);
+	((LPDXGIVideoSource)*ppSource)->m_memRawBuffer = NULL;
+	((LPDXGIVideoSource)*ppSource)->m_pVideoDataRealCalBack = NULL;
+	((LPDXGIVideoSource)*ppSource)->m_pVideoDataRealCalBackUser = NULL;
+	InitializeCriticalSection(&((LPDXGIVideoSource)*ppSource)->m_csMemLock);
+
+	HRESULT hr = S_OK;
+	//Direct3D驱动类型
+	D3D_DRIVER_TYPE DriverTypes[] =
+	{
+		D3D_DRIVER_TYPE_HARDWARE, //硬件驱动
+		D3D_DRIVER_TYPE_WARP,//软件驱动-性能高
+		D3D_DRIVER_TYPE_REFERENCE, //软件驱动-精度高,速度慢
+		D3D_DRIVER_TYPE_SOFTWARE,//软件驱动-性能低
+	};
+
+	UINT NumDriverTypes = ARRAYSIZE(DriverTypes);
+	D3D_FEATURE_LEVEL FeatureLevels[] =
+	{
+		D3D_FEATURE_LEVEL_11_0,
+		D3D_FEATURE_LEVEL_10_1,
+		D3D_FEATURE_LEVEL_10_0,
+		D3D_FEATURE_LEVEL_9_1
+	};
+
+	//初始化D3D设备-m_hDevice
+	UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);
+	D3D_FEATURE_LEVEL FeatureLevel;
+	for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex)
+	{
+		hr = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, 0, FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION, &((LPDXGIVideoSource)*ppSource)->m_hDevice, &FeatureLevel, &((LPDXGIVideoSource)*ppSource)->m_hContext);
+		if (SUCCEEDED(hr))
+		{
+			break;
+		}
+	}
+
+	if (FAILED(hr))
+	{
+		goto exit;
+	}
+
+	IDXGIDevice* hDxgiDevice = NULL;
+	hr = ((LPDXGIVideoSource)*ppSource)->m_hDevice->QueryInterface(IID_IDXGIDevice/*__uuidof(IDXGIDevice)*/, (void**)(&hDxgiDevice));
+	if (FAILED(hr))
+	{
+		goto exit;
+	}
+
+	//获取桌面对象描述符-m_dxgiOutDesc,主要是获取桌面分辨率大小
+	IDXGIAdapter* hDxgiAdapter = NULL;
+	hr = hDxgiDevice->GetParent(IID_IDXGIAdapter, (void**)(&hDxgiAdapter));
+	RESET_OBJECT(hDxgiDevice);
+	if (FAILED(hr))
+	{
+		goto exit;
+	}
+
+	INT nOutput = 0;
+	IDXGIOutput* hDxgiOutput = NULL;
+	hr = hDxgiAdapter->EnumOutputs(nOutput, &hDxgiOutput);
+	RESET_OBJECT(hDxgiAdapter);
+	if (FAILED(hr))
+	{
+		goto exit;
+	}
+
+	hDxgiOutput->GetDesc(&((LPDXGIVideoSource)*ppSource)->m_dxgiOutDesc);
+
+	IDXGIOutput1* hDxgiOutput1 = NULL;
+	hr = hDxgiOutput->QueryInterface(IID_IDXGIOutput1, (void**)(&hDxgiOutput1));
+	RESET_OBJECT(hDxgiOutput);
+	if (FAILED(hr))
+	{
+		goto exit;
+	}
+
+	hr = hDxgiOutput1->DuplicateOutput((IUnknown*)((LPDXGIVideoSource)*ppSource)->m_hDevice, (IDXGIOutputDuplication**)&((LPDXGIVideoSource)*ppSource)->m_hDeskDupl);
+	RESET_OBJECT(hDxgiOutput1);
+	if (FAILED(hr))
+	{
+		goto exit;
+	}
+
+	return;
+exit:
+	DXGIReleaseVideoResource((LPDXGIVideoSource)*ppSource);
+	*ppSource = NULL;
+}
+
+//释放视频源对象
+void DXGIReleaseVideoResource(LPDXGIVideoSource pSource)
+{
+	RESET_OBJECT(pSource->m_hDeskDupl);
+	RESET_OBJECT(pSource->m_hContext);
+	RESET_OBJECT(pSource->m_hDevice);
+	free(((LPDXGIVideoSource)pSource)->m_memRawBuffer);
+	((LPDXGIVideoSource)pSource)->m_memRawBuffer = NULL;
+	DeleteCriticalSection(&((LPDXGIVideoSource)pSource)->m_csMemLock);
+	free(pSource);
+	pSource = NULL;
+}
+
+//开始捕获视频数据
+bool DXGIStartVideoCapture(LPDXGIVideoSource pSource)
+{
+	// 释放之前申请的的存放图像的缓存
+	free(((LPDXGIVideoSource)pSource)->m_memRawBuffer);
+	((LPDXGIVideoSource)pSource)->m_memRawBuffer = NULL;
+	((LPDXGIVideoSource)pSource)->m_nMemSize = 0;
+
+	//计算所需存放图像的缓存大小
+	((LPDXGIVideoSource)pSource)->m_nMemSize = pSource->m_nWidth * pSource->m_nHeight * 4;//获取的图像位图深度32位,所以是*4
+	((LPDXGIVideoSource)pSource)->m_memRawBuffer = (char*)malloc(((LPDXGIVideoSource)pSource)->m_nMemSize);
+	memset(((LPDXGIVideoSource)pSource)->m_memRawBuffer, 0, ((LPDXGIVideoSource)pSource)->m_nMemSize);
+
+	//创建捕获图像的线程
+	unsigned int dwThreadId;
+	pSource->m_hCaptureThread = (HANDLE)_beginthreadex(NULL,
+		0,
+		(_beginthreadex_proc_type)&DXGIOnVideoCaptureThread,
+		pSource,
+		THREAD_PRIORITY_NORMAL,
+		&dwThreadId);
+	if (!pSource->m_hCaptureThread)
+		return false;
+
+	return true;
+}
+
+//停止捕获视频数据
+void DXGIStopVideoCapture(LPDXGIVideoSource pSource)
+{
+	//发送线程停止工作信号
+	SetEvent(pSource->m_hStopSignal);
+	//等待线程安全退出
+	if (pSource->m_bActive)
+	{
+		WaitForSingleObject(pSource->m_hCaptureThread, INFINITE);
+	}
+
+	pSource->m_nMemSize = 0;
+}
+
+//视频数据循环捕获线程
+DWORD WINAPI DXGIOnVideoCaptureThread(LPVOID param)
+{
+	LPDXGIVideoSource pSource = (LPDXGIVideoSource)param;
+	DXGIDoVideoCapture(pSource);
+	_endthreadex(0);
+	return 0;
+}
+
+//视频数据循环捕获线程-处理线程
+bool DXGIDoVideoCapture(LPDXGIVideoSource pSource)
+{
+	DWORD        dwTimeout = 1;
+	DWORD dwStartTickCount = GetTickCount();
+
+	// 等待超时进入下一次图像数据获取
+	while (WaitForSingleObject(pSource->m_hStopSignal, dwTimeout) == WAIT_TIMEOUT)
+	{
+		if (DXGIProcessVideoCaptureData(pSource))
+		{
+			if (((LPDXGIVideoSource)pSource)->m_bActive)
+			{
+				//获取图像成功,回调数据给应用层用户处理
+				if (pSource->m_pVideoDataRealCalBack)
+				{
+					pSource->m_pVideoDataRealCalBack((LPBYTE)pSource->m_memRawBuffer, pSource->m_nMemSize, pSource->m_nWidth, pSource->m_nHeight, pSource->m_pVideoDataRealCalBackUser);
+				}
+			}
+			else
+			{
+				// 因为第一帧是黑屏。需要忽略,具体原因???
+				((LPDXGIVideoSource)pSource)->m_bActive = true;
+			}
+		}
+	}
+
+	//关闭信号
+	CloseHandle(pSource->m_hStopSignal);
+	pSource->m_hStopSignal = NULL;
+	//关闭线程句柄
+	CloseHandle(pSource->m_hCaptureThread);
+	pSource->m_hCaptureThread = NULL;
+	((LPDXGIVideoSource)pSource)->m_bActive = false;
+	return true;
+}
+
+//
+//将桌面挂到这个进程中
+//
+bool AttatchToThread(VOID)
+{
+	HDESK hOldDesktop = GetThreadDesktop(GetCurrentThreadId());
+	HDESK hCurrentDesktop = OpenInputDesktop(0, FALSE, GENERIC_ALL);
+	if (!hCurrentDesktop)
+	{
+		return false;
+	}
+
+	bool bDesktopAttached = SetThreadDesktop(hCurrentDesktop);
+	CloseDesktop(hOldDesktop);
+	CloseDesktop(hCurrentDesktop);
+	hCurrentDesktop = NULL;
+
+	return bDesktopAttached;
+}
+
+//视频数据捕获函数
+bool DXGIProcessVideoCaptureData(LPDXGIVideoSource pSource)
+{
+	//将桌面挂到这个进程中
+	if (!AttatchToThread())
+	{
+		return false;
+	}
+
+	///截取屏幕数据
+	IDXGIResource* hDesktopResource = NULL;
+	DXGI_OUTDUPL_FRAME_INFO FrameInfo;
+	HRESULT hr = pSource->m_hDeskDupl->AcquireNextFrame(500, &FrameInfo, &hDesktopResource);
+	if (FAILED(hr))
+	{
+		//
+		// 在一些win10的系统上,如果桌面没有变化的情况下,
+		// 这里会发生超时现象,但是这并不是发生了错误,而是系统优化了刷新动作导致的。
+		// 所以,这里没必要返回FALSE,返回不带任何数据的TRUE即可
+		//
+		return true;
+	}
+
+	//获取纹理2D
+	ID3D11Texture2D* hAcquiredDesktopImage = NULL;
+	hr = hDesktopResource->QueryInterface(IID_ID3D11Texture2D, (void**)(&hAcquiredDesktopImage));
+	RESET_OBJECT(hDesktopResource);
+	if (FAILED(hr))
+	{
+		return false;
+	}
+
+	D3D11_TEXTURE2D_DESC frameDescriptor;
+	hAcquiredDesktopImage->GetDesc(&frameDescriptor);
+
+	//创建一个新的2D纹理对象,用于把 hAcquiredDesktopImage的数据copy进去
+	ID3D11Texture2D* hNewDesktopImage = NULL;
+	frameDescriptor.Usage = D3D11_USAGE_STAGING;
+	frameDescriptor.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+	frameDescriptor.BindFlags = 0;
+	frameDescriptor.MiscFlags = 0;
+	frameDescriptor.MipLevels = 1;
+	frameDescriptor.ArraySize = 1;
+	frameDescriptor.SampleDesc.Count = 1;
+	hr = pSource->m_hDevice->CreateTexture2D( &frameDescriptor, NULL, &hNewDesktopImage);
+	if (FAILED(hr))
+	{
+		RESET_OBJECT(hAcquiredDesktopImage);
+		pSource->m_hDeskDupl->ReleaseFrame();
+		return false;
+	}
+
+	///获取整个帧的数据 
+	pSource->m_hContext->CopyResource((ID3D11Resource*)hNewDesktopImage, (ID3D11Resource*)hAcquiredDesktopImage);
+	RESET_OBJECT(hAcquiredDesktopImage);
+	pSource->m_hDeskDupl->ReleaseFrame();
+
+	// 获取这个2D纹理对象的表面
+	IDXGISurface* hStagingSurf = NULL;
+	hr = hNewDesktopImage->QueryInterface(IID_IDXGISurface, (void**)(&hStagingSurf));
+	RESET_OBJECT(hNewDesktopImage);
+	if (FAILED(hr))
+	{
+		return false;
+	}
+
+	//映射锁定表面,从而获取表面的数据地址
+	//这个时候 mappedRect.pBits 指向的内存就是原始的图像数据, 因为DXGI固定为 32位深度色
+	//mappedRect.pBits 指向的就是 BGRA 元数组
+	DXGI_MAPPED_RECT mappedRect;
+	hr = hStagingSurf->Map( &mappedRect, DXGI_MAP_READ);
+	if (SUCCEEDED(hr))
+	{
+		WORD bitsPerPixel = 4;	// 每个像素点数据占4个字节 - RGBA
+		int iWidth = pSource->m_dxgiOutDesc.DesktopCoordinates.right - pSource->m_dxgiOutDesc.DesktopCoordinates.left;
+		int iHeight = pSource->m_dxgiOutDesc.DesktopCoordinates.bottom - pSource->m_dxgiOutDesc.DesktopCoordinates.top;
+		int iCopyDataLength = (pSource->m_nWidth * 32 + 31) / 32 * bitsPerPixel;
+		int j = 0;
+		for (int h = pSource->m_nTop; h < pSource->m_nTop + pSource->m_nHeight; h++)
+		{
+			int iSrcOffset = (h * iWidth + pSource->m_nLeft) * bitsPerPixel;
+			BYTE* pSrc = mappedRect.pBits + iSrcOffset;
+			int iDesOffset = (pSource->m_nWidth * 32 + 31) / 32 * j * bitsPerPixel;
+			BYTE* pDes = (BYTE*)pSource->m_memRawBuffer + iDesOffset;
+			memcpy(pDes, pSrc, iCopyDataLength);
+			j++;
+		}
+
+		hStagingSurf->Unmap();
+	}
+
+	RESET_OBJECT(hStagingSurf);
+	return SUCCEEDED(hr);
+}
+
+//设置图像数据回调函数
+void DXGISetVideoCaptureDataRealCallback(LPDXGIVideoSource pSource, LPVideoDataRealCallback pVideoDataRealCalBack, void* pUser)
+{
+	pSource->m_pVideoDataRealCalBack = pVideoDataRealCalBack;
+	pSource->m_pVideoDataRealCalBackUser = pUser;
+}
+
+
+// DXGI方式,设置视频回调函数,并开始捕获视频数据
+void* DXGI_VideoSourceStartCapture(int left, int top, int width, int height, LPVideoDataRealCallback pCallback, void* pUser)
+{
+	// 申请一个视频数据源
+	LPDXGIVideoSource pSource = NULL;
+	DXGIAllocVideoResource(&pSource);
+
+	//保存捕获区域参数
+	printf("录制区域left=%d,top=%d,w=%d,h=%d\n", left, top, width, height);
+	pSource->m_nLeft = left;
+	pSource->m_nTop = top;
+	pSource->m_nWidth = width;
+	pSource->m_nHeight = height;
+
+	//设置图像数据回调函数
+	DXGISetVideoCaptureDataRealCallback(pSource, pCallback, pUser);
+	if (pSource && DXGIStartVideoCapture(pSource))
+	{
+		return pSource;
+	}
+	else
+	{
+		goto exit;
+	}
+
+exit:
+	//释放,释放所有资源
+	DXGIReleaseVideoResource(pSource);
+	pSource = NULL;
+	return pSource;
+}
+
+// 停止视频数据捕获
+bool DXGI_VideoSourceStopCapture(void* pSource)
+{
+	if (pSource == NULL)
+		return true;
+
+	DXGISetVideoCaptureDataRealCallback((LPDXGIVideoSource)pSource, NULL, NULL);
+	DXGIStopVideoCapture((LPDXGIVideoSource)pSource);
+	return true;
+}

+ 21 - 0
GameAssist/GameAssist/CVideoCapture.h

@@ -0,0 +1,21 @@
+#pragma once
+
+//#define CINTERFACE 
+/*
+在c++中以c的方式使用接口时,应当:i->lpVtbl->....,
+但是编译器可能会提示lpVtbl不是相应com接口的成员。
+这是因为在com头文件中有两种定义方式,即c和c++;这两种方式通过 __cplusplus和CINTERFACE来区分。
+*/
+
+#ifndef _VIDEODATA_CALLBACK_
+#define _VIDEODATA_CALLBACK_
+typedef void(*LPVideoDataRealCallback)(unsigned char* pRgbData, int size, int width, int height, void* pContext);
+#endif
+
+// DXGI方式,设置视频回调函数,并开始捕获视频数据
+void* DXGI_VideoSourceStartCapture(int left, int top, int width, int height, LPVideoDataRealCallback pCallback, void* pUser);
+// 停止视频数据捕获
+bool DXGI_VideoSourceStopCapture(void* pSource);
+
+
+

+ 351 - 0
GameAssist/GameAssist/GameAssist.cpp

@@ -0,0 +1,351 @@
+
+// GameAssist.cpp : 定义应用程序的类行为。
+//
+
+#include "stdafx.h"
+#include "GameAssist.h"
+#include "GameAssistDlg.h"
+
+// directx
+#include <Dshow.h>
+#include <strmif.h>
+#pragma comment(lib, "strmiids.lib")
+#define VI_MAX_CAMERAS 20
+// DEFINE_GUID(CLSID_SystemDeviceEnum, 0x62be5d10, 0x60eb, 0x11d0, 0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86);
+// DEFINE_GUID(CLSID_VideoInputDeviceCategory, 0x860bb310, 0x5d01, 0x11d0, 0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86);
+// DEFINE_GUID(IID_ICreateDevEnum, 0x29840822, 0x5b84, 0x11d0, 0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86);
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+//列出硬件设备
+int listDevices(std::vector<std::string>& list)
+{
+	// 初始化COM环境;
+	::CoInitialize(NULL);
+	ICreateDevEnum *pDevEnum = NULL;
+	IEnumMoniker *pEnum = NULL;
+	int deviceCounter = 0;	
+
+	//HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,IID_ICreateDevEnum,reinterpret_cast<void**>(&pDevEnum));
+	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,IID_ICreateDevEnum,(void**)(&pDevEnum));
+	if (SUCCEEDED(hr))
+	{
+		hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEnum, 0);
+		if (hr == S_OK){
+
+			IMoniker *pMoniker = NULL;
+			while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
+			{
+				IPropertyBag *pPropBag;
+				hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,(void**)(&pPropBag));
+
+				if (FAILED(hr)) {
+					pMoniker->Release();
+					continue; // Skip this one, maybe the next one will work.
+				}
+
+				VARIANT varName;
+				VariantInit(&varName);
+				hr = pPropBag->Read(L"Description", &varName, 0);
+				if (FAILED(hr))
+				{
+					hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+				}
+
+				if (SUCCEEDED(hr))
+				{
+					hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+					int count = 0;
+					char tmp[255] = { 0 };
+					while (varName.bstrVal[count] != 0x00 && count < 255)
+					{
+						tmp[count] = (char)varName.bstrVal[count];
+						count++;
+					}
+					list.push_back(tmp);
+				}
+
+				pPropBag->Release();
+				pPropBag = NULL;
+				pMoniker->Release();
+				pMoniker = NULL;
+
+				deviceCounter++;
+			}
+
+			pDevEnum->Release();
+			pDevEnum = NULL;
+			pEnum->Release();
+			pEnum = NULL;
+		}
+	}
+
+	// 释放COM环境;
+	::CoUninitialize();
+
+	return deviceCounter;
+}
+
+#define OUTPUT_PIN       1
+#define OUTPUT_MEDIATYPE 1
+
+char* GuidToString(const GUID &guid)
+{
+	int buf_len=64;
+	char *buf =(char *)malloc(buf_len);
+	_stprintf_s(
+		buf,
+		buf_len,
+		"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+		guid.Data1, guid.Data2, guid.Data3,
+		guid.Data4[0], guid.Data4[1],
+		guid.Data4[2], guid.Data4[3],
+		guid.Data4[4], guid.Data4[5],
+		guid.Data4[6], guid.Data4[7]);
+	//printf("%s\n",buf);
+	return buf;
+}
+
+int DirectShowDemo()
+{
+	// Init COM
+	HRESULT hr=NULL;
+	hr= CoInitialize(NULL);
+	if (FAILED(hr)){
+		printf("Error, Can not init COM.");
+		return -1;
+	}
+	printf("===============Directshow Filters ===============\n");
+	ICreateDevEnum *pSysDevEnum = NULL;
+	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum);
+	if (FAILED(hr)){
+		return hr;
+	}
+ 
+	IEnumMoniker *pEnumCat = NULL;
+	//Category	
+	/************************************************************************
+	Friendly Name	                      CLSID
+	-------------------------------------------------------------------------
+	Audio Capture Sources	              CLSID_AudioInputDeviceCategory
+	Audio Compressors	                  CLSID_AudioCompressorCategory
+	Audio Renderers	                      CLSID_AudioRendererCategory
+	Device Control Filters	              CLSID_DeviceControlCategory
+	DirectShow Filters	                  CLSID_LegacyAmFilterCategory
+	External Renderers	                  CLSID_TransmitCategory
+	Midi Renderers	                      CLSID_MidiRendererCategory
+	Video Capture Sources	              CLSID_VideoInputDeviceCategory
+	Video Compressors	                  CLSID_VideoCompressorCategory
+	WDM Stream Decompression Devices	  CLSID_DVDHWDecodersCategory
+	WDM Streaming Capture Devices	      AM_KSCATEGORY_CAPTURE
+	WDM Streaming Crossbar Devices	      AM_KSCATEGORY_CROSSBAR
+	WDM Streaming Rendering Devices	      AM_KSCATEGORY_RENDER
+	WDM Streaming Tee/Splitter Devices	  AM_KSCATEGORY_SPLITTER
+	WDM Streaming TV Audio Devices	      AM_KSCATEGORY_TVAUDIO
+	WDM Streaming TV Tuner Devices	      AM_KSCATEGORY_TVTUNER
+	WDM Streaming VBI Codecs	          AM_KSCATEGORY_VBICODEC 
+	************************************************************************/
+	hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnumCat, 0);
+	//hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
+	//hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioCompressorCategory, &pEnumCat, 0);
+	//hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEnumCat, 0);
+	//hr = pSysDevEnum->CreateClassEnumerator(CLSID_MediaMultiplexerCategory, &pEnumCat, 0);
+	//hr = pSysDevEnum->CreateClassEnumerator(CLSID_LegacyAmFilterCategory, &pEnumCat, 0);
+ 
+	if (hr != S_OK) {
+		pSysDevEnum->Release();
+		return -1;
+	}
+	
+	IMoniker *pMoniker = NULL;
+	ULONG monikerFetched;
+	//Filter
+	while(pEnumCat->Next(1, &pMoniker, &monikerFetched) == S_OK){
+		IPropertyBag *pPropBag;
+		VARIANT varName;
+		IBaseFilter *pFilter;
+		hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,(void **)&pPropBag);
+		if (FAILED(hr)){
+			pMoniker->Release();
+			continue;
+		}
+		VariantInit(&varName);
+		hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+		//"FriendlyName": The name of the device.
+		//"Description": A description of the device.
+		//Filter Info================
+		_tprintf_s(_T("[%ls]\n"),varName.bstrVal);
+		VariantClear(&varName);
+		//========================
+#if OUTPUT_PIN
+		hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,(void**)&pFilter);
+		if (!pFilter){
+			continue;
+		}
+ 
+		IEnumPins * pinEnum = NULL;
+		IPin * pin = NULL;
+		ULONG pinFetched = 0;
+		if (FAILED(pFilter->EnumPins(&pinEnum))){
+			pinEnum->Release();
+			continue;	
+		}
+		pinEnum->Reset();
+		//Pin Info
+		while (SUCCEEDED(pinEnum->Next(1, &pin, &pinFetched)) && pinFetched){
+			if (!pin){
+				continue;
+			}
+			PIN_INFO pinInfo;
+			if (FAILED(pin->QueryPinInfo(&pinInfo))){
+				continue;
+			}
+			printf("\t[Pin] ");
+				switch(pinInfo.dir){
+				case PINDIR_INPUT:printf("Dir:Input  \t");break;
+				case PINDIR_OUTPUT:printf("Dir:Output \t");break;
+				default:printf("Dir:Unknown\n");break;
+			}
+			_tprintf_s(_T("Name:%ls\n"),pinInfo.achName);
+					
+			//MediaType
+#if OUTPUT_MEDIATYPE
+			IEnumMediaTypes *mtEnum=NULL;
+			AM_MEDIA_TYPE   *mt=NULL;
+			if( FAILED( pin->EnumMediaTypes( &mtEnum )) )
+				break;
+			mtEnum->Reset();
+			
+			ULONG mtFetched = 0;
+ 
+			while (SUCCEEDED(mtEnum->Next(1, &mt, &mtFetched)) && mtFetched){
+ 
+				printf("\t\t[MediaType]\n");
+				//Video
+				char *MEDIATYPE_Video_str=GuidToString(MEDIATYPE_Video);
+				//Audio
+				char *MEDIATYPE_Audio_str=GuidToString(MEDIATYPE_Audio);
+				//Stream
+				char *MEDIATYPE_Stream_str=GuidToString(MEDIATYPE_Stream);
+				//Majortype
+				char *majortype_str=GuidToString(mt->majortype);
+				//Subtype
+				char *subtype_str=GuidToString(mt->subtype);
+ 
+				printf("\t\t  Majortype:");
+				if(strcmp(majortype_str,MEDIATYPE_Video_str)==0){
+					printf("Video\n");
+				}else if(strcmp(majortype_str,MEDIATYPE_Audio_str)==0){
+					printf("Audio\n");
+				}else if(strcmp(majortype_str,MEDIATYPE_Stream_str)==0){
+					printf("Stream\n");
+				}else{
+					printf("Other\n");
+				}
+				printf("\t\t  Subtype GUID:%s",subtype_str);
+ 
+				free(MEDIATYPE_Video_str);
+				free(MEDIATYPE_Audio_str);
+				free(MEDIATYPE_Stream_str);
+				free(subtype_str);
+				free(majortype_str);
+				printf("\n");
+ 
+			}
+#endif
+			pin->Release();
+				
+		}
+		pinEnum->Release();
+ 
+		pFilter->Release();
+#endif
+		
+		pPropBag->Release();
+		pMoniker->Release();
+	}
+	pEnumCat->Release();
+	pSysDevEnum->Release();
+	printf("=================================================\n");
+	CoUninitialize();
+	return 0;
+
+}
+
+// CGameAssistApp
+
+BEGIN_MESSAGE_MAP(CGameAssistApp, CWinAppEx)
+	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+
+// CGameAssistApp 构造
+
+CGameAssistApp::CGameAssistApp()
+{
+	// TODO: 在此处添加构造代码,
+	// 将所有重要的初始化放置在 InitInstance 中
+}
+
+
+// 唯一的一个 CGameAssistApp 对象
+
+CGameAssistApp theApp;
+
+
+// CGameAssistApp 初始化
+
+BOOL CGameAssistApp::InitInstance()
+{
+	// 如果一个运行在 Windows XP 上的应用程序清单指定要
+	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
+	//则需要 InitCommonControlsEx()。否则,将无法创建窗口。
+	INITCOMMONCONTROLSEX InitCtrls;
+	InitCtrls.dwSize = sizeof(InitCtrls);
+	// 将它设置为包括所有要在应用程序中使用的
+	// 公共控件类。
+	InitCtrls.dwICC = ICC_WIN95_CLASSES;
+	InitCommonControlsEx(&InitCtrls);
+
+	CWinAppEx::InitInstance();
+
+	AfxEnableControlContainer();
+
+#if 0
+	DirectShowDemo();
+	std::vector<std::string> vtDevices;
+	listDevices(vtDevices);
+	// 枚举USB摄像头设备;
+	ICreateDevEnum *pCreateDevEnum=0;
+	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pCreateDevEnum);
+#endif
+
+	// 标准初始化
+	// 如果未使用这些功能并希望减小
+	// 最终可执行文件的大小,则应移除下列
+	// 不需要的特定初始化例程
+	// 更改用于存储设置的注册表项
+	// TODO: 应适当修改该字符串,
+	// 例如修改为公司或组织名
+	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
+
+	CGameAssistDlg dlg;
+	m_pMainWnd = &dlg;
+	INT_PTR nResponse = dlg.DoModal();
+	if (nResponse == IDOK)
+	{
+		// TODO: 在此放置处理何时用
+		//  “确定”来关闭对话框的代码
+	}
+	else if (nResponse == IDCANCEL)
+	{
+		// TODO: 在此放置处理何时用
+		//  “取消”来关闭对话框的代码
+	}
+
+	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
+	//  而不是启动应用程序的消息泵。
+	return FALSE;
+}

+ 32 - 0
GameAssist/GameAssist/GameAssist.h

@@ -0,0 +1,32 @@
+
+// GameAssist.h : PROJECT_NAME 应用程序的主头文件
+//
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+	#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
+#endif
+
+#include "resource.h"		// 主符号
+
+
+// CGameAssistApp:
+// 有关此类的实现,请参阅 GameAssist.cpp
+//
+
+class CGameAssistApp : public CWinAppEx
+{
+public:
+	CGameAssistApp();
+
+// 重写
+	public:
+	virtual BOOL InitInstance();
+
+// 实现
+
+	DECLARE_MESSAGE_MAP()
+};
+
+extern CGameAssistApp theApp;

+ 215 - 0
GameAssist/GameAssist/GameAssist.rc

@@ -0,0 +1,215 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#ifndef APSTUDIO_INVOKED
+#include "targetver.h"
+#endif
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// 中文(简体,中国) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
+#pragma code_page(936)
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#ifndef APSTUDIO_INVOKED\r\n"
+    "#include ""targetver.h""\r\n"
+    "#endif\r\n"
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+    "#define _AFX_NO_OLE_RESOURCES\r\n"
+    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+    "\r\n"
+    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
+    "LANGUAGE 4, 2\r\n"
+    "#pragma code_page(936)\r\n"
+    "#include ""res\\GameAssist.rc2""  // 非 Microsoft Visual C++ 编辑的资源\r\n"
+    "#include ""l.CHS\\afxres.rc""      // 标准组件\r\n"
+    "#endif\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME           ICON                    "res\\GameAssist.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "关于 GameAssist"
+FONT 9, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+    ICON            IDR_MAINFRAME,IDC_STATIC,14,14,21,20
+    LTEXT           "GameAssist,1.0 版",IDC_STATIC,42,14,114,8,SS_NOPREFIX
+    LTEXT           "Copyright (C) 2020",IDC_STATIC,42,26,114,8
+    DEFPUSHBUTTON   "确定",IDOK,113,41,50,14,WS_GROUP
+END
+
+IDD_GAMEASSIST_DIALOG DIALOGEX 0, 0, 320, 200
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "GameAssist"
+FONT 9, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+    DEFPUSHBUTTON   "确定",IDOK,209,179,50,14
+    PUSHBUTTON      "取消",IDCANCEL,263,179,50,14
+    CTEXT           "TODO: 在此放置对话框控件。",IDC_STATIC,10,96,300,8
+    PUSHBUTTON      "打开",BTN_OPENGAME,7,7,50,14
+    PUSHBUTTON      "Button2",IDC_BUTTON2,8,28,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "080403a8"
+        BEGIN
+            VALUE "CompanyName", "TODO: <公司名>"
+            VALUE "FileDescription", "TODO: <文件说明>"
+            VALUE "FileVersion", "1.0.0.1"
+            VALUE "InternalName", "GameAssist.exe"
+            VALUE "LegalCopyright", "TODO: (C) <公司名>。保留所有权利。"
+            VALUE "OriginalFilename", "GameAssist.exe"
+            VALUE "ProductName", "TODO: <产品名>"
+            VALUE "ProductVersion", "1.0.0.1"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x804, 936
+    END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+    IDD_ABOUTBOX, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 163
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 55
+    END
+
+    IDD_GAMEASSIST_DIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 313
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 193
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// AFX_DIALOG_LAYOUT
+//
+
+IDD_GAMEASSIST_DIALOG AFX_DIALOG_LAYOUT
+BEGIN
+    0
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+    IDS_ABOUTBOX            "关于 GameAssist(&A)..."
+END
+
+#endif    // 中文(简体,中国) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+#include "res\GameAssist.rc2"  // 非 Microsoft Visual C++ 编辑的资源
+#include "l.CHS\afxres.rc"      // 标准组件
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+

+ 286 - 0
GameAssist/GameAssist/GameAssist.vcproj

@@ -0,0 +1,286 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="GameAssist"
+	ProjectGUID="{A83AED38-393A-4928-BB07-3D5D03CDB242}"
+	RootNamespace="GameAssist"
+	Keyword="MFCProj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="false"
+				ValidateParameters="true"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				UACExecutionLevel="2"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="false"
+				ValidateParameters="true"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG"
+				MinimalRebuild="false"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				UACExecutionLevel="2"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\Assist.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\GameAssist.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\GameAssistDlg.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\Assist.h"
+				>
+			</File>
+			<File
+				RelativePath=".\GameAssist.h"
+				>
+			</File>
+			<File
+				RelativePath=".\GameAssistDlg.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\Assist.ini"
+				>
+			</File>
+			<File
+				RelativePath=".\res\GameAssist.ico"
+				>
+			</File>
+			<File
+				RelativePath=".\GameAssist.rc"
+				>
+			</File>
+			<File
+				RelativePath=".\res\GameAssist.rc2"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+		<Global
+			Name="RESOURCE_FILE"
+			Value="GameAssist.rc"
+		/>
+	</Globals>
+</VisualStudioProject>

+ 156 - 0
GameAssist/GameAssist/GameAssist.vcxproj

@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{A83AED38-393A-4928-BB07-3D5D03CDB242}</ProjectGuid>
+    <RootNamespace>GameAssist</RootNamespace>
+    <Keyword>MFCProj</Keyword>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v142</PlatformToolset>
+    <UseOfMfc>Dynamic</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <PlatformToolset>v142</PlatformToolset>
+    <UseOfMfc>Dynamic</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>16.0.30323.82</_ProjectFileVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>..\..\..\bin\$(SolutionName)\</OutDir>
+    <IntDir>$(OutDir)$(Configuration)\</IntDir>
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>..\..\..\bin\$(SolutionName)\</OutDir>
+    <IntDir>$(OutDir)$(Configuration)\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Midl>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+    </ClCompile>
+    <ResourceCompile>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0804</Culture>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <Link>
+      <UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Midl>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+    </Midl>
+    <ClCompile>
+      <Optimization>MaxSpeed</Optimization>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>false</MinimalRebuild>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+    </ClCompile>
+    <ResourceCompile>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0804</Culture>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <Link>
+      <UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Windows</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="Assist.cpp" />
+    <ClCompile Include="CVideoCapture.cpp" />
+    <ClCompile Include="GameAssist.cpp" />
+    <ClCompile Include="GameAssistDlg.cpp" />
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="VideoDXGICaptor.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Assist.h" />
+    <ClInclude Include="CVideoCapture.h" />
+    <ClInclude Include="GameAssist.h" />
+    <ClInclude Include="GameAssistDlg.h" />
+    <ClInclude Include="Resource.h" />
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+    <ClInclude Include="VideoDXGICaptor.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Assist.ini" />
+    <None Include="res\GameAssist.rc2" />
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\GameAssist.ico" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="GameAssist.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+  <ProjectExtensions>
+    <VisualStudio>
+      <UserProperties RESOURCE_FILE="GameAssist.rc" />
+    </VisualStudio>
+  </ProjectExtensions>
+</Project>

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

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="源文件">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="头文件">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="资源文件">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Assist.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="GameAssist.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="GameAssistDlg.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="CVideoCapture.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="VideoDXGICaptor.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Assist.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="GameAssist.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="GameAssistDlg.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="Resource.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="stdafx.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="CVideoCapture.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="VideoDXGICaptor.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Assist.ini">
+      <Filter>资源文件</Filter>
+    </None>
+    <None Include="res\GameAssist.rc2">
+      <Filter>资源文件</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\GameAssist.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="GameAssist.rc">
+      <Filter>资源文件</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ReadMe.txt" />
+  </ItemGroup>
+</Project>

+ 344 - 0
GameAssist/GameAssist/GameAssistDlg.cpp

@@ -0,0 +1,344 @@
+
+// GameAssistDlg.cpp : 实现文件
+//
+
+#include "stdafx.h"
+#include "GameAssist.h"
+#include "GameAssistDlg.h"
+//#include "VideoDXGICaptor.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
+
+class CAboutDlg : public CDialog
+{
+public:
+	CAboutDlg();
+
+// 对话框数据
+	enum { IDD = IDD_ABOUTBOX };
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
+
+// 实现
+protected:
+	DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
+{
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
+END_MESSAGE_MAP()
+
+
+// CGameAssistDlg 对话框
+
+
+
+
+CGameAssistDlg::CGameAssistDlg(CWnd* pParent /*=NULL*/)
+	: CDialog(CGameAssistDlg::IDD, pParent)
+{
+	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+}
+
+void CGameAssistDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CGameAssistDlg, CDialog)
+	ON_WM_SYSCOMMAND()
+	ON_WM_PAINT()
+	ON_WM_QUERYDRAGICON()
+	//}}AFX_MSG_MAP
+	ON_BN_CLICKED(BTN_OPENGAME, &CGameAssistDlg::OnBnClickedOpengame)
+	ON_BN_CLICKED(IDC_BUTTON2, &CGameAssistDlg::OnBnClickedButton2)
+END_MESSAGE_MAP()
+
+
+// CGameAssistDlg 消息处理程序
+
+BOOL CGameAssistDlg::OnInitDialog()
+{
+	CDialog::OnInitDialog();
+
+	// 将“关于...”菜单项添加到系统菜单中。
+
+	// IDM_ABOUTBOX 必须在系统命令范围内。
+	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+	ASSERT(IDM_ABOUTBOX < 0xF000);
+
+	CMenu* pSysMenu = GetSystemMenu(FALSE);
+	if (pSysMenu != NULL)
+	{
+		BOOL bNameValid;
+		CString strAboutMenu;
+		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
+		ASSERT(bNameValid);
+		if (!strAboutMenu.IsEmpty())
+		{
+			pSysMenu->AppendMenu(MF_SEPARATOR);
+			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
+		}
+	}
+
+	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
+	//  执行此操作
+	SetIcon(m_hIcon, TRUE);			// 设置大图标
+	SetIcon(m_hIcon, FALSE);		// 设置小图标
+
+	// TODO: 在此添加额外的初始化代码
+
+	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
+}
+
+void CGameAssistDlg::OnSysCommand(UINT nID, LPARAM lParam)
+{
+	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
+	{
+		CAboutDlg dlgAbout;
+		dlgAbout.DoModal();
+	}
+	else
+	{
+		CDialog::OnSysCommand(nID, lParam);
+	}
+}
+
+// 如果向对话框添加最小化按钮,则需要下面的代码
+//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
+//  这将由框架自动完成。
+
+void CGameAssistDlg::OnPaint()
+{
+	if (IsIconic())
+	{
+		CPaintDC dc(this); // 用于绘制的设备上下文
+
+		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
+
+		// 使图标在工作区矩形中居中
+		int cxIcon = GetSystemMetrics(SM_CXICON);
+		int cyIcon = GetSystemMetrics(SM_CYICON);
+		CRect rect;
+		GetClientRect(&rect);
+		int x = (rect.Width() - cxIcon + 1) / 2;
+		int y = (rect.Height() - cyIcon + 1) / 2;
+
+		// 绘制图标
+		dc.DrawIcon(x, y, m_hIcon);
+	}
+	else
+	{
+		CDialog::OnPaint();
+	}
+}
+
+//当用户拖动最小化窗口时系统调用此函数取得光标
+//显示。
+HCURSOR CGameAssistDlg::OnQueryDragIcon()
+{
+	return static_cast<HCURSOR>(m_hIcon);
+}
+
+
+void CGameAssistDlg::OnBnClickedOpengame()
+{
+#if 1 // 获取游戏标题;
+	DWORD dwPid = GAssist::FindProcess(_T("Game.exe"));
+	HWND hProWnd = GAssist::GetProHwnd(dwPid);
+	//HWND hProWnd = GAssist::GetProHwnd(5824);
+	TCHAR szWinText[MAX_PATH] = {0};
+	::GetWindowText(hProWnd, szWinText, MAX_PATH);
+
+#if 0
+ 	Sleep(1000);
+ 	GAssist::MouseMove(hProWnd, CPoint(205,150));
+ 	Sleep(2000);
+ 	GAssist::MouseMove(hProWnd, CPoint(100,100), CPoint(250,250));
+ 	Sleep(2000);
+ 	GAssist::MouseMove(hProWnd, CPoint(100,100), CPoint(350,350));
+#endif
+
+	if (0)
+	{
+		Sleep(1000);
+		GAssist::MouseClick(hProWnd, CPoint(205,150));
+
+		Sleep(1000);
+		GAssist::MouseClick(hProWnd, CPoint(235,150));
+
+		Sleep(1000);
+		GAssist::MouseClick(hProWnd, CPoint(275,150));
+	}
+
+	if (1)
+	{
+		Sleep(5000);
+		::SetForegroundWindow(hProWnd);
+		GAssist::DragMouse(hProWnd, CPoint(243,138), CPoint(295,190));
+	}
+
+	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) )
+	{
+		MessageBox("游戏程序不存在", "温馨提示");
+		return;
+	}
+
+	// 设置辅助程序工作目录为游戏目录;
+	//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秒;
+#else
+	SHELLEXECUTEINFO stuExecInfo = { 0 };
+	DWORD dwExitCode = STILL_ACTIVE;
+	//CString strCommandLine = _T("open");
+	stuExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
+	stuExecInfo.lpFile = GAssist::g_szGamePath;
+	stuExecInfo.lpParameters = "open";
+	stuExecInfo.nShow = SW_SHOWNORMAL;
+	stuExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
+
+	if (!ShellExecuteEx(&stuExecInfo))
+	{
+		DWORD dwError = GetLastError();
+		CString strError = _T("");
+		strError.Format(_T("执行ShellExecuteEx失败,错误码:%d"),dwError);
+		AfxMessageBox(strError);
+		return ;
+	}
+
+	HANDLE hProcess = stuExecInfo.hProcess;
+	if ( hProcess != NULL )
+	{
+		WaitForSingleObject(hProcess,INFINITE);
+		CloseHandle(hProcess);
+	}
+
+#endif
+
+	DWORD dwPID = GAssist::FindProcess(_T("Main.exe"));
+#if 1
+	EnumWindows(GAssist::EnumChildWindowCallBack, dwPID);
+
+	if ( GAssist::g_vtGameHwnd.size() )
+	{
+		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 ( _tcsicmp(it->strWinText.c_str(), _T("最小化")) == 0 )
+			{
+				gbmin = &*it;
+			}
+
+			if ( _tcsicmp(it->strWinText.c_str(), _T("大话水浒")) == 0 )
+			{
+				gp = &*it;
+			}
+
+			if ( _tcsicmp(it->strWinText.c_str(), _T("进入游戏")) == 0 )
+			{
+				gbentry = &*it;
+			}
+		}
+
+		if ( gp && gbentry && gbmin)
+		{
+			//::SendMessage(gp->hwnd, WM_LBUTTONDOWN, (WPARAM)gb->dwId, 0);
+			//::SendMessage(gp->hwnd, WM_LBUTTONUP, (WPARAM)gb->dwId, 0);
+			// 发送点击事件;
+			// 先最小化;
+			::SendMessage(gp->hwnd,WM_COMMAND,gbmin->dwId,NULL);
+			// 再进入;
+			::SendMessage(gp->hwnd,WM_COMMAND,gbentry->dwId,NULL);
+
+
+			Sleep(1500);
+			dwPID = GAssist::FindProcess(_T("Game.exe"));
+			if ( dwPID )
+			{
+				GAssist::g_vtGameHwnd.clear();
+				EnumWindows(GAssist::EnumChildWindowCallBack, dwPID);
+				HWND hwnd = GAssist::GetProHwnd(dwPID);
+				if ( hwnd )
+				{
+					TCHAR szName[MAX_PATH] = {0};
+					::GetWindowText(hwnd, szName, MAX_PATH);
+					CRect rc;
+					::GetWindowRect(hwnd, &rc);
+					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 ( 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);
+					}
+				}
+			}
+		}
+	}
+#endif
+}
+
+
+void CGameAssistDlg::OnBnClickedButton2()
+{
+	// TODO: 在此添加控件通知处理程序代码
+	
+// 	VideoDXGICaptor vdx;
+// 	if (vdx.Init())
+// 	{
+// 		INT len = 1024 * 1024 * 1024;
+// 		BYTE* pData = new BYTE[len];
+// 		vdx.CaptureImage(pData, len);
+// 		vdx.Deinit();
+// 	}
+}

+ 35 - 0
GameAssist/GameAssist/GameAssistDlg.h

@@ -0,0 +1,35 @@
+
+// GameAssistDlg.h : 头文件
+//
+
+#pragma once
+
+
+// CGameAssistDlg 对话框
+class CGameAssistDlg : public CDialog
+{
+// 构造
+public:
+	CGameAssistDlg(CWnd* pParent = NULL);	// 标准构造函数
+
+// 对话框数据
+	enum { IDD = IDD_GAMEASSIST_DIALOG };
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持
+
+
+// 实现
+protected:
+	HICON m_hIcon;
+
+	// 生成的消息映射函数
+	virtual BOOL OnInitDialog();
+	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
+	afx_msg void OnPaint();
+	afx_msg HCURSOR OnQueryDragIcon();
+	DECLARE_MESSAGE_MAP()
+public:
+	afx_msg void OnBnClickedOpengame();
+	afx_msg void OnBnClickedButton2();
+};

+ 69 - 0
GameAssist/GameAssist/ReadMe.txt

@@ -0,0 +1,69 @@
+================================================================================
+    MICROSOFT 基础类库: GameAssist 项目概述
+===============================================================================
+
+应用程序向导已为您创建此 GameAssist 应用程序。此应用程序不仅演示使用 Microsoft 基础类的基本知识,而且可作为编写应用程序的起点。
+
+此文件包含组成 GameAssist 应用程序的各个文件的内容摘要。
+
+GameAssist.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件。
+    它包含有关生成文件的 Visual C++ 版本的信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+GameAssist.h
+    这是应用程序的主要头文件。它包括其他项目特定的头文件(包括 Resource.h),并声明 CGameAssistApp 应用程序类。
+
+GameAssist.cpp
+    这是包含应用程序类 CGameAssistApp 的主要应用程序源文件。
+
+GameAssist.rc
+    这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ 中进行编辑。项目资源位于 2052 中。
+
+res\GameAssist.ico
+    这是用作应用程序图标的图标文件。此图标包括在主要资源文件 GameAssist.rc 中。
+
+res\GameAssist.rc2
+    此文件包含不是由 Microsoft Visual C++ 编辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+应用程序向导创建一个对话框类:
+
+GameAssistDlg.h,GameAssistDlg.cpp - 对话框
+    这些文件包含 CGameAssistDlg 类。该类定义应用程序主对话框的行为。该对话框的模板位于 GameAssist.rc 中,该文件可以在 Microsoft Visual C++ 中进行编辑。
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+其他功能:
+
+ActiveX 控件
+    应用程序包括对使用 ActiveX 控件的支持。
+
+打印及打印预览支持
+    应用程序向导已通过从 MFC 库调用 CView 类中的成员函数,生成了用于处理打印、打印设置和打印预览命令的代码。
+
+/////////////////////////////////////////////////////////////////////////////
+
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 GameAssist.pch 的预编译头(PCH)文件和名为 StdAfx.obj 的预编译类型文件。
+
+Resource.h
+    这是标准头文件,它定义新资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+GameAssist.manifest
+	Windows XP 使用应用程序清单文件描述应用程序	对特定版本并行程序集的依赖性。加载程序使用此	信息从程序集缓存加载相应程序集或	从应用程序加载私有信息。应用程序清单可能作为	与应用程序可执行文件安装在同一文件夹中的外部 .manifest 文件包括在内以便重新发布,	也可能以资源的形式包括在该可执行文件中。
+/////////////////////////////////////////////////////////////////////////////
+
+其他注释:
+
+应用程序向导使用“TODO:”指示应添加或自定义的源代码部分。
+
+如果应用程序在共享 DLL 中使用 MFC,则将需要重新发布 MFC DLL。如果应用程序所用与操作系统的区域设置不同,则也将必须重新发布对应的本地化资源 MFC90XXX.DLL。
+有关这两个主题的详细信息,请参阅 MSDN 文档中有关重新发布 Visual C++ 应用程序的部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 304 - 0
GameAssist/GameAssist/VideoDXGICaptor.cpp

@@ -0,0 +1,304 @@
+#include "stdafx.h"
+#include "VideoDXGICaptor.h"
+#include <windows.h>
+#include <gdiplus.h>
+
+#pragma comment(lib, "d3d11.lib")
+#pragma comment(lib, "dxgi.lib")
+
+#define RESET_OBJECT(obj) { if(obj) obj->Release(); obj = NULL; }
+static BOOL g_bAttach = FALSE;
+
+VideoDXGICaptor::VideoDXGICaptor()
+{
+	m_bInit = FALSE;
+
+	m_hDevice = NULL;
+	m_hContext = NULL;
+	m_hDeskDupl = NULL;
+
+	ZeroMemory(&m_dxgiOutDesc, sizeof(m_dxgiOutDesc));
+}
+
+VideoDXGICaptor::~VideoDXGICaptor()
+{
+	Deinit();
+}
+
+BOOL VideoDXGICaptor::Init()
+{
+	HRESULT hr = S_OK;
+
+	if (m_bInit)
+	{
+		return FALSE;
+	}
+
+	// Driver types supported
+	D3D_DRIVER_TYPE DriverTypes[] =
+	{
+		D3D_DRIVER_TYPE_HARDWARE,
+		D3D_DRIVER_TYPE_WARP,
+		D3D_DRIVER_TYPE_REFERENCE,
+	};
+	UINT NumDriverTypes = ARRAYSIZE(DriverTypes);
+
+	// Feature levels supported
+	D3D_FEATURE_LEVEL FeatureLevels[] =
+	{
+		D3D_FEATURE_LEVEL_11_0,
+		D3D_FEATURE_LEVEL_10_1,
+		D3D_FEATURE_LEVEL_10_0,
+		D3D_FEATURE_LEVEL_9_1
+	};
+	UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);
+
+	D3D_FEATURE_LEVEL FeatureLevel;
+
+	//
+	// Create D3D device
+	//
+	for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex)
+	{
+		hr = D3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, 0, FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION, &m_hDevice, &FeatureLevel, &m_hContext);
+		if (SUCCEEDED(hr))
+		{
+			break;
+		}
+	}
+	if (FAILED(hr))
+	{
+		return FALSE;
+	}
+
+	//
+	// Get DXGI device
+	//
+	IDXGIDevice* hDxgiDevice = NULL;
+	hr = m_hDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&hDxgiDevice));
+	if (FAILED(hr))
+	{
+		return FALSE;
+	}
+
+	//
+	// Get DXGI adapter
+	//
+	IDXGIAdapter* hDxgiAdapter = NULL;
+	hr = hDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&hDxgiAdapter));
+	RESET_OBJECT(hDxgiDevice);
+	if (FAILED(hr))
+	{
+		return FALSE;
+	}
+
+	//
+	// Get output
+	//
+	INT nOutput = 0;
+	IDXGIOutput* hDxgiOutput = NULL;
+	hr = hDxgiAdapter->EnumOutputs(nOutput, &hDxgiOutput);
+	RESET_OBJECT(hDxgiAdapter);
+	if (FAILED(hr))
+	{
+		return FALSE;
+	}
+
+	//
+	// get output description struct
+	//
+	hDxgiOutput->GetDesc(&m_dxgiOutDesc);
+
+	//
+	// QI for Output 1
+	//
+	IDXGIOutput1* hDxgiOutput1 = NULL;
+	hr = hDxgiOutput->QueryInterface(__uuidof(hDxgiOutput1), reinterpret_cast<void**>(&hDxgiOutput1));
+	RESET_OBJECT(hDxgiOutput);
+	if (FAILED(hr))
+	{
+		return FALSE;
+	}
+
+	//
+	// Create desktop duplication
+	//
+	hr = hDxgiOutput1->DuplicateOutput(m_hDevice, &m_hDeskDupl);
+	RESET_OBJECT(hDxgiOutput1);
+	if (FAILED(hr))
+	{
+		return FALSE;
+	}
+
+	// 初始化成功
+	m_bInit = TRUE;
+	return TRUE;
+	// #else
+		// 小于vs2012,此功能不能实现
+	return FALSE;
+	// #endif
+}
+
+VOID VideoDXGICaptor::Deinit()
+{
+	if (!m_bInit)
+	{
+		return;
+	}
+
+	m_bInit = FALSE;
+
+	if (m_hDeskDupl)
+	{
+		m_hDeskDupl->Release();
+		m_hDeskDupl = NULL;
+	}
+
+	if (m_hDevice)
+	{
+		m_hDevice->Release();
+		m_hDevice = NULL;
+	}
+
+	if (m_hContext)
+	{
+		m_hContext->Release();
+		m_hContext = NULL;
+	}
+	// #endif
+}
+
+BOOL VideoDXGICaptor::AttatchToThread(VOID)
+{
+	if (g_bAttach)
+	{
+		return TRUE;
+	}
+
+	HDESK hCurrentDesktop = OpenInputDesktop(0, FALSE, GENERIC_ALL);
+	if (!hCurrentDesktop)
+	{
+		return FALSE;
+	}
+
+	// Attach desktop to this thread
+	BOOL bDesktopAttached = SetThreadDesktop(hCurrentDesktop);
+	CloseDesktop(hCurrentDesktop);
+	hCurrentDesktop = NULL;
+
+	g_bAttach = TRUE;
+
+	return bDesktopAttached;
+}
+
+BOOL VideoDXGICaptor::CaptureImage(RECT& rect, void* pData, INT& nLen)
+{
+	return QueryFrame(pData, nLen);
+}
+
+BOOL VideoDXGICaptor::CaptureImage(void* pData, INT& nLen)
+{
+	return QueryFrame(pData, nLen);
+}
+
+BOOL VideoDXGICaptor::ResetDevice()
+{
+	Deinit();
+	return Init();
+}
+
+BOOL VideoDXGICaptor::QueryFrame(void* pImgData, INT& nImgSize)
+{
+	if (!m_bInit || !AttatchToThread())
+	{
+		return FALSE;
+	}
+
+	nImgSize = 0;
+
+	IDXGIResource* hDesktopResource = NULL;
+	DXGI_OUTDUPL_FRAME_INFO FrameInfo;
+	HRESULT hr = m_hDeskDupl->AcquireNextFrame(0, &FrameInfo, &hDesktopResource);
+	if (FAILED(hr))
+	{
+		//
+		// 在一些win10的系统上,如果桌面没有变化的情况下,;
+		// 这里会发生超时现象,但是这并不是发生了错误,而是系统优化了刷新动作导致的。;
+		// 所以,这里没必要返回FALSE,返回不带任何数据的TRUE即可;
+		//
+		return TRUE;
+	}
+
+	//
+	// query next frame staging buffer
+	//
+	ID3D11Texture2D* hAcquiredDesktopImage = NULL;
+	hr = hDesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&hAcquiredDesktopImage));
+	RESET_OBJECT(hDesktopResource);
+	if (FAILED(hr))
+	{
+		return FALSE;
+	}
+
+	//
+	// copy old description
+	//
+	D3D11_TEXTURE2D_DESC frameDescriptor;
+	hAcquiredDesktopImage->GetDesc(&frameDescriptor);
+
+	//
+	// create a new staging buffer for fill frame image
+	//
+	ID3D11Texture2D* hNewDesktopImage = NULL;
+	frameDescriptor.Usage = D3D11_USAGE_STAGING;
+	frameDescriptor.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+	frameDescriptor.BindFlags = 0;
+	frameDescriptor.MiscFlags = 0;
+	frameDescriptor.MipLevels = 1;
+	frameDescriptor.ArraySize = 1;
+	frameDescriptor.SampleDesc.Count = 1;
+	hr = m_hDevice->CreateTexture2D(&frameDescriptor, NULL, &hNewDesktopImage);
+	if (FAILED(hr))
+	{
+		RESET_OBJECT(hAcquiredDesktopImage);
+		m_hDeskDupl->ReleaseFrame();
+		return FALSE;
+	}
+
+	//
+	// copy next staging buffer to new staging buffer
+	//
+	m_hContext->CopyResource(hNewDesktopImage, hAcquiredDesktopImage);
+
+	RESET_OBJECT(hAcquiredDesktopImage);
+	m_hDeskDupl->ReleaseFrame();
+
+	//
+	// create staging buffer for map bits
+	//
+	IDXGISurface* hStagingSurf = NULL;
+	hr = hNewDesktopImage->QueryInterface(__uuidof(IDXGISurface), (void**)(&hStagingSurf));
+	RESET_OBJECT(hNewDesktopImage);
+	if (FAILED(hr))
+	{
+		return FALSE;
+	}
+
+	//
+	// copy bits to user space
+	//
+	DXGI_MAPPED_RECT mappedRect;
+	hr = hStagingSurf->Map(&mappedRect, DXGI_MAP_READ);
+	if (SUCCEEDED(hr))
+	{
+		// nImgSize = GetWidth() * GetHeight() * 3;
+		// PrepareBGR24From32(mappedRect.pBits, (BYTE*)pImgData, m_dxgiOutDesc.DesktopCoordinates);
+		// mappedRect.pBits;
+		// am_dxgiOutDesc.DesktopCoordinates;
+		memcpy((BYTE*)pImgData, mappedRect.pBits, m_dxgiOutDesc.DesktopCoordinates.right * m_dxgiOutDesc.DesktopCoordinates.bottom * 4);
+		hStagingSurf->Unmap();
+	}
+
+	RESET_OBJECT(hStagingSurf);
+	return SUCCEEDED(hr);
+}

+ 41 - 0
GameAssist/GameAssist/VideoDXGICaptor.h

@@ -0,0 +1,41 @@
+#pragma once
+
+#include <d3d11.h>
+#include <dxgi1_2.h>
+
+class VideoDXGICaptor
+{
+public:
+	VideoDXGICaptor();
+	~VideoDXGICaptor();
+
+public:
+	BOOL Init();
+	VOID Deinit();
+
+public:
+	virtual BOOL CaptureImage(RECT& rect, void* pData, INT& nLen);
+	virtual BOOL CaptureImage(void* pData, INT& nLen);
+	virtual BOOL ResetDevice();
+
+private:
+	BOOL  AttatchToThread(VOID);
+	BOOL  QueryFrame(void* pImgData, INT& nImgSize);
+	BOOL  QueryFrame(void* pImgData, INT& nImgSize, int z);
+
+private:
+	IDXGIResource* zhDesktopResource;
+	DXGI_OUTDUPL_FRAME_INFO zFrameInfo;
+	ID3D11Texture2D* zhAcquiredDesktopImage;
+	IDXGISurface* zhStagingSurf;
+
+private:
+	BOOL                    m_bInit;
+	int                     m_iWidth, m_iHeight;
+
+	ID3D11Device* m_hDevice;
+	ID3D11DeviceContext* m_hContext;
+
+	IDXGIOutputDuplication* m_hDeskDupl;
+	DXGI_OUTPUT_DESC        m_dxgiOutDesc;
+};

BIN
GameAssist/GameAssist/res/GameAssist.ico


+ 13 - 0
GameAssist/GameAssist/res/GameAssist.rc2

@@ -0,0 +1,13 @@
+//
+// GameAssist.RC2 - Microsoft Visual C++ 不会直接编辑的资源
+//
+
+#ifdef APSTUDIO_INVOKED
+#error 此文件不能用 Microsoft Visual C++ 编辑
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// 在此处添加手动编辑的资源...
+
+/////////////////////////////////////////////////////////////////////////////

+ 23 - 0
GameAssist/GameAssist/resource.h

@@ -0,0 +1,23 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ 生成的包含文件。
+// 供 GameAssist.rc 使用
+//
+#define IDM_ABOUTBOX                    0x0010
+#define IDD_ABOUTBOX                    100
+#define IDS_ABOUTBOX                    101
+#define IDD_GAMEASSIST_DIALOG           102
+#define IDR_MAINFRAME                   128
+#define IDC_BUTTON1                     1000
+#define BTN_OPENGAME                    1000
+#define IDC_BUTTON2                     1001
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        129
+#define _APS_NEXT_COMMAND_VALUE         32771
+#define _APS_NEXT_CONTROL_VALUE         1002
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif

+ 8 - 0
GameAssist/GameAssist/stdafx.cpp

@@ -0,0 +1,8 @@
+
+// stdafx.cpp : 只包括标准包含文件的源文件
+// GameAssist.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+

+ 67 - 0
GameAssist/GameAssist/stdafx.h

@@ -0,0 +1,67 @@
+
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+
+#pragma once
+
+#ifndef _SECURE_ATL
+#define _SECURE_ATL 1
+#endif
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include "targetver.h"
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+// 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏
+#define _AFX_ALL_WARNINGS
+
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+
+
+#include <afxdisp.h>        // MFC 自动化类
+
+
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>             // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <afxcontrolbars.h>     // 功能区和控件条的 MFC 支持
+
+
+
+
+
+
+
+
+
+#ifdef _UNICODE
+#if defined _M_IX86
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_IA64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+
+#include <vector>
+#include <string>
+#include <Shlwapi.h>
+#pragma comment(lib,"Shlwapi.lib") /*需要加上此行才可以正确link,VC6.0*/
+#include <tlhelp32.h>
+
+#include "Assist.h"

+ 26 - 0
GameAssist/GameAssist/targetver.h

@@ -0,0 +1,26 @@
+
+#pragma once
+
+// 以下宏定义要求的最低平台。要求的最低平台
+// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
+// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
+// 正常工作。
+
+// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
+// 有关不同平台对应值的最新信息,请参考 MSDN。
+#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
+#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
+#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
+#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
+#endif
+
+#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
+#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
+#endif
+