Sign in to follow this  
dontoo

c++ class and create D3D device

Recommended Posts

I am studying DirectX SDK samples tutorials and I found that they are written in C procedure manner. All variables are global and there are no classes. I decide that I will implement first tutorial ( create device ) using classes for encapsulation variables and methods. I am having problem with function: LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) That is the function that is called everytime when application recives message. When this function is implemented in C style, without classes, in Register class and create window part of building basic Win32 window, there is no problem. // Register class WNDCLASSEX wcex; wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; But when I create class D3D that holds all my methods and I put that function in the class compiler reports me an error in this line of code: wcex.lpfnWndProc = &D3D::WndProc;//Must create pointer to member with & Error is: error C2440: '=' : cannot convert from 'LRESULT (__stdcall D3D::* )(HWND,UINT,WPARAM,LPARAM)' to 'WNDPROC' That is the first question. Second question is about destroying COM objects within destructor. Do I need to call destructor explictly at the end of my program just before return 0; of WinMain() function or is it enough just to define destructor in class( public: ~D3D(); )? Does destructor going to be called when my program end, when object is destroyed? I am beginner programmer and don't know much about OOP. Class D3D.Contains definiton of all functions and fields. Is this good style?(constructor initialization of swap chain and device variables)
class D3D
{
private:
	HINSTANCE g_hInst;
	HWND                    g_hWnd;
	D3D10_DRIVER_TYPE       g_driverType;
	ID3D10Device*           g_pd3dDevice;
	IDXGISwapChain*         g_pSwapChain;
	ID3D10RenderTargetView* g_pRenderTargetView;
public:
	D3D ():
	g_hInst(NULL),
	g_hWnd(NULL),
	g_driverType(D3D10_DRIVER_TYPE_NULL),
	g_pd3dDevice(NULL),
	g_pSwapChain(NULL),
    g_pRenderTargetView(NULL)
	{
	}

	~D3D();

	int Run();
	LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
	HRESULT InitMainWindow( HINSTANCE, int );
	HRESULT InitDevice();
	HRESULT OnResize( HRESULT, UINT, UINT );
	void Render();
};
Entry point of a program.
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
	D3D d3dObject;
    if( FAILED( d3dObject.InitMainWindow( hInstance, nCmdShow ) ) )
        return 0;

    if( FAILED( d3dObject.InitDevice() ) )
    {
        return 0;
    }
	return d3dObject.Run();    
}
message loop
int D3D::Run()
{
	// Main message loop
    MSG msg = {0};
    while( WM_QUIT != msg.message )
    {
        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
		else
		{
			Render();
		}
    }
	return ( int )msg.wParam;
}
Register class and create window
HRESULT D3D::InitMainWindow( HINSTANCE hInstance, int nCmdShow )
{
    // Register class
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof( WNDCLASSEX );
    wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = &D3D::WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_ICON1 );
    wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
    wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = L"WindowClass";
    wcex.hIconSm = LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_ICON1 );
    if( !RegisterClassEx( &wcex ) )
        return E_FAIL;

    // Create window
    g_hInst = hInstance;
    RECT rc = { 0, 0, 640, 480 };
    AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
    g_hWnd = CreateWindow( L"WindowClass", L"Direct3D 10", WS_OVERLAPPEDWINDOW,
                           CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance,
                           NULL );
    if( !g_hWnd )
        return E_FAIL;

    ShowWindow( g_hWnd, nCmdShow );

    return S_OK;
}
Called every time the application receives a message
LRESULT CALLBACK D3D::WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    PAINTSTRUCT ps;
    HDC hdc;

    switch( message )
    {
		case WM_ACTIVATE:
			break;
		case WM_SIZE:
			break;
		case WM_ENTERSIZEMOVE:
			break;
		case WM_EXITSIZEMOVE:
			break;
        case WM_PAINT:
            hdc = BeginPaint( hWnd, &ps );
            EndPaint( hWnd, &ps );
            break;
        case WM_DESTROY:
            PostQuitMessage( 0 );
            break;
        default:
            return DefWindowProc( hWnd, message, wParam, lParam );
    }

    return 0;

}
Create Direct3D device and swap chain( at the end it calls OnResize() function that resize swap chain when window is resized.
HRESULT D3D::InitDevice()
{
    HRESULT hr = S_OK;;

    RECT rc;
    GetClientRect( g_hWnd, &rc );
    UINT width = rc.right - rc.left;
    UINT height = rc.bottom - rc.top;

    UINT createDeviceFlags = 0;
#ifdef _DEBUG
    createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG;
#endif

    D3D10_DRIVER_TYPE driverTypes[] =
    {
        D3D10_DRIVER_TYPE_HARDWARE,
        D3D10_DRIVER_TYPE_REFERENCE,
    };
    UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] );

    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory( &sd, sizeof( sd ) );
    sd.BufferCount = 1;
    sd.BufferDesc.Width = width;
    sd.BufferDesc.Height = height;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = g_hWnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = TRUE;

    for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
    {
        g_driverType = driverTypes[driverTypeIndex];
        hr = D3D10CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags,
                                            D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice );
        if( SUCCEEDED( hr ) )
            break;
    }
    if( FAILED( hr ) )
        return hr;
	return OnResize( hr, width, height );//////////Call OnResize() 

}
OnResize - Not yet implemented.
HRESULT D3D::OnResize( HRESULT hr, UINT width, UINT height )
{
	return S_OK;
}
Render frame
void D3D::Render()
{
    // Just clear the backbuffer
    float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
    g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor );
    g_pSwapChain->Present( 0, 0 );
}
Clean up the objects we've created
D3D::~D3D()
{
    if( g_pd3dDevice ) g_pd3dDevice->ClearState();
    if( g_pRenderTargetView ) g_pRenderTargetView->Release();
    if( g_pSwapChain ) g_pSwapChain->Release();
    if( g_pd3dDevice ) g_pd3dDevice->Release();
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this