| 
 
 IntroductionThis page provides source code for a framework for developing graphics
applications using DirectX 8.  The framework provides a quick starting
point, while not imposing any high level functionality. 
 Using the FrameworkTo use the framework, you will need to write a minimum of three functions: 
 The framework is written under Visual C++ 6.0, and has not yet been compiled on other compilers. There is no guarantee of fitness for other compilers, and may require modification. If anyone adapts this for another compiler, I'd love to hear about it, and possibly post it here with your permission. Direct this or other comments to rdunlop@mvps.org. YOURPROGRAM.CPP#include "stdafx.h"
DXContext *lpDX=NULL;
static char szClass[] = "YourProgramClass";
static char szCaption[] = "Your Program";
void render_frame(float elapsed)
{
    lpDX->lpDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0x00000000,1.0f,0);
    if (D3D_OK==lpDX->lpDevice->BeginScene()) {
        // Place your rendering code here
        lpDX->lpDevice->EndScene();
    }
    lpDX->lpDevice->Present(NULL,NULL,NULL,NULL);
}
void Cleanup()
{
    if (lpDX)
        lpDX->Cleanup();
}
LRESULT CALLBACK 
WindowProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_DESTROY:
            Cleanup();
            PostQuitMessage(0);
            break;
        case WM_SIZE:
            // clear or set activity flag to reflect focus
            if (lpDX) {
                if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
                    lpDX->active = FALSE;
                else
                    lpDX->active = TRUE;
            }
            break;
        case WM_KEYUP: 
            switch (wParam) { 
                case VK_ESCAPE:
                    // exit the program on escape
                    DestroyWindow(hWnd);
                    break;
            } 
            break;
        default:
            return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0L;
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
    // create application handler and link to our WindowProc
    lpDX=new DXContext(hInstance,szClass,szCaption,WindowProc);
    if (!lpDX)
        return FALSE;
    // check for error
    if (lpDX->lastErr!=S_OK) {
        delete lpDX;
        return FALSE;
    }
    // initialize full screen graphics to 640 x 480 x 32 bit, with 2 back buffers
    if (!lpDX->Init(640,480,16,2,TRUE)) {
        delete lpDX;
        return FALSE;
    }
    // run the game loop, passing pointer to our rendering routine
    lpDX->Run(render_frame);
    SafeDelete(lpDX);
    return TRUE;
} 
STDAFX.H
#include <windows.h>
#include <mmsystem.h>
#include <d3d8.h>
#include <d3dx8.h>
#include <d3dx8mesh.h>
#include "dxcontext.h"
#define SafeRelease(x) if (x) {x->Release(); x=NULL;}
#define SafeDelete(x) if (x) {delete x; x=NULL;} 
DXCONTEXT.H
class DXContext 
{
    public:
        void SetRenderFunc(void (*ptr)(float));
        BOOL TestDepth(D3DFORMAT fmt);
        BOOL TestFormat(D3DFORMAT fmt);
        void (*renderPtr)(float);
        DXContext(HINSTANCE hInstance,LPCSTR pClass,LPCSTR pCaption,WNDPROC pProc);
        ~DXContext();
        BOOL Init(WORD wWidth,WORD wHeight,WORD wDepth,WORD wBackBuffers,BOOL bWindowed);
        int Run(void (*ptr)(float));
        void Cleanup();
        HRESULT hRes;
        HRESULT lastErr;
        D3DFORMAT format;
        D3DFORMAT zFormat;
        WORD height;
        WORD width;
        LPDIRECT3D8 lpD3D;
        LPDIRECT3DDEVICE8 lpDevice;
        BOOL active;
        HWND hwnd;
};
#define DXC_ERR_REGWIN -2
#define DXC_ERR_CREATEWIN -3
#define DXC_ERR_CREATE3D -4
#define DXC_ERR_GETFORMAT -5
#define DXC_ERR_FORMAT -6
#define DXC_ERR_CREATEDEV -7
DXCONTEXT.CPP#include "stdafx.h"
#include "DXContext.h"
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"d3d8.lib")
#ifdef _DEBUG
    #pragma comment(lib, "d3dx8d.lib")
#else
    #pragma comment(lib, "d3dx8.lib")
