天天微动态丨游戏环境下如何实现真正D3D的窗口?启动进程和取得进程的方法
(资料图)
前些日子一直忙,也没来看看,说要给出代码和方法的一直没有给出来请大家见谅,今天给出来! 声明:我不是做游戏外挂的,所以对外挂部分还比较薄弱,没做,只做实现窗口这一块! 1.先看实现的图片,等下慢慢解释。
2.首先解释要如何启动诸仙的进程。我们要想拥有自己的窗口,那么就必须在诸仙的进程启动之前得到Direct3DCreate8接口(诸仙用Direct3D8)。所以启动过程如下: //启动诸仙并获取诸仙进程句柄 ZhuXianProc.OpenExe("C://游戏目录//诛仙//element//elementclient.exe"); if(!ZhuXianProc.GetProcess()) { MessageBox(NULL, " 无法正常启动《诸仙》主程序/n/n获取帮助请与本工作室技术人员联系", "天涯工作室程序运行错误提示!",MB_OK); return TRUE; } //在程序运行之前先HOOK住所需要HOOK的API HookApi("C://游戏目录//诛仙//element//elementclient.exe","C://游戏目录//诛仙//element//ZxDll.dll"); ZhuXianFunc(); ZhuXianProc.CloseAllHandle(); 关于ZhuXianProc是一个CGetProc类型,这个类主要是打开进程和取得进程的一些信息,GetProcess()取的改进程的句柄。这个类里面要解释下的是:void CGetProc::OpenExe(CString str) { memset(&si,0,sizeof(si)); si.cb=sizeof(si); si.wShowWindow=SW_SHOW; si.dwFlags=STARTF_USESHOWWINDOW; CreateProcess(str,NULL,NULL,FALSE,NULL,CREATE_SUSPENDED,NULL,NULL,&si,&pi); } “CREATE_SUSPENDED”指明该进程并不是一开始就让他运行,原因是我们要想得到Direct3DCreate8接口就必须在运行进程之前注入我们的DLL,并让我们的DLL里的HOOK Direct3DCreate8接口跑到他的初始化之前。我们来看看HookApi()的内容:bool CUIThread::HookApi(char* pszFileExe,char* pszFileDll) { //让程序启动的时候JMP到自己的DLL中去 HANDLE hProcess = ZhuXianProc.GetProcess(); // 在目标进程申请空间,存放字符串pszDllName,作为远程线程的参数 int cbSize = (strlen(pszFileDll) + 1); LPVOID lpRemoteDllName = ::VirtualAllocEx(hProcess, NULL, cbSize, MEM_COMMIT, PAGE_READWRITE); ::WriteProcessMemory(hProcess, lpRemoteDllName, pszFileDll, cbSize, NULL); // 取得LoadLibraryA函数的地址,我们将以它作为远程线程函数启动 HMODULE hModule=::GetModuleHandle ("kernel32.dll"); LPTHREAD_START_ROUTINE pfnStartRoutine = (LPTHREAD_START_ROUTINE)::GetProcAddress(hModule, "LoadLibraryA"); // 启动远程线程 ::ResumeThread(ZhuXianProc.GetThread()); HANDLE hRemoteThread = ::CreateRemoteThread(hProcess, NULL, 0, pfnStartRoutine, lpRemoteDllName, 0, NULL); if(hRemoteThread == NULL) { ::CloseHandle(hProcess); return FALSE; } ::CloseHandle(hRemoteThread); return TRUE; } 这段关键是在: // 启动远程线程 ::ResumeThread(ZhuXianProc.GetThread()); HANDLE hRemoteThread = ::CreateRemoteThread(hProcess, NULL, 0, pfnStartRoutine, lpRemoteDllName, 0, NULL); 必须这样,ResumeThread诸仙进程之后立即启动我们的DLL。呵呵,也不能弄反,如果进程没启动,我们注入的DLL就启动了,进程可能就崩溃了。 在这里有个小技巧,诸仙进程启动不代表就立即进行Direct3DCreate8初始化,他还有些事情要做,到他初始化的时候我们的DLL早就跑了一段了:)。 3.来看看我们的重点,我们注入的ZXDLL.DLL到底做了些什么事情。 #pragma comment(lib, "d3d8.lib")// CZxDllAppBEGIN_MESSAGE_MAP(CZxDllApp, CWinApp)END_MESSAGE_MAP()// CZxDllApp 构造CZxDllApp::CZxDllApp(){// TODO: 在此处添加构造代码, // 将所有重要的初始化放置在 InitInstance 中}// 唯一的一个 CZxDllApp 对象CZxDllApp theApp;CAPIHook hookapi2("d3d8.dll","Direct3DCreate8",(PROC)NewDirect3DCreate8);// CZxDllApp 初始化BOOL CZxDllApp::InitInstance(){CWinApp::InitInstance(); return TRUE;}看完DLL的这一段小程序,基本上是VC向导完成的,只有一句:CAPIHook hookapi2("d3d8.dll","Direct3DCreate8",(PROC)NewDirect3DCreate8);这 句在DLL一运行的时候他就运行了,并把Direct3DCreate8给变成了新的入口地址NewDirect3DCreate8了,那么当诸仙运行的 时候这个函数就跑到我们的NewDirect3DCreate8里来了,呵呵,正好,我们抓住了Direct3DCreate8接口了,来我们一起看看 NewDirect3DCreate8函数里的内容。IDirect3D8 * WINAPI NewDirect3DCreate8(UINT SDKVersion){static int count = 0; static IDirect3D8* test = NULL; hookapi2.Unhook(); IDirect3D8 * m = Direct3DCreate8(SDKVersion); hookapi2.Rehook();//程序一共3个3维平面驱动 count++; if(count==2){//1,窗口模式请用2,全屏模式请用3 lpD3D = m; //替换VTable,实现对IDirect3Draw 的 COM接口的挂钩 NewlpD3d = new MyIDirect3D8; m = (IDirect3D8*)NewlpD3d; } return m;}呵 呵,诸仙对IDirect3D8接口其实是驱动了3次,我没查出来第一次是干什么的,但是后两次一个是在窗口模式下用的,一个是在全屏模式下用的。光得到 IDirect3D8接口是没用的这里我们还要进行COM HOOK 获得Direct3DDevice8(D3D 设备) 的接口的指针从而得到我们的Render该放到什么地方。COM HOOK其实就是写一个同样的类用来替换COM的VTable,不做详细的解释,实在搞不懂就google(俺也是这么得来的:))。MyIDirect3D8就是一个新的IDirect3D8类,他是从IDirect3D8继承来的,定义如下:class MyIDirect3D8 : public IDirect3D8{public: HRESULT APIENTRY QueryInterface(REFIID riid, void** ppvObj); ULONG APIENTRY AddRef(); ULONG APIENTRY Release(); /*** IDirect3D8 methods ***/ HRESULT APIENTRY RegisterSoftwareDevice(void* pInitializeFunction); UINT APIENTRY GetAdapterCount(); HRESULT APIENTRY GetAdapterIdentifier(UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER8* pIdentifier); UINT APIENTRY GetAdapterModeCount(UINT Adapter); HRESULT APIENTRY EnumAdapterModes(UINT Adapter,UINT Mode,D3DDISPLAYMODE* pMode); HRESULT APIENTRY GetAdapterDisplayMode(UINT Adapter,D3DDISPLAYMODE* pMode); HRESULT APIENTRY CheckDeviceType(UINT Adapter,D3DDEVTYPE CheckType,D3DFORMAT DisplayFormat,D3DFORMAT BackBufferFormat,BOOL Windowed); HRESULT APIENTRY CheckDeviceFormat(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat); HRESULT APIENTRY CheckDeviceMultiSampleType(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType); HRESULT APIENTRY CheckDepthStencilMatch(UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat); HRESULT APIENTRY GetDeviceCaps(UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS8* pCaps); HMONITOR APIENTRY GetAdapterMonitor(UINT Adapter); HRESULT APIENTRY CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice8** ppReturnedDeviceInterface); MyIDirect3D8(void); IDirect3D8 * lpD3D; IDirect3DDevice8 * lpD3DD8; IDirect3DDevice8 * lpD3DD8bak; ULONG m_count;};pGame就是我们的外挂的主类包括界面处理等等,在下一点讲解。IpD3DDevice是Direct3DDevice8(D3D 设备) 的接口的指针,我们也要想办法解决,不急,等下慢慢说。替换VTable其实很简单,我们只需要new一个我们自己的的MyIDirect3D8把老的IDirect3D8的指针内容直接替换就行了,呵呵://替换VTable,实现对IDirect3Draw 的 COM接口的挂钩NewlpD3d = new MyIDirect3D8;m = (IDirect3D8*)NewlpD3d;Direct3DDevice8(D3D 设备) 的接口的指针是在IDirect3D8里面Create的我们再看看MyIDirect3D8的CreateDevice函数如何定义:HRESULT APIENTRY MyIDirect3D8::CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice8** ppReturnedDeviceInterface){static MyIDirect3DDevice8 * id3dd8 = NULL; HRESULT m = lpD3D->CreateDevice(Adapter,DeviceType,hFocusWindow,BehaviorFlags,pPresentationParameters,ppReturnedDeviceInterface); lpD3DD8 = *ppReturnedDeviceInterface; //Hook IDirect3DDevice8 ::ShowWindow(hFocusWindow,SW_HIDE); lpD3D->CreateDevice(Adapter,DeviceType,hFocusWindow,BehaviorFlags,pPresentationParameters,&lpD3DD8bak); ::ShowWindow(hFocusWindow,SW_SHOW); ::SetFocus(hFocusWindow); id3dd8 = new MyIDirect3DDevice8(lpD3DD8bak); *ppReturnedDeviceInterface = (IDirect3DDevice8*)id3dd8; return m;}至于::ShowWindow(hFocusWindow,SW_HIDE);初始化后::ShowWindow(hFocusWindow,SW_SHOW);保证进程不挂,呵呵。IDirect3DDevice8要想得到IDirect3DDevice8的里面的内容,我们也采用同样方法的偷粱换柱子。MyIDirect3DDevice8定义就不再贴出来了,浪费页面。要解释下的地方是HRESULT APIENTRY MyIDirect3DDevice8::BeginScene(){return g_pD3DDevice->BeginScene();}HRESULT APIENTRY MyIDirect3DDevice8::EndScene(){if(pGame!=NULL) pGame->Render(); return g_pD3DDevice->EndScene();}我们的画图函数按道理讲要放到BeginScene()之后,但是我们不是写自己的3D游戏,而是在做外挂,程序是这么处理的:别人调用BeginScene();别人Render();别人调用EndScene();看看这个,我们把自己的pGame->Render();放到MyIDirect3DDevice8::BeginScene()里,结果就是自己的画图全被别人的图覆盖了,所有选择放到MyIDirect3DDevice8::EndScene()里去。到这里我们从诸仙得到的东西已经能满足我们的需求了,那我们就专心的干我们的事情吧,做外挂界面吧。4.游戏外挂界面处理类CGAME实现游戏外挂界面做外挂自己做个UI,估计没那必要,所以要选个UI,这里我选的是CEGUI来实现的。解释之前先来看看CEGUI做出来的最终效果:
至于怎么没读出一些人物信息,没办法,我的诛仙版本是很久以前的,也懒得升级,无法登陆,在这里说明问题就行了。我的CGame定义如下:#pragma once#include#include "d3dfont.h"#include "d3dpanel.h"#include#include#include#pragma comment (lib, "d3d8.lib")#pragma comment (lib, "d3dx8.lib")#pragma comment (lib, "dxguid.lib")#pragma comment (lib, "winmm.lib")#define _DWORD(name,address);/ DWORD *##name;void _##name(void){##name = (DWORD *)(##address+BaseAddress);};#define _WCHAR(name,address);/ wchar_t **##name;void _##name(void){##name = (wchar_t **)(##address+BaseAddress);};#define _DOUBLE(name,address);/ double *##name;void _##name(void){##name = (double *)(##address+BaseAddress);};#define INIT(ClassName) _##ClassName(DWORD _BaseAddress){BaseAddress = _BaseAddress;#define _INIT }#define init(name); _##name();#define pHp 0x254 //生命值偏移static DWORD BaseAddress = NULL;static bool focusflag = false;static int creatflag = 0;static CEGUI::String creat_str="";//全局函数static void AsciiToUtf8(char * AsciiStr,char * Utf8Str){//ascii转换成unicode CStringW strw; strw = CA2W(AsciiStr); //unicode转换成UTF8 DWORD dwMinSize; dwMinSize = WideCharToMultiByte(CP_UTF8, 0, strw, -1, 0,0,NULL,NULL); WideCharToMultiByte(CP_UTF8,0,strw,-1,Utf8Str,dwMinSize,NULL,NULL);}//人物基本信息class _HumInfo{public: //定义人物基本信息值 _WCHAR( name, 0x3a4 );//角色名字 _DWORD( id, 0x240 );//角色ID _DWORD( zy, 0x248 );//职业代码 _DWORD( lv, 0x24c );//等级 _DOUBLE(jy, 0x260 );//经验 double 8字节 _DWORD( hp, 0x254 );//生命 _DWORD( mp, 0x258 );//生命上限 _DWORD( hpmax, 0x26c );//真气 _DWORD( mpmax, 0x270 );//真气上限 _DWORD( skillmin, 0x2a4 );//最小攻击 _DWORD( skillmax, 0x2a8 );//最大攻击 _DWORD( fy, 0x2b0 );//防御 _DWORD( sd, 0x2b4 );//闪躲 _DWORD( si, 0x7b8 );//目标ID _DWORD( gold, 0x2d4 );//金钱 _DOUBLE( x, 0x3dc );//x坐标 _DOUBLE( y, 0x3e0 );//y坐标 //初始化人物基本信息值 INIT(HumInfo) init(name); init(id); init(zy); init(lv); init(jy); init(hp); init(mp); init(hpmax); init(mpmax); init(skillmin); init(skillmax); init(fy); init(sd); init(si); init(gold); init(x); init(y); _INIT};//周围人物/怪物static UINT GetBaseinfoProc(LPVOID pParam);class CGame{public: CGame(LPDIRECT3DDEVICE8 pD3DDevice); ~CGame(void); void Render(void); // 窗口消息处理 LRESULT WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lparam); _HumInfo *huminfo; struct BASEINFO //基本信息结构 {unsigned long int baseadd; unsigned long int base; //基地址 unsigned long int hummanbase; //人物基地址 }baseinfo; CEGUI::Window *gameGUI;private: CD3DFont * pfont; CD3DPanel * pPanel; LPDIRECT3DDEVICE8 g_pD3DDevice; D3DVIEWPORT8 Viewport; CWinThread* hThread; int s_W,s_H; float m_rotateY; CEGUI::DirectX81Renderer* myRenderer; void Setup2DCamera(int W, int H); void SetupGUI(void); bool TurnLeft(const CEGUI::EventArgs& e); bool TurnRight(const CEGUI::EventArgs& e); bool DoubleClick(const CEGUI::EventArgs& e); //关闭初始化窗口 bool CloseCreate(const CEGUI::EventArgs& e); //初始化确定 bool CGame::OkCreate(const CEGUI::EventArgs& e); bool GetHumanInfo(void); // 获得基本信息 bool GetBaseInfo(void); // 关闭人物信息窗口 bool CloseHumanInfo(const CEGUI::EventArgs& e); // 打开人物信息窗口 bool OpenHumanInfo(const CEGUI::EventArgs& e);public: // //线程退出标志 bool mExitThread;};CEGUI在CGame里是怎么运行起来的呢?在CGame初始化的时候,我调用了里面的SetupGUI()这个函数,开始初始化CEGUI.SetupGUI()如下:void CGame::SetupGUI(void){/// 初始化GUI资源的缺省路径 myRenderer = new CEGUI::DirectX81Renderer(g_pD3DDevice,0); new CEGUI::System(myRenderer); CEGUI::DefaultResourceProvider* rp = static_cast(CEGUI::System::getSingleton().getResourceProvider()); rp->setResourceGroupDirectory("schemes", "datafiles/schemes/"); rp->setResourceGroupDirectory("imagesets", "datafiles/imagesets/"); rp->setResourceGroupDirectory("fonts", "datafiles/fonts/"); rp->setResourceGroupDirectory("layouts", "datafiles/layouts/"); rp->setResourceGroupDirectory("looknfeels", "datafiles/looknfeel/"); //rp->setResourceGroupDirectory("lua_scripts", "../datafiles/lua_scripts/"); /// 设置使用的缺省资源 CEGUI::Imageset::setDefaultResourceGroup("imagesets"); CEGUI::Font::setDefaultResourceGroup("fonts"); CEGUI::Scheme::setDefaultResourceGroup("schemes"); CEGUI::WidgetLookManager::setDefaultResourceGroup("looknfeels"); CEGUI::WindowManager::setDefaultResourceGroup("layouts"); //CEGUI::ScriptModule::setDefaultResourceGroup("lua_scripts"); /// 设置GUI using namespace CEGUI; /// 得到GUI样式的图片集 Imageset* taharezlookImage; try{taharezlookImage = ImagesetManager::getSingleton().createImageset("TaharezLook.imageset"); }catch (CEGUI::Exception& exc) {AfxMessageBox(exc.getMessage().c_str()); } /// 设置鼠标图标// System::getSingleton().setDefaultMouseCursor(&taharezlookImage->getImage("MouseArrow")); /// 设置字体 FontManager::getSingleton().createFont("simhei-10.font"); /// 设置GUI皮肤 WidgetLookManager::getSingleton().parseLookNFeelSpecification("TaharezLook.looknfeel"); /// 载入GUI规划 SchemeManager::getSingleton().loadScheme("TaharezLook.scheme"); /// 得到窗口管理单件 CEGUI::WindowManager& winMgr = WindowManager::getSingleton(); /// 从layout文件中载入布局 gameGUI = winMgr.loadWindowLayout("TabControlDemo.layout"); /// 设置GUI的Sheet(Sheet是CEGUI中窗口的容器) System::getSingleton().setGUISheet(gameGUI); TabControl *tc = static_cast(winMgr.getWindow ("TabControlDemo/TabControl")); // Add some pages to tab control tc->addTab(winMgr.loadWindowLayout ("baseinfo.layout", "TabControlDemo/")); tc->addTab(winMgr.loadWindowLayout ("TabPage1.layout", "TabControlDemo/")); tc->addTab(winMgr.loadWindowLayout ("TabPage2.layout", "TabControlDemo/")); //设置主界面 ImagesetManager::getSingleton().createImagesetFromImageFile("ImageHP", "hp.bmp"); ImagesetManager::getSingleton().createImagesetFromImageFile("ImageMP", "mp.bmp"); ImagesetManager::getSingleton().createImagesetFromImageFile("ImageFACE", "face.bmp"); ImagesetManager::getSingleton().createImagesetFromImageFile("ImagePick", "pick.bmp"); ImagesetManager::getSingleton().createImagesetFromImageFile("ImageAttack", "attack.bmp"); ImagesetManager::getSingleton().createImagesetFromImageFile("ImageDig", "dig.bmp"); ImagesetManager::getSingleton().createImagesetFromImageFile("ImageRepair", "Repair.bmp"); winMgr.getWindow("TabControlDemo/BaseInfo/ImageHp")->setProperty("Image","set:ImageHP image:full_image"); winMgr.getWindow("TabControlDemo/BaseInfo/ImageMp")->setProperty("Image","set:ImageMP image:full_image"); winMgr.getWindow("TabControlDemo/BaseInfo/Face")->setProperty("Image","set:ImageFACE image:full_image"); winMgr.getWindow("TabControlDemo/BaseInfo/Imagegold")->setProperty("Image","set:ImagePick image:full_image"); winMgr.getWindow("TabControlDemo/BaseInfo/attack")->setProperty("Image","set:ImageAttack image:full_image"); winMgr.getWindow("TabControlDemo/BaseInfo/attack1")->setProperty("Image","set:ImageRepair image:full_image"); winMgr.getWindow("TabControlDemo/BaseInfo/attack2")->setProperty("Image","set:ImageDig image:full_image"); MultiColumnList* mclbox = static_cast(winMgr.getWindow("TabControlDemo/BaseInfo/BagItem")); mclbox->addRow(); mclbox->addRow(); mclbox->addRow(); mclbox->addRow(); mclbox->addRow(); mclbox->addRow(); mclbox->addRow(); mclbox->addRow(); mclbox->addRow(); mclbox->addRow(); mclbox->addRow(); mclbox->setItem(new MyListItem((CEGUI::utf8*)(LPCSTR)("狗皮膏药")),0,0); mclbox->setItem(new MyListItem("10"),1,0); mclbox->setItem(new MyListItem((CEGUI::utf8*)(LPCSTR)("狗皮膏药")),0,1); mclbox->setItem(new MyListItem("10"),1,1); mclbox->setItem(new MyListItem((CEGUI::utf8*)(LPCSTR)("狗皮膏药")),0,2); mclbox->setItem(new MyListItem("10"),1,2); mclbox->setItem(new MyListItem((CEGUI::utf8*)(LPCSTR)("狗皮膏药")),0,3); mclbox->setItem(new MyListItem("10"),1,3); mclbox->setItem(new MyListItem((CEGUI::utf8*)(LPCSTR)("狗皮膏药")),0,4); mclbox->setItem(new MyListItem("10"),1,4); mclbox->setItem(new MyListItem((CEGUI::utf8*)(LPCSTR)("狗皮膏药")),0,5); mclbox->setItem(new MyListItem("10"),1,5); mclbox->setItem(new MyListItem((CEGUI::utf8*)(LPCSTR)("狗皮膏药")),0,6); mclbox->setItem(new MyListItem("10"),1,6); mclbox->setItem(new MyListItem((CEGUI::utf8*)(LPCSTR)("狗皮膏药")),0,7); mclbox->setItem(new MyListItem("10"),1,7); mclbox->setItem(new MyListItem((CEGUI::utf8*)(LPCSTR)("狗皮膏药")),0,8); mclbox->setItem(new MyListItem("10"),1,8); mclbox->setItem(new MyListItem((CEGUI::utf8*)(LPCSTR)("狗皮膏药")),0,9); mclbox->setItem(new MyListItem("10"),1,9); mclbox->setItem(new MyListItem((CEGUI::utf8*)(LPCSTR)("狗皮膏药")),0,10); mclbox->setItem(new MyListItem("10"),1,10); winMgr.getWindow("TabControlDemo/")->hide(); winMgr.getWindow("GameGUI/Creat")->hide(); winMgr.getWindow("GameGUI/Creat/EDIT")->setText("100"); //建立事件监听 /// 设置鼠标事件自动重复 winMgr.getWindow("GameGUI/Button")->setWantsMultiClickEvents(false); winMgr.getWindow("GameGUI/Button")->setMouseAutoRepeatEnabled(true); //打开主窗口 winMgr.getWindow("GameGUI/Button")->subscribeEvent( CEGUI::Window::EventMouseButtonDown, CEGUI::Event::Subscriber(&CGame::TurnLeft, this)); //关闭主窗口 winMgr.getWindow("TabControlDemo/BaseInfo/Close")->subscribeEvent( CEGUI::Window::EventMouseButtonDown, CEGUI::Event::Subscriber(&CGame::TurnRight, this)); //关闭HUMANINFO窗口// winMgr.getWindow("GameGUI/HumanInfo/Close")->subscribeEvent(// CEGUI::Window::EventMouseButtonDown, // CEGUI::Event::Subscriber(&CGame::CloseHumanInfo, this)); //打开HUMANINFO窗口// winMgr.getWindow("GameGUI/Window//Item1/Item3")->subscribeEvent(// CEGUI::Window::EventMouseButtonDown, // CEGUI::Event::Subscriber(&CGame::OpenHumanInfo, this)); //关闭初始化窗口 winMgr.getWindow("GameGUI/Creat/CLOSE")->subscribeEvent( CEGUI::Window::EventMouseButtonDown, CEGUI::Event::Subscriber(&CGame::CloseCreate, this)); //初始化确定 winMgr.getWindow("GameGUI/Creat/OK")->subscribeEvent( CEGUI::Window::EventMouseButtonDown, CEGUI::Event::Subscriber(&CGame::OkCreate, this));}关于CEGUI不懂的还是老方法->google,我就不要讲太多了,现在太晚了,我还是快点写完睡觉。这段程序里的解释也够多,我要讲的就是如何使CEGUI和诸仙的鼠标键盘事件联系起来和CEGUI如何和诸仙联系起来。myRenderer = new CEGUI::DirectX81Renderer(g_pD3DDevice,0);这里CEGUI已经取得了D3D的设备接口了,只要在CGame的 Render加入CEGUI的Render就行了,记住必须等你的CEGUI初始化完了你才开始 CEGUI::System::getSingleton().renderGUI(),CGame的Render在前面已经运行去来了,不记得的大家到 前面去看看)。程序如下:void CGame::Render(void){static DWORD m_dwFrames = 0; static DWORD m_dwStartTime = timeGetTime(); char buffer[255]; DWORD dwDuration = (timeGetTime() - m_dwStartTime) / 1000; if(dwDuration > 0) {sprintf(buffer, "TEST: %d seconds. Frames: %d. FPS: %d.", dwDuration, m_dwFrames, (m_dwFrames / dwDuration)); } else {sprintf(buffer, "Calculating..."); } pfont->DrawText(buffer, 3, 3, D3DCOLOR_XRGB(0, 0, 0 )); pfont->DrawText(buffer, 3, 2, D3DCOLOR_XRGB(0, 0, 255)); CEGUI::System::getSingleton().renderGUI(); m_dwFrames++;}和诸仙的鼠标键盘事件联系起来看看下面一段你就明白了。extern "C" void PASCAL EXPORT S_hWnd(void){HWND shWnd = GetForegroundWindow(); Zx_OldWinFunc = SetWindowLong(shWnd,GWL_WNDPROC,(long)&WindowFunc); //以下防止该线程过早结束,导致WindowFunc提前失效 while(1) {Sleep(3000); }}//开始新的消息循环LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lparam){ if(pGame->WindowFunc(hwnd,message,wParam,lparam)) return ::CallWindowProc((WNDPROC)Zx_OldWinFunc,hwnd,message,wParam,lparam); //默认的消息交给原来的消息处理函数处理 else return 1;}// 窗口消息处理,让Game将窗口消息监听起来LRESULT CGame::WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lparam){switch(message) {case WM_MOUSEMOVE: if(CEGUI::System::getSingleton().injectMousePosition(static_cast(LOWORD(lparam)), static_cast(HIWORD(lparam)))) return 0; break; case WM_LBUTTONDOWN: if(CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI::LeftButton)) return 0; break; case WM_LBUTTONUP: if(CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI::LeftButton)) return 0; break; case WM_CHAR: if(wParam<48||wparam>57) break; if(CEGUI::System::getSingleton().injectChar(wParam)) return 0; break; case WM_KEYDOWN: if(CEGUI::System::getSingleton().injectKeyDown(static_cast(wParam))) return 0; break; case WM_KEYUP: if(CEGUI::System::getSingleton().injectKeyUp(static_cast(wParam))) return 0; break; } if(focusflag) return 0; return 1;}写到这里,相信大家已经能够用这种方法在D3D游戏中能够真正的做出D3D窗口的外挂了,我也了了以前说的要给出方法的许诺。时间仓促,写的不好,错误是肯定有的,有错误大家跟贴指正,不要骂人哈。喜欢写点小程序的加我QQ:34187280 烂人哭吧
标签: 狗皮膏药
相关推荐:
精彩放送:
- []天天微头条丨小纹身价格一般多少钱?小纹身价格介绍
- []环球新动态:会议电话的组成是什么?会议电视系统有哪些?
- []白了少年头的上一句是什么?白了少年头出自哪里?
- []环球短讯!关于紫石英事件你了解多少?关于紫石英事件的介绍
- []威胁的近义词是什么?威胁的近义词有哪些?
- []墓土彩虹在哪里?墓土彩虹相关内容介绍
- []【天天聚看点】历史上的李温把皇位传给了谁?详情介绍
- []淘宝超级店长是什么?超级店长适用于所有淘宝网店
- []李焕英真实人物是谁?是谁的原型怎么发生意外的?
- []电脑假死怎么办?电脑假死的三种解决方法
- []天天资讯:哪家的移动电源做的好?泓能移动电源价格介绍
- []cmd命令提示符详细介绍
- []全球即时:全员加速中猎人军团 全员加速中猎人名单
- []tooky京崎手机手绘密码忘记了怎么办?解锁教程了解一下
- []唐山12中和23中高中哪所学校好?两校实力旗鼓相当
- []环球快讯:三星S5830i内存不足怎么办?刷机教程来了
- []关于大熊猫的资料大全300字 你知道多少?
- []视焦点讯!白景屹和刘柏辛分手了没有?刘柏辛和小白什么时候在一起的?
- []今日快看!一台电脑多少瓦?电脑功耗如何?
- []天天信息:梢棒是什么意思?梢棒的详情介绍
- []景甜到底什么背景?景甜个人资料介绍?
- []今日要闻!无线路由是什么?无线路由有哪些应用?
- []今日热门!dota2为什么一直显示连接至游戏协调服务器中?原因分析
- []世界动态:课外常识:夏天的英文单词怎么说?夏天的英文单词介绍
- []安卓设备的USB周边和安卓USB配件如何调试?具体操作方法
- []【环球时快讯】动态语言:C、PHP、Perl、Ruby哪个更适合你?
- []今日看点:洛克王国果子怎么得?洛克王国手游V3.2安卓版
- []今日精选:最后的勇士讲述了什么故事?最后的勇士剧情介绍?
- []天天看热讯:2016笔记本哪款销量好?2016笔记本销量排行榜大全
- []当前热讯:慧通V8机动车检测站收费管理软件 实现数据电子化
- []【环球新视野】QQ如何使用声卡?QQ检测不到声音怎么办?
- []每日视讯:什么是车载gps终端?车载GPS终端有什么作用?
- []如何解决家中的无线信号覆盖问题?wifi无线覆盖解决方案
- []世界热文:七个巧克力怎么分给三个人?七招巧很多
- []当前要闻:三极管进入截止区与饱和区的条件及制作方法
- []精选!CentOS怎么升级Proftpd?CentOS升级Proftpd教程
- []每日报道:浙江理工大学在杭州什么位置?浙江理工大学资料介绍?
- []ppt中的控件工具箱——ShockwaveFlash
- []如何用ghost进行一键还原?六个步骤教你正确使用
- []【世界时快讯】宁波大榭島有哪些景点?宁波大榭島附近的景点介绍?
- []天天实时:教你用4种方法实现项目目录中的界面功能
- []全球快看点丨擦玻璃神器有哪些?擦玻璃神器汇总?
- []什么是SEM?SEM和SEM有什么区别?
- []通讯!Windows生态系统:限制用户的应用程序
- []天天观点:yydsNginx–无root权限安装(内网安装)
- []当前滚动:dns输入错误怎么办?dns设置错误解决办法
- []umd是什么格式?umd格式怎么打开?
- []全球热议:矣怎么组词?矣的组词有哪些?
- []当前信息:苹果ipad3 ios6.1怎么越狱?苹果ipad3 ios6.1越狱教程介绍
- []珠海吉林大学在哪里?珠海吉林大学怎么样?
- []看热讯:【技术】空间光调制器与激光加工技术的应用介绍
- []每日关注!如何安装HTC更新实用程序?Android手机更新实用程序(RUU)的使用方法
- []环球快报:驱动到底是什么?我们应该如何安装和更新驱动?
- []当前头条:CSS文件中的中文字体名称怎么写?CSS常用的中文字体名称对照表
- []世界今亮点!Win10怎么关闭自动更新?Win10关闭自动更新方法
- []环球最新:华为g525可以刷鸿蒙系统吗?华为g525强刷官方rom系统的教程
- []热点在线丨商标买卖网站哪个靠谱?尚标商标转让网商标购买平台
- []解析ElasticSearch ElasticSearch字段类型解析
- []当前观点:互联网广告表现形式有哪些?一文读懂互联网广告分类及收费方式
- []【热闻】博彩股集体走强 澳门3月博彩毛收入127.38亿澳门元
- []ClamAV病毒扫描工具怎么安装?ClamAV3.扫描工具安装使用教程
- []世界聚焦:如何设置默认浏览器?谷歌浏览器设置默认Tip流程
- []【世界时快讯】港股内房股多数上涨 裕田中国涨超8%、中海涨超7%
- []当前滚动:浙江余姚工业园区建设公司4亿中票回售 并调整利率至3.50%
- []SEO优化中如何利用爱站工具去分析搜索引擎蜘蛛?
- []环球视点!天山铝业:截止3月31日公司股东人数71783人
- []阳澄湖滨酒店和新江南8.51亿元商业ABS更新至“已受理”
- []【全球新要闻】博主探店变“探钱”,消费者避雷变“踩雷”
- []焦点热文:4月3日限售股解禁一览(名单)
- []环球今亮点!周口城投10亿元私募债项目更新至“已受理”
- []世界快播:金能科技:截至2023年3月31日,公司股东户数共42007户
- []世界讯息:三川智慧:截至3月31日,公司股东总数是30,425户
- []环球观热点:青海华鼎:截止2023年3月31日公司股东人数为31900名
- []当前焦点!最牛大赚400%!刚刚 基金公司长期业绩榜单来了
- []【全球时快讯】思南人B队0-3金海绿化 罗志伟取得进球
- []天天热消息:邮轮出境游重新起航,上海、深圳率先试点恢复
- []全球新动态:厌倦上班的年轻人,辞职开民宿:本以为要亏本,却意外爆满
- []即时:哈登带伤出战,大帝陷入重围,76人季后赛敲响警钟
- []国瑞健康:2022年实现收入33.4亿元
- []世界速读:朗诗绿色管理:2022年归属股东净亏损25.88亿元
- []节能铁汉:公司正在按照相关程序推进以简易程序向特定对象发行股票事项
- []观热点:聚焦IPO | 四月第一周再迎10家新股申购,客户依赖问题需重点关注
- []全球今热点:唐人神:公司截至3月31日的股东人数将在2023年一季报中披露,还
- []大地海洋:截至2023年3月31日,公司共有股东3611户
- []环球微资讯!运机集团:您好投资者,截止3.31公司股东人数为10354户
- []个人养老金投资最新成绩出炉 七成养老FOF跑输基准
- []估值持续修复 基金一季度业绩迎“开门红”
- []全球快看点丨派息分红是利好还是利空
- []每日时讯!炒股会亏钱吗
- []信息:外资机构大举加仓ETF 新锐基金经理产品成自购热门
- []美团企业版即将上线;阿里商旅推出因私预订功能 | 一周商旅动态
- []全球快看点丨国债逆回购周五买几天合算
- []每日精选:萌翻啦!第十七届华南(广州)宠物嘉年华在华农举行
- []每日速递:光储那通事 | 户用光储系统,你选对了吗?
- []全球实时:最快4.8年可回本!光伏巨头户用光储系统经济性分析
- []环球实时:美股期指什么意思
- []今热点:投资也有“鄙视链”?不怕被“看不起” 这只超级牛基创造了传奇!
- []天天通讯!九安医疗为什么涨这么多
- []【全球新要闻】银河证券:当前阶段银行板块估值性价比高 配置价值凸显
- []环球即时:缴费基数是啥意思,参保人缴纳社会保险的基本基数
- 医无忧保险具体条款
- 两部门发文要推进的“带押过户”到底是什么?
- 【全球时快讯】2022现在车险可以提前多久买,最少30天
- 每日速读!西安雁塔区推出2宗共148亩商住用地 挂牌截止时间为5月6日
- “带押过户”全面推广 已有百余城开闸
- 雅居乐获授23.08亿港元及3693.6万美元定期贷款融资
- 不断加码,贝壳累计回购金额近2.3亿美金
- 全球焦点!职工医保余额怎么查询
- 全球观焦点:公积金租房提取多久可以申请一次,三个月
- 康师傅方便面:长期稳健经营,多元细分产品塑造竞争优势
- 在元宇宙里,咏声动漫正在掀起新生代文化娱乐热潮
- 在元宇宙里,咏声动漫正在掀起新生代文化娱乐热潮
- 当前聚焦:k线怎么看涨跌
- 全球观点:跌停板吸筹的特征
- 动态:五行火行业比较有前景的行业
- 【全球播资讯】股票市场是什么
- 热点评!三峡能源股票前景怎么样
- 【世界速看料】玉米面营养价值及功效_玉米的营养价值及功效与作用
- 世界热头条丨中指研究院企业研究总监刘水:前3月重点房企销售出现正增长
- 世界最资讯丨标榜股份:公司主营业务为汽车尼龙管路及连接件等系列产品的研发、生产和销售
- 【焦点热闻】阿里变阵,飞猪“提前开跑”;东呈推出超级IP青猫 | 一周速览
- 世界聚焦:4月新规来了
- 【环球速看料】闰土股份:截至2023年3月31日,公司的股东人数为37,556
- 天天热门:鹏华基金经理金笑非:医药板块开启投资新周期 中国创新药未来三五年会成为全球高地
- 环球快资讯丨亚朵连续四年盈利;百度仍为携程最大股东 | 大公司简报
- 【天天新要闻】新纽科技完成稳中求进 2022年实现收入及净利润双增长
- 首席经济学家七人谈:二季度GDP同比增速或超7% 财政货币政策将继续发力
- 【播资讯】纳斯:等赛季结束会花几周时间考虑去留
- 天天通讯!3月基金发行迎“小阳春” 增量资金等待时机进场
- 热点在线丨重磅!2022年公募基金年报数据全解!
- 奕东电子:公司的动力电池管理系统FPC根据设计和要求可与各类电池进行适配
- 天天即时:*ST皇台:待公司2022年年度报告披露后,若符合深交所股票上市规则的相关规定,公司会向深交所提出申请
- 当前速读:加满一箱油少花13元!油价迎今年来最大降幅
- 爱仕达:公司暂未涉及乡村振兴相关的业务
- 首批试点!市中医院入选胃癌规范化诊疗“国家队”
- 【环球新视野】德信中国:2022年总收入约人民币221.45亿元
- 全球快播:给宝宝买保险怎么选择
- 环球微头条丨公积金第三次贷款条件
- 富力地产:2022年实现收入352亿元
- 如何根据身材挑选T恤衫 怎么根据身材挑选T恤衫
- 每日时讯!明发集团:2022年综合收入约105.684亿元
- 环球简讯:绿地香港:2022年实现收入266.14亿元
- 【环球聚看点】通鼎互联:公司密切关注6G技术发展方向,未来将结合主营业务适时布局相关产品及解决方案
- 当前滚动:支付宝申请失业补助金成功后怎么领取
- 华侨城亚洲:2022年权益持有人应占亏损约19.13亿元
- 国寿财是哪个保险公司
- 第三者责任险只赔人不赔车吗,都赔
- 世界消息!诈骗5万元能判几年_5万元左右最好的车
- 正荣服务:2022年实现收入11.41亿元
- 天天视点!灰谷狩猎的三个怪在线观看_灰谷狩猎的三个怪
- 快看点丨亿达中国:2022年收入为人民币45.32亿元
- 播报:市场下行期,融创仍稳步降负债:2022年整体有息负债减少642亿
- 【环球新要闻】农业银行2022年归母净利2591.40亿 2023年力争新增县域贷款超万亿
- 环球信息:合景泰富2022全年按权益合并收入约为人民币224.62亿元
- 全球今日报丨福晟国际:2022年收入约为人民币17.93亿元
- 大悦城地产:2022年物业开发收入同比增长130.6%
- 融信服务:2022年总收益约为人民币8.76亿元
- 每日短讯:本钢板材:公司会按照季度报告披露要求,在规定时间内披露
- 顺络电子:3月30日公司高管袁金钰减持公司股份合计321.19万股
- 消息!港龙中国2022年业绩:稳健经营,提质增效
- 环球热文:远大中国:2022年收入约人民币14.71亿元
- 每日动态!佳云科技控股股东所持1.35亿股股份被司法冻结,持股方为佳兆业商业集团
- 北京市挂牌两宗住宅用地,总起拍价56.3亿元,涉及大兴区、丰台区
- 保利发展2022年报:穿越行业周期波动 企稳高质量发展之路
- 【环球快播报】港龙中国地产:2022年收益约为人民币118.92亿元
- 全球播报:中国三迪:2022年总收入约为人民币34.49亿元
- 天天关注:大悦城地产:2022年实现收入208.31亿元
- 中泰证券发布中泰财富与家族信托等金融服务
- 保利发展:3月31日公司高管黄海增持公司股份合计2万股
- 三立期货3月31日基差:一张图尽览有色金属、黑色系、能源化工和农产品基差
- 环球观天下!国锐地产:2022年亏损约3.2亿港元
- 新资讯:宋都服务:2022年实现收入2.68亿元
- 环球今亮点!荣万家:2022年归属股东净利润2.35亿元
- 远洋服务:2022年归属股东净利润人民币7540万元
- 雅化集团:业绩预告的发布有相应的规则和时间要求,具体信息您可上网查询和了解
- 今日讯!ST步森股民索赔时效不足4个月 此前已有获赔案例
- 世界快消息!买房卖房大消息!"带押过户"全国全面推进!北京正式启动,100多地市已开展
- 维金加德推出了与热门电视剧维京人合作的第二部分
- 【天天新视野】从可用座位公里,看航空市场过去25年的变化
- 环球焦点!超级IP青猫出道,东呈互联网化又下一棋
- 焦点热门:旅行社入境团队游今起恢复,入境航班搜索热度增长370%
- 环球聚焦:香港旅游业复苏推动航空运力增长,但全面恢复并不容易
- 当前滚动:世茂集团:2022年全年业绩及2022年年报延迟刊发及寄发
- 全球关注:上坤地产:延迟刊发2022年经审核末期业绩
- 财报金选|杨惠妍:在分化市场中寻找确定性
- 罗牛山:各行各业的采购方会对投标企业设立不同情况的资格门槛,要求投标单位具备各种其所需的条件
- 每日关注!云南能投:截至目前公司未收到任何大股东有关减持的通知
- 天天最新:财报金选丨领地控股2022年收益达139.79亿元 毛损19.996亿元
- 世界要闻:财报金选丨弘阳地产2022年总收入200.13亿元 录得毛利16.66亿元
- 全球焦点!国林科技:公司新疆晶体乙醛酸项目采用釜式反应装置
- 天天即时看!华兰疫苗:2022年度公司流感疫苗产品的整体毛利率为88.49% 占营业收入的比重为99.56%
- 勇闯元宇宙,这家动漫公司破势生长
- 让元宇宙更好玩,咏声动漫是认真的!
- 让元宇宙更好玩,咏声动漫是认真的!
- 煤矿截断护林水,六旬老汉跪地引关注,谁的锅?
- 环球看热讯:浙江温州:鼓励新增的海上风电、集中式光伏电站建设或购买新型储能(服务)
- 快速大爆发的逆变器龙头,德业股份在光储行业的逆袭
- 当前关注:580亿!海辰储能获工商银行授信!
- 石油行业的春天来了?
- 环球看热讯:中交地产:拟发行7亿元公司债券