諸仙D3D遊戲環境下如何實現真正D3D的窗口

諸仙D3D遊戲環境下如何實現真正D3D的窗口,給出關鍵代碼及其方法(希望大家在D3
D遊戲中做出D3D窗口)!
前些日子一直忙,也沒來看看,說要給出代碼和方法的一直沒有給出來請大家見諒,今天給出來!  
聲明:我不是做遊戲外掛的,所以對外掛部分還比較薄弱,沒做,只做實現窗口這一塊!  
 
1.先看實現的圖片,等下慢慢解釋。 
 
 
 
2.首先解釋要如何啓動諸仙的進程。  
我們要想擁有自己的窗口,那麼就必須在諸仙的進程啓動之前得到Direct3DCreate8接口(諸仙用Direct
3D8)。所以啓動過程如下:  
 
//啓動諸仙並獲取諸仙進程句柄  
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類型,這個類主要是打開進程和取得進程的一些信息,GetPr
ocess()取的改進程的句柄。這個類裏面要解釋下的是: 
 
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_REA
DWRITE);  
::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, lpRemote
DllName, 0, NULL);  
if(hRemoteThread == NULL)  
{  
  ::CloseHandle(hProcess);  
  return FALSE;  
}  
::CloseHandle(hRemoteThread);  
return TRUE;  
}  
 
這段關鍵是在:  
 
// 啓動遠程線程  
::ResumeThread(ZhuXianProc.GetThread());  
HANDLE hRemoteThread = ::CreateRemoteThread(hProcess, NULL, 0, pfnStartRoutine, lpRemote
DllName, 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給變成了新的入口地址NewDirect3DCreat
e8了,那麼當諸仙運行的時候這個函數就跑到我們的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 HO
OK 獲得Direct3DDevice8(D3D 設備) 的接口的指針從而得到我們的Render該放到什麼地方。 
COM HOOK其實就是寫一個同樣的類用來替換COM的VTable,不做詳細的解釋,實在搞不懂就googl
e(俺也是這麼得來的:))。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_IDENTI
FIER8* pIdentifier); 
    UINT APIENTRY  GetAdapterModeCount(UINT Adapter); 
    HRESULT APIENTRY EnumAdapterModes(UINT Adapter,UINT Mode,D3DDISPLAYMODE* pMo
de); 
    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,D3DFORM
AT 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,D3DF
ORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat); 
    HRESULT APIENTRY GetDeviceCaps(UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS8* p
Caps); 
    HMONITOR APIENTRY  GetAdapterMonitor(UINT Adapter); 
    HRESULT APIENTRY CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWi
ndow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDe
vice8** 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的C
reateDevice函數如何定義: 
 
HRESULT APIENTRY MyIDirect3D8::CreateDevice(UINT Adapter,D3DDEVTYPE DeviceType,HWND
 hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,I
Direct3DDevice8** ppReturnedDeviceInterface) 

    static MyIDirect3DDevice8 * id3dd8 = NULL; 
 
    HRESULT m = lpD3D->CreateDevice(Adapter,DeviceType,hFocusWindow,BehaviorFlags,pPresen
tationParameters,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的裏面的內容,我們也採用同樣方法的偷粱換柱子。MyIDir
ect3DDevice8定義就不再貼出來了,浪費頁面。要解釋下的地方是 
 
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::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::DefaultResourceProvider*> 
        (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::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<float>(LOWORD(lparam)),
static_cast<float>(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<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; 

 
寫到這裏,相信大家已經能夠用這種方法在D3D遊戲中能夠真正的做出D3D窗口的外掛了,我也了了以
前說的要給出方法的許諾。 
時間倉促,寫的不好,錯誤是肯定有的,有錯誤大家跟貼指正,不要罵人哈。 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章