#endif
DXContext:: DXContext(HINSTANCE hInstance,LPCSTR pClass,LPCSTR pCaption,WNDPROC pProc)
{
    WNDCLASS wc;
    // clear the error register
    lastErr=S_OK;
    // clear the active flag
    active=FALSE;
    // Set up and register window class
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = (WNDPROC) pProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = sizeof(DWORD);
    wc.hInstance = hInstance;
    wc.hIcon = NULL;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = pClass;
    if (!RegisterClass(&wc)) {
        lastErr=-2;
        return;
    }
    // Get dimensions of display
    int ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
    int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
    hwnd = CreateWindow(pClass, // class
                        pCaption, // caption
                        WS_OVERLAPPEDWINDOW, // style 
                        0, // left
                        0, // top
                        ScreenWidth, // width
                        ScreenHeight, // height
                        NULL, // parent window
                        NULL, // menu 
                        hInstance, // instance
                        NULL); // parms
    if (!hwnd) {
        lastErr=-3;
        return;
    }
}
DXContext::~DXContext()
{
    // call cleanup in case program did not
    // the cleanup routine will only release objects once, despite repeated calls 
    Cleanup();
}
void DXContext::Cleanup()
{
    // clear active flag
    active=FALSE;
    // release 3D interfaces
    SafeRelease(lpDevice);
    SafeRelease(lpD3D);
}
BOOL DXContext::TestFormat(D3DFORMAT fmt)
{
    if (D3D_OK==lpD3D->CheckDeviceType(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,fmt,fmt,FALSE))
        return TRUE;
    return FALSE;
}
BOOL DXContext::TestDepth(D3DFORMAT fmt)
{
    if (D3D_OK!=lpD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,format,
                                         D3DUSAGE_DEPTHSTENCIL,D3DRTYPE_SURFACE,fmt))
        return FALSE;
    if (D3D_OK!=lpD3D->CheckDepthStencilMatch(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,
                                              format,format,fmt))
        return FALSE;
    return TRUE;
}
#define DXTestFmt(x) if (TestFormat(x)) {format=x; break;}
#define DXTestDepth(x) if (TestDepth(x)) zFormat=x
BOOL DXContext::Init(WORD wWidth,WORD wHeight,WORD wDepth,WORD wBackBuffers,BOOL bWindowed)
{
    // save screen parameters
    width=wWidth;
    height=wHeight;
    SetWindowPos(hwnd,HWND_TOP,0,0,width,height,SWP_SHOWWINDOW);
    lpD3D=Direct3DCreate8(D3D_SDK_VERSION);
    if (!lpD3D) {
        lastErr=-4;
        return FALSE;
    }
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp,sizeof(d3dpp));
    if (bWindowed) {
        d3dpp.Windowed=TRUE;
        D3DDISPLAYMODE d3ddm;
        if( FAILED( hRes=lpD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) ) {
            lastErr=-5;
            return FALSE;
        }
        format=d3dpp.BackBufferFormat=d3ddm.Format; 
    } else {
        d3dpp.Windowed=FALSE;
        switch (wDepth) {
            case 32:
                DXTestFmt(D3DFMT_A8R8G8B8);
                DXTestFmt(D3DFMT_X8R8G8B8);
            case 16:
                DXTestFmt(D3DFMT_R5G6B5);
                DXTestFmt(D3DFMT_X1R5G5B5);
            default:
                format=D3DFMT_UNKNOWN;
        }
        if (format==D3DFMT_UNKNOWN) {
            lastErr=-6;
            return FALSE;
        }
        d3dpp.BackBufferFormat=format;
        d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT;
        d3dpp.FullScreen_PresentationInterval=D3DPRESENT_INTERVAL_ONE;
    }
    d3dpp.BackBufferWidth=width;
    d3dpp.BackBufferHeight=height;
    d3dpp.BackBufferCount=wBackBuffers;
    d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
    zFormat=D3DFMT_UNKNOWN;
    DXTestDepth(D3DFMT_D32);
    else DXTestDepth(D3DFMT_D32);
    else DXTestDepth(D3DFMT_D24S8);
    else DXTestDepth(D3DFMT_D24X4S4);
    else DXTestDepth(D3DFMT_D24X8);
    else DXTestDepth(D3DFMT_D16);
    else DXTestDepth(D3DFMT_D15S1);
    else DXTestDepth(D3DFMT_D16_LOCKABLE);
    if (zFormat!=D3DFMT_UNKNOWN) {
        d3dpp.EnableAutoDepthStencil=TRUE;
        d3dpp.AutoDepthStencilFormat=zFormat;
    }
    if( FAILED( hRes=lpD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
                                          D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                          &d3dpp,&lpDevice ) ) ) {
        lastErr=-7;
        return FALSE;
    }    
    // return success
    return TRUE;
}
int DXContext::Run(void (*ptr)(float))
{
    renderPtr=ptr;
    LONGLONG cur_time; // current time
    BOOL perf_flag=FALSE; // flag determining which timer to use
    LONGLONG last_time=0; // time of previous frame
    float time_elapsed; // time since previous frame
    float time_scale; // scaling factor for time
    // select timer, get current time, and calculate time scale
    if (QueryPerformanceFrequency((LARGE_INTEGER *) &cur_time)) {
        time_scale=1.0f/cur_time;
        QueryPerformanceCounter((LARGE_INTEGER *) &last_time);
        perf_flag=TRUE;
    } else {
        time_scale=0.001f;
        last_time=timeGetTime();
    }
    // set status as active
    active=TRUE;
    // Now we're ready to recieve and process Windows messages.
    BOOL bGotMsg;
    MSG msg;
    PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );
    while( WM_QUIT != msg.message ) {
        if (!active) {
            bGotMsg=GetMessage(&msg, NULL, 0U, 0U);
            if( bGotMsg ) {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
            }
        } else {
            bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
            if( bGotMsg ) {
                TranslateMessage( &msg );
                DispatchMessage( &msg );
            } else {
                // use the appropriate method to get time 
                // and calculate elapsed time since last frame
                if (perf_flag) 
                    QueryPerformanceCounter((LARGE_INTEGER *) &cur_time);
                else 
                    cur_time=timeGetTime();
                // calculate elapsed time
                time_elapsed=(cur_time-last_time)*time_scale;
                // save frame time
                last_time=cur_time;
                if (renderPtr)
                    renderPtr(time_elapsed);
            }
        }
    }
    // return final message
    return msg.wParam;
}
void DXContext::SetRenderFunc(void (__cdecl *ptr)(float))
{
    renderPtr=ptr;
} | 
 
 
 Visitors Since 1/1/2000: 
 
  |