代码框架来自Visual C++ 专栏作家 “浅墨” 以及《Visual C++游戏编程基础》,在这里首先感谢浅墨大神的无私分享。
下面是本人的初始化程序,有一些小的改动以及一些自己的注释,更详细的资料以及程序说明请见浅墨大神博文http://blog.csdn.net/poem_qianmo/article/details/8197792
//Visual C++ + Directx3D Init
//by xcz on 2013.10.28
#include <d3d9.h>
//环境配好以后,每次包含这三个库就可以了。
#pragma comment (lib,"d3d9.lib")
#pragma comment (lib,"d3dx9.lib")
#pragma comment (lib,"winmm.lib")
#define SCREEN_WIDTH 800 //窗口宽度
#define SCREEN_LEIGHT 600 //窗口高度
#define WINDOW_TITLE L"Direct3D_Init" //窗口标题
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } //自定义一个SAFE_RELEASE()宏,便于com资源的释放
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //Direct3D设备对象
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
HRESULT Direct3D_Init(HWND hwnd);
void Direct3D_Render( );
void Direct3D_CleanUp( );
// 函数: WinMain( )
// 功能: Windows应用程序入口函数。创建主窗口,处理消息循环
/*
参数说明:
参数1:标识应用程序的句柄,即一个指向该程序所占据内存区域的指针
参数2:为了保持与Windows应用程序的兼容性
参数3:指向应用程序命令行参数字符串的指针
参数4:用来指定窗口显示方式的整数
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nShowCmd)
{
//初始化窗口类WNDCLASSEZ的基本参数
WNDCLASSEX wndClass = { 0 }; //定义窗口类
wndClass.cbSize = sizeof( WNDCLASSEX ) ; //设置结构体的字节数大小
wndClass.style = CS_HREDRAW | CS_VREDRAW; //窗口的样式(这个参数表示,如果高度或者宽度发生变化,重绘整个窗口)
wndClass.lpfnWndProc = WndProc; //指向窗口消息函数(过程函数)的指针
wndClass.cbClsExtra = 0; //分配给窗口类结构之后的额外字节数
wndClass.cbWndExtra = 0; //分配给窗口实例之后的额外字节数
wndClass.hInstance = hInstance; //窗口所对应的应用程序的句柄。
wndClass.hIcon=(HICON)::LoadImage(NULL,L"icon.ico",IMAGE_ICON,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);
//窗口的图标(从全局的::LoadImage函数从本地加载自定义ico图标)
wndClass.hCursor = LoadCursor( NULL, IDC_ARROW ); //窗口的鼠标。
wndClass.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);
//窗口的背景(为hbrBackground成员指定一个灰色画刷句柄)
wndClass.lpszMenuName = NULL; //窗口的菜单资源名称,表示该窗口没有菜单
wndClass.lpszClassName = L"ForTheDreamOfGameDevelop"; //窗口类的名称,在调用CreateWindow时用到
//以上,初始化窗口基本参数完成,下面使用RegisterClass注册窗口
if( !RegisterClassEx( &wndClass ) ) //对窗口类进行注册,这样才能创建该类型的窗口
return -1;
HWND hwnd = CreateWindow( L"ForTheDreamOfGameDevelop",WINDOW_TITLE, //创建窗口,其中,名字和上面一样
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, SCREEN_WIDTH,
SCREEN_LEIGHT, NULL, NULL, hInstance, NULL );
/*CreateWindow说明:
参数1:窗口类的名称,参数2:窗口标题,参数3:窗口风格,这个为普通型,参数4-7,窗口位置x,y坐标,窗口宽度,高度
参数8-11:父窗口句柄,菜单句柄,应用程序句柄,最后一个一般为NULL
*/
MoveWindow(hwnd,200,50,SCREEN_WIDTH,SCREEN_LEIGHT,true);
//调整窗口显示时的位置,窗口左上角位于屏幕坐标(200,50)处
ShowWindow( hwnd, nShowCmd ); //显示窗口,第一个表示窗口句柄,第二个表示显示方式
UpdateWindow(hwnd); //更新窗口
//Direct3D资源的初始化,成功或者失败都用messagebox予以显示
if (S_OK==Direct3D_Init (hwnd))
{
MessageBox(hwnd, L"Direct3D初始化完成~!", L"xcz", 0); //使用MessageBox函数,创建一个消息窗口
}
else
{
MessageBox(hwnd, L"Direct3D初始化失败~!", L"xcz", 0); //使用MessageBox函数,创建一个消息窗口
}
//消息循环过程
MSG msg = { 0 }; //初始化msg
while( msg.message != WM_QUIT ) //使用while循环
{
if( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )
//PeekMessage函数从应用程序的消息队列中按照先进先出的原则将消息逐个取出来,放进一个MSG结构,如果没有将立即返回
{
TranslateMessage( &msg ); //将虚拟键消息转换为字符消息,满足键盘输入的需要
DispatchMessage( &msg ); //把当前消息发送到对应的窗口过程中去
}
else
{
Direct3D_Render();
}
}
UnregisterClass(L"ForTheDreamOfGameDevelop", wndClass.hInstance);
return 0;
}
// 函数: WndProc()
// 功能: 对窗口消息进行处理
//参数依次为:接受消息窗口的句柄,主消息值,副消息值1,副消息值2
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) //窗口过程函数WndProc
{
switch( message ) //switch语句开始
{
case WM_PAINT: // 客户区重绘消息
Direct3D_Render(); //调用Direct3D_Render函数,进行画面的绘制
ValidateRect(hwnd, NULL); // 更新客户区显示
break;
case WM_KEYDOWN: // 键盘消息
if (wParam == VK_ESCAPE) // ESC键
DestroyWindow(hwnd); // 销毁窗口, 并发送一条WM_DESTROY消息
break;
case WM_DESTROY: //窗口销毁消息
Direct3D_CleanUp(); //调用Direct3D_CleanUp函数,清理COM接口对象
PostQuitMessage( 0 ); //向系统表明有个线程有终止请求。用来响应WM_DESTROY消息
break;
case WM_RBUTTONDOWN: //鼠标右键按下了
MessageBox(hwnd, L"鼠标右键按下了", L"xcz", 0);
break;
default: //若上述case条件都不符合,则执行该default语句
return DefWindowProc( hwnd, message, wParam, lParam );
//调用缺省的窗口过程来为应用程序没有处理的窗口消息提供缺省的处理。
}
return 0; //正常退出
}
// 函数: Direct3D_Init( )
// 功能: 初始化Direct3D
HRESULT Direct3D_Init(HWND hwnd)
{
//创建Direct3D接口对象, 以便用该Direct3D对象创建Direct3D设备对象
LPDIRECT3D9 pD3D = NULL; //Direct3D接口对象的创建
if( NULL == ( pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) //初始化Direct3D接口对象,并进行DirectX版本协商
return E_FAIL;
// 获取硬件设备信息
D3DCAPS9 caps; int vp = 0;
if( FAILED( pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps ) ) )
{
return E_FAIL;
}
if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; //支持硬件顶点运算,就采用硬件顶点运算
else
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; //不支持硬件顶点运算,只好采用软件顶点运算
// 填充D3DPRESENT_PARAMETERS结构体
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.BackBufferWidth = SCREEN_WIDTH; //后台缓冲区的宽度
d3dpp.BackBufferHeight = SCREEN_LEIGHT; //后台缓冲区的高度
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; //后台缓冲区的保存像素格式
d3dpp.BackBufferCount = 1; //后台缓冲区的的数量,用于屏幕切换的缓存数量
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; //表示多重采样的类型
d3dpp.MultiSampleQuality = 0; //多重采样的格式,一般为0
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //用于指定Direct3D如何将后台缓冲区的内容复制到前台的缓存中
d3dpp.hDeviceWindow = hwnd; //窗口句柄,决定在哪个窗口上进行绘制
d3dpp.Windowed = true; //绘制窗体的显示模式,TRUE表示使用窗口模式,FALSE表示使用全屏模式。
d3dpp.EnableAutoDepthStencil = true; //是否为应用程序自动管理深度缓存,true表示自动管理
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; //关于自动管理深度缓存进行相关像素格式的设置
d3dpp.Flags = 0; //附加属性,一般为0;
d3dpp.FullScreen_RefreshRateInHz = 0; //全屏模式时指定的屏幕的刷新率,全屏模式一般默认值D3DPRESENT_RATE_DEFAULT,窗口模式没有意义为0
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //指定后台缓冲区与前台缓冲区的最大交换频率
// 创建Direct3D设备接口
if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
hwnd, vp, &d3dpp, &g_pd3dDevice)))
return E_FAIL;
SAFE_RELEASE(pD3D) //LPDIRECT3D9接口对象的使命完成,将其释放掉
return S_OK;
}
// 函数: Direct3D_Render()
// 功能: 使用Direct3D进行渲染
void Direct3D_Render()
{
//暂时为空
}
// 函数: Direct3D_CleanUp()
// 功能: 对Direct3D的资源进行清理
void Direct3D_CleanUp()
{
//释放Direct3D设备对象
SAFE_RELEASE(g_pd3dDevice)
}