刚开始接触DirectX,所以特地对整个Direct3D初始化框架都做了点解释,方便自己以后观看,其他部分注释是来至于网上大神的。
#include <d3d9.h>
#include <d3dx9.h>
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"winmm.lib")
const int Width = 800;
const int Height = 600;
#define SAFE_RELEASE(p) if(p){(p)->Release();(p) = NULL;}
#define windowTitle L"DirectX的初始化"
IDirect3DDevice9* Device = NULL;//Direct3D设备对象
LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);//消息响应函数,接受Peekmessage提交过来的消息
LRESULT Driect3Dinit(HWND hWnd);//DirectX进行初始化的操作
void CleanUp();//用于COM接口对象和其他动态申请的变量释放内存
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
//开始设计一个完整的窗口类
WNDCLASSEX wndClass = { 0 };
//用WINDCLASSEX定义了一个窗口类,即用wndClass实例化了WINDCLASSEX,用于之后窗口的各项初始化
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"MyClass"; //用一个以空终止的字符串,指定窗口类的名字。
if (!RegisterClassEx(&wndClass)) //设计完窗口后,需要对窗口类进行注册,这样才能创建该类型的窗口
return -1;
HWND hwnd = CreateWindow(L"MyClass", windowTitle, //喜闻乐见的创建窗口函数CreateWindow
WS_EX_TOPMOST, CW_USEDEFAULT, CW_USEDEFAULT, Width,
Height, NULL, NULL, hInstance, NULL);
MoveWindow(hwnd, 200, 50, Width, Height, true); //调整窗口显示时的位置,窗口左上角位于屏幕坐标(200,50)处
ShowWindow(hwnd, nShowCmd); //调用Win32函数ShowWindow来显示窗口
UpdateWindow(hwnd); //对窗口进行更新,就像我们买了新房子要装修一样
//Direct3D资源的初始化,成功或者失败都用messagebox予以显示
if (FAILED(Driect3Dinit(hwnd))){
MessageBox(0, 0, L"Driect3D初始化失败", 0);
}
else{
MessageBox(0, 0, L"Driect3D初始化成功", 0);
}
//消息循环过程
MSG msg = { 0 }; //初始化msg
while (msg.message != WM_QUIT) //使用while循环
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) //查看应用程序消息队列,有消息时将队列中的消息派发出去。
{
TranslateMessage(&msg); //将虚拟键消息转换为字符消息
DispatchMessage(&msg); //该函数分发一个消息给窗口程序。
}
else
{
}
}
UnregisterClass(L"MyClass", wndClass.hInstance);//销毁窗口类
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) //窗口过程函数WndProc
{
switch (message) //switch语句开始
{
case WM_PAINT: // 客户区重绘消息
ValidateRect(hwnd, NULL); // 更新客户区的显示
break; //跳出该switch语句
case WM_KEYDOWN: // 键盘按下消息
if (wParam == VK_ESCAPE) // ESC键
DestroyWindow(hwnd); // 销毁窗口, 并发送一条WM_DESTROY消息
break;
case WM_DESTROY: //窗口销毁消息
CleanUp();
PostQuitMessage(0); //向系统表明有个线程有终止请求。用来响应WM_DESTROY消息
break; //跳出该switch语句
default: //若上述case条件都不符合,则执行该default语句
return DefWindowProc(hwnd, message, wParam, lParam); //调用缺省的窗口过程来为应用程序没有处理的窗口消息提供缺省的处理。
}
return 0; //正常退出
}
LRESULT Driect3Dinit(HWND hWnd)
{
//创接口,取信息,填内容,创设备
//创接口
LPDIRECT3D9 g_d3d = NULL;//Direct3D接口对象创建
if ((g_d3d = Direct3DCreate9(DIRECT3D_VERSION)) == NULL){//初始化Direct3D接口对象,并进行DirectX版本协商,表示当前使用的DirectX SDK的版本
return E_FAIL;
}
//取信息
int vp = 0;
D3DCAPS9 g_caps;//用来储存当前硬件设备的信息
if (FAILED(g_d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,&g_caps))){
return E_FAIL;
}
if (g_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT){//判断显卡是否可以硬件支持变换和光照
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; //支持硬件顶点运算,我们就采用硬件顶点运算
}
else{
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;//不支持硬件顶点运算,无奈只好采用软件顶点运算
}
//填内容
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.BackBufferWidth = Width;//后台缓冲区的宽度
d3dpp.BackBufferHeight = Height;//后台缓冲区的高度
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;//指定后台缓冲区的保存像素格式
d3dpp.BackBufferCount = 1;//后台缓冲区的个数
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;//表示多重采样的类型
d3dpp.MultiSampleQuality = 0; //表示多重采样的格式
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;//前后台缓存交换的方式
d3dpp.hDeviceWindow = hWnd;//窗口的句柄
d3dpp.Windowed = true;//是否创建窗口模式
d3dpp.EnableAutoDepthStencil = true;//Direct3D是否为应用程序自动管理深度缓存
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;//自动管理深度缓存的像素格式
d3dpp.Flags = 0;//是否需要附加属性
d3dpp.FullScreen_RefreshRateInHz = 0;//在全屏模式时指定的屏幕的刷新率,窗口模式时这个成员没有意义,我们把它就设为0了
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;//指定后台缓冲区与前台缓冲区的最大交换频率
//创设备
if (FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, vp, &d3dpp, &Device))){
return E_FAIL;
}
SAFE_RELEASE(g_d3d);
return S_OK;
}
void CleanUp()
{
SAFE_RELEASE(Device);
}