天马阁

 找回密码
 立即注册
                                        →→→→→→→→→→→→ 1点击查看所有VIP教程目录长列表(总教程数269个) 2办理VIP详情进入 ←←←←←←←←←←←←
1 x64CE与x64dbg入门基础教程 7课 已完结 2 x64汇编语言基础教程 16课 已完结 3 x64辅助入门基础教程 9课 已完结 4 C++x64内存辅助实战技术教程 149课 已完结
5 C++x64内存检测与过检测技术教程 10课 已完结 6 C+x64二叉树分析遍历与LUA自动登陆教程 19课已完结 7 C++BT功能原理与x64实战教程 29课 已完结 8 C+FPS框透视与自瞄x64实现原理及防护思路 30课完结
64驱?封? 9 64反驱? 10 64位V? 11 绝? 12 ???课?
13 64透 ? 14 64U ? 15 64Q ? 16 64功 ?
17 64U ? 18 64模 ? 19 64多 ? 20 64网 ?
21 64注 ? 22 64火 ? 23 64棋 ? 24 64自二链L?
25 64破 ? VIP会员办理QQ: 89986068   
【请先加好友,然后到好友列表双击联系客服办理,不然可能无法接受到信息。】
27 加入2000人交流群637034024 3 28 免责声明?
查看: 4249|回复: 0

诸仙D3D游戏环境下如何实现真正D3D的窗口,给出关键代码...

[复制链接]

10

主题

0

回帖

12

积分

编程入门

Rank: 1

天马币
20
发表于 2024-3-2 09:57:14 | 显示全部楼层 |阅读模式
前些日子一直忙,也没来看看,说要给出代码和方法的一直没有给出来请大家见谅,今天给出来!  
声明:我不是做游戏智辅的,所以对智辅部分还比较薄弱,没做,只做实现窗口这一块!
  

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,π);  
}


“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")
// CZxDllApp

BEGIN_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 <d3d8.h>
#include "d3dfont.h"
#include "d3dpanel.h"
#include <d3dx8.h>
#include <mmsystem.h>
#include <RendererModules/directx81GUIRenderer/renderer.h>

#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:irectX81Renderer* 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:irectX81Renderer(g_pD3DDevice,0);
    new CEGUI::System(myRenderer);
    CEGUI:efaultResourceProvider* rp = static_cast<CEGUI:efaultResourceProvider*>
        (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<TabControl *>(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<MultiColumnList*>(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:irectX81Renderer(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<float>(LOWORD(lparam)), static_cast<float>(HIWORD(lparam)))) return 0;
        break;
    case WM_LBUTTONDOWN:
        if(CEGUI::System::getSingleton().injectMouseButtonDown(CEGUI:eftButton)) return 0;
        break;
    case WM_LBUTTONUP:
        if(CEGUI::System::getSingleton().injectMouseButtonUp(CEGUI:eftButton)) 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<unsigned int>(wParam))) return 0;
        break;
    case WM_KEYUP:
        if(CEGUI::System::getSingleton().injectKeyUp(static_cast<unsigned int>(wParam))) return 0;
        break;
    }
    if(focusflag) return 0;
    return 1;

}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

天马阁|C/C++辅助教程|安卓逆向安全| 论坛导航|免责申明|Archiver||网站地图
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表天马阁立场!
任何人不得以任何方式翻录、盗版或出售本站视频,一经发现我们将追究其相关责任!
我们一直在努力成为最好的编程论坛!
Copyright© 2010-2021 All Right Reserved.
快速回复 返回顶部 返回列表