| |
|
|
HowTo 1: Show an ingame info screen (a simple bitmap) -- Section: Proxy-Dll --
Okay, you got familiar with the proxy-dll concept so far ? Fine. In this HowTo, we'll try to add an "ingame info screen" to a DirectX 9 application (I use the Flatspace Demo for testing). Please note
that you need the DX9 SDK with the Summer2004 update.
Based on the "basic proxy-dll implementation" (see downloads page), we'll add a partly
transparent texture and show it ingame. For the sake of simplicity, I do not cover switching this feature on or off using a keyboard hook. It is always on.
- To keep things a bit straight, we add a new class CmyOwnStuff to the project, and delete the
myIDirect3DDevice9::ShowWeAreHere routine (and the call within ::Present, of course). Ensure the CmyOwnStuff receives a pointer to the dll-internal IDirect3DDevice9 and stores it.
- Create a fancy 256x128 bitmap (*.bmp), and paint all soon-to-be transparent areas as black (0/0/0). Add this bitmap as a resource to your project.
- To show this bitmap ingame, we'll create a ID3DXSprite Object. Using textured triangles would work aswell. I just like the Sprite thingy, though.
- Add a ID3DXSprite* to your CmyOwnStuff. Create the Sprite in the Constructor, and release it within the Destructor.
- Add a IDirect3DTexture9* to CmyOwnStuff. Load your fancy bitmap from the resource, while in the Constructor, and release it within the Destructor.
- Add a public CmyOwnStuff::Render routine. Here we'll draw the Sprite using the
ID3DXSprite::Draw method.
- Now we need to ensure that our sprite object is drawn every time the routine myIDirect3DDevice9::Present is called. So, add an CmyOwnStuff pointer to myIDirect3DDevice9. Create the CmyOwnStuff Object once (I do this within ::Present), and delete it withinmyIDirect3DDevice9::Release. Don't forget to set the
OwnStuff pointer to NULL in the myIDirect3DDevice9 Constructor.
- Hang on, work is nearly finished. As we created the texture for the background as D3DPOOL_MANAGED (believe me, we did), there is no need to take care of it if the DirectX device is in lost state (e.g. when someone tabs out). We need to cover the sprite object, though. So, add two new public routines to CmyOwnStuff: OnLostDevice and OnResetDevice. Call the corresponding routines from ID3DXSprite there. Ensure that CmyOwnStuff::OnLostDevice and CmyOwnStuff::OnResetDevice get called frommyIDirect3DDevice9 (I use the ::Reset for this). Another way (and probably less prone to errors) is to create the ID3DXSprite Object on every render pass (and delete it afterwards). This increases impact on the fps, though.
Well, basically, this is the way I chose to add own content to a DirectX application. You may want to add several security checks. Remember if something fails within your added code, the application will most probably break, leaving a lot of memory garbage on the system.
Code fragments as discussed above (the project source is available at the downloads page):
myOwnStuff.h
#pragma once
#include <d3dx9core.h>
class CmyOwnStuff
{
public:
CmyOwnStuff(IDirect3DDevice9 *pD3DDevice);
~CmyOwnStuff(void);
void Render(void);
void OnLostDevice(void);
void OnResetDevice(void);
private:
IDirect3DDevice9* m_pD3DDevice;
ID3DXSprite* m_pBackgroundSprite;
IDirect3DTexture9* m_pBackgroundTexture;
}; |
myOwnStuff.cpp
#include "StdAfx.h"
#include ".\myownstuff.h"
CmyOwnStuff::CmyOwnStuff(IDirect3DDevice9 *pD3DDevice)
{
extern HINSTANCE gl_hThisInstance;
m_pD3DDevice = pD3DDevice;
m_pBackgroundSprite = NULL;
m_pBackgroundTexture = NULL;
D3DXCreateSprite(m_pD3DDevice,&m_pBackgroundSprite);
D3DXCreateTextureFromResourceEx(m_pD3DDevice,
gl_hThisInstance,
MAKEINTRESOURCE(IDB_BITMAP1),
256,
128,
0,
NULL,
D3DFMT_UNKNOWN,
D3DPOOL_MANAGED,
D3DX_FILTER_NONE,
D3DX_FILTER_NONE,
0xFF000000,
NULL,
NULL,
&m_pBackgroundTexture);
}
|
CmyOwnStuff::~CmyOwnStuff(void)
{
if (m_pBackgroundSprite) m_pBackgroundSprite->Release();
if (m_pBackgroundTexture) m_pBackgroundTexture->Release();
}
|
void CmyOwnStuff::Render(void)
{
m_pD3DDevice->BeginScene();
m_pBackgroundSprite->Begin(NULL);
m_pBackgroundSprite->Draw(m_pBackgroundTexture,
NULL,
NULL,
NULL,
D3DCOLOR_ARGB(0xaa,0xff,0xff,0xff));
m_pBackgroundSprite->End();
m_pD3DDevice->EndScene();
}
|
void CmyOwnStuff::OnLostDevice(void)
{
m_pBackgroundSprite->OnLostDevice();
}
|
void CmyOwnStuff::OnResetDevice(void)
{
m_pBackgroundSprite->OnResetDevice();
} |
myIDirect3DDevice9.cpp
HRESULT myIDirect3DDevice9::Present(...)
{
// we may want to draw own things here before flipping surfaces
// ... draw own stuff ...
if (!m_pMyOwnStuff) m_pMyOwnStuff = new CmyOwnStuff(m_pIDirect3DDevice9);
if (m_pMyOwnStuff) m_pMyOwnStuff->Render();
// call original routine
HRESULT hres = m_pIDirect3DDevice9->Present( pSourceRect,
pDestRect,
hDestWindowOverride,
pDirtyRegion);
return (hres);
} |
HRESULT myIDirect3DDevice9::Reset(...)
{
if (m_pMyOwnStuff) m_pMyOwnStuff->OnLostDevice();
if (m_pMyOwnStuff) m_pMyOwnStuff->OnResetDevice();
return(m_pIDirect3DDevice9->Reset(pPresentationParameters));
} |
|
|
|
|
|