这里讲的是创建一个通用的Direct3D窗口。
这里我先讲下用到的所有函数和结构
Window
WNDCLASSEX
[cpp] view
plaincopy
- typedef struct tagWNDCLASSEXA {
- UINT cbSize;
- UINT style;
- WNDPROC lpfnWndProc;
- int cbClsExtra;
- int cbWndExtra;
- HINSTANCE hInstance;
- HICON hIcon;
- HCURSOR hCursor;
- HBRUSH hbrBackground;
- LPCSTR lpszMenuName;
- LPCSTR lpszClassName;
- HICON hIconSm;
- } WNDCLASSEXA, *PWNDCLASSEXA
1.cbSize:
WNDCLASSEX 的大小。我们可以用sizeof(WNDCLASSEX)来获得准确的值。
2.style:
从这个窗口类派生的窗口具有的风格。您可以用“or”操作符来把几个风格或到一起。
3.lpfnWndProc:
窗口处理函数的指针。
4.cbClsExtra:
指定紧跟在窗口类结构后的附加字节数。
5.cbWndExtra:
指定紧跟在窗口实例的附加字节数。如果一个应用程序在资源中用CLASS伪指令注册一个对话框类时,则必须把这个成员设成DLGWINDOWEXTRA。
6.hInstance:
本模块的实例句柄。
7.hIcon:
图标的句柄。
8.hCursor:
光标的句柄。
9.hbrBackground:
背景画刷的句柄。
10.lpszMenuName:
指向菜单的指针。
11.lpszClassName:
指向类名称的指针。
12.hIconSm:
和窗口类关联的小图标。如果该值为NULL。则把hIcon中的图标转换成大小合适的小图标。
RegisterClassEx()窗口注册
CreateWindow()窗口创建
[cpp] view
plaincopy
- HWND CreateWindow(
- LPCTSTR lpClassName,
- LPCTSTR lpWindowName,
- DWORD dwStyle,
- int x,
- int y,
- int nWidth,
- int nHeight,
- HWND hWndParent,
- HMENU hMenu,
- HANDLE hlnstance,
- LPVOID lpParam);
lpClassName
指向一个空结束的字符串或整型数atom。如果该参数是一个整型量,它是由此前调用theGlobalAddAtom函数产生的全局量。这个小于0xC000的16位数必须是lpClassName参数字的低16位,该参数的高位必须是0。
如果lpClassName是一个字符串,它指定了窗口的类名。这个类名可以是任何用函数RegisterClass注册的类名,或是任何预定义的控制类名。请看说明部分的列表。
LPWindowName
指向一个指定窗口名的空结束的字符串指针。
如果窗口风格指定了标题条,由lpWindowName指向的窗口标题将显示在标题条上。当使用Createwindow函数来创建控制例如按钮,选择框和静态控制时,可使用lpWindowName来指定控制文本。
dwStyle
指定创建窗口的风格。该参数可以是下列窗口风格的组合再加上说明部分的控制风格。风格意义:
WS_BORDER:创建一个带边框的窗口。
WS_CAPTION:创建一个有标题框的窗口(包括WS_BORDER风格)。
WS_CHILD:创建一个子窗口。这个风格不能与WS_POPUP风格合用。
WS_CHILDWINDOW:与WS_CHILD相同。
WS_CLIPCHILDREN:当在父窗口内绘图时,排除子窗口区域。在创建父窗口时使用这个风格。
WS_CLIPSIBLINGS:排除子窗口之间的相对区域,也就是,当一个特定的窗口接收到WM_PAINT消息时,WS_CLIPSIBLINGS 风格将所有层叠窗口排除在绘图之外,只重绘指定的子窗口。如果未指定WS_CLIPSIBLINGS风格,并且子窗口是层叠的,则在重绘子窗口的客户区时,就会重绘邻近的子窗口。
WS_DISABLED:创建一个初始状态为禁止的子窗口。一个禁止状态的窗口不能接受来自用户的输入信息。
WS_DLGFRAME:创建一个带对话框边框风格的窗口。这种风格的窗口不能带标题条。
WS_GROUP:指定一组控制的第一个控制。这个控制组由第一个控制和随后定义的控制组成,自第二个控制开始每个控制,具有WS_GROUP风格,每个组的第一个控制带有WS_TABSTOP风格,从而使用户可以在组间移动。用户随后可以使用光标在组内的控制间改变键盘焦点。
WS_HSCROLL:创建一个有水平滚动条的窗口。
WS_ICONIC:创建一个初始状态为最小化状态的窗口。与WS_MINIMIZE风格相同。
WS_MAXIMIZE:创建一个初始状态为最大化状态的窗口。
WS_MAXIMIZEBOX:创建一个具有最大化按钮的窗口。该风格不能与WS_EX_CONTEXTHELP风格同时出现,同时必须指定WS_SYSMENU风格。
WS_OVERLAPPED:产生一个层叠的窗口。一个层叠的窗口有一个标题条和一个边框。与WS_TILED风格相同。
WS_OVERLAPPEDWINDOW:创建一个具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU WS_THICKFRAME,WS_MINIMIZEBOX,WS_MAXIMIZEBOX风格的层叠窗口,与WS_TILEDWINDOW风格相同。
WS_POPUP:创建一个弹出式窗口。该风格不能与WS_CHILD风格同时使用。
WS_POPUPWINDOW:创建一个具有WS_BORDER,WS_POPUP,WS_SYSMENU风格的窗口,WS_CAPTION和WS_POPUPWINDOW必须同时设定才能使窗口某单可见。
WS_SIZEBOX:创建一个可调边框的窗口,与WS_THICKFRAME风格相同。
WS_SYSMENU:创建一个在标题条上带有窗口菜单的窗口,必须同时设定WS_CAPTION风格。
WS_TABSTOP:创建一个控制,这个控制在用户按下Tab键时可以获得键盘焦点。按下Tab键后使键盘焦点转移到下一具有WS_TABSTOP风格的控制。
WS_THICKFRAME:创建一个具有可调边框的窗口,与WS_SIZEBOX风格相同。
WS_TILED:产生一个层叠的窗口。一个层叠的窗口有一个标题和一个边框。与WS_OVERLAPPED风格相同。
WS_TILEDWINDOW:创建一个具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU, WS_THICKFRAME,WS_MINIMIZEBOX,WS_MAXIMIZEBOX风格的层叠窗口。与WS_OVERLAPPEDWINDOW风格相同。
WS_VISIBLE:创建一个初始状态为可见的窗口。
WS_VSCROLL:创建一个有垂直滚动条的窗口。
X
指定窗口的初始水平位置。对一个层叠或弹出式窗口,X参数是屏幕坐标系的窗口的左上角的初始X坐标。对于子窗口,x是子窗口左上角相对父窗口客户区左上角的初始X坐标。如果该参数被设为CW_USEDEFAULT则系统为窗口选择缺省的左上角坐标并忽略Y参数。CW_USEDEFAULT只对层叠窗口有效,如果为弹出式窗口或子窗口设定,则X和y参数被设为零。
Y
指定窗口的初始垂直位置。对一个层叠或弹出式窗口,y参数是屏幕坐标系的窗口的左上角的初始y坐标。对于子窗口,y是子窗口左上角相对父窗口客户区左上角的初始y坐标。对于列表框,y是列表框客户区左上角相对父窗口客户区左上角的初始y坐标。如果层叠窗口是使用WS_VISIBLE风格位创建的并且X参数被设为CW_USEDEFAULT,则系统将忽略y参数。
nWidth
以设备单元指明窗口的宽度。对于层叠窗口,nWidth或是屏幕坐标的窗口宽度或是CW_USEDEFAULT。若nWidth是CW_USEDEFAULT,则系统为窗口选择一个缺省的高度和宽度:缺省宽度为从初始X坐标开始到屏幕的右边界,缺省高度为从初始Y坐标开始到目标区域的顶部。CW_USEDEFAULT只对层叠窗口有效;如果为弹出式窗口和子窗口设定CW_USEDEFAULT标志则nWidth和nHeight被设为零。
nHeight
以设备单元指明窗口的高度。对于层叠窗口,nHeight是屏幕坐标的窗口宽度。若nWidth被设为CW_USEDEFAULT,则系统忽略nHeight参数。
hWndParent
指向被创建窗口的父窗口或所有者窗口的句柄。若要创建一个子窗口或一个被属窗口,需提供一个有效的窗口句柄。这个参数对弹出式窗口是可选的。Windows NT 5.0;创建一个消息窗口,可以提供HWND_MESSAGE或提供一个己存在的消息窗口的句柄。
hMenu
菜单句柄,或依据窗口风格指明一个子窗口标识。对于层叠或弹出式窗口,hMenu指定窗口使用的菜单:如果使用了菜单类,则hMenu可以为NULL。对于子窗口,hMenu指定了该子窗口标识(一个整型量),一个对话框使用这个整型值将事件通知父类。应用程序确定子窗口标识,这个值对于相同父窗口的所有子窗口必须是唯一的。
hlnstance
与窗口相关联的模块实例的句柄。
lpParam
指向一个值的指针,该值传递给窗口WM_CREATE消息。该值通过在IParam参数中的CREATESTRUCT结构传递。如果应用程序调用CreateWindow创建一个MDI客户窗口,则lpParam必须指向一个CLIENTCREATESTRUCT结构。
返回值:如果函数成功,返回值为新窗口的句柄:如果函数失败,返回值为NULL。若想获得更多错误信息,请调用GetLastError函数。
UnregisterClass();//销毁窗口
DirectD3D
Direct3DCreate9() 创建D3D对象
GetAdapterDisplayMode()获取显示器信息
D3DPRESENT_PARAMETERS结构
[cpp] view
plaincopy
- <pre name="code" class="cpp">typedef struct _D3DPRESENT_PARAMETERS_
- {
- UINT BackBufferWidth;
- UINT BackBufferHeight;
- D3DFORMAT BackBufferFormat;
- UINT BackBufferCount;
- D3DMULTISAMPLE_TYPE MultiSampleType;
- DWORD MultiSampleQuality;
- D3DSWAPEFFECT SwapEffect;
- HWND hDeviceWindow;
- BOOL Windowed;
- BOOL EnableAutoDepthStencil;
- D3DFORMAT AutoDepthStencilFormat;
- DWORD Flags;
- UINT FullScreen_RefreshRateInHz;
- UINT PresentationInterval;
- } D3DPRESENT_PARAMETERS;
BackBufferWidth 后台缓冲区的宽
BackBufferHeight 后台缓冲区的高
BackBufferFormat 后台缓冲区格式。有关格式的更多信息,。这个参数是一个D3DFORMAT枚举类型,它的值有很多种,例 如D3DFMT_R5G6B5、D3DFMT_X8R8G8B8为游戏后备缓冲常用格式,这说明后备缓冲的格式是每个像素16位,其实红色(R)占5位,绿色(G)占6位,蓝色(B)占5位,为什么绿色会多一位呢?据说是因为人的眼睛对绿色比较敏感。
BackBufferCount 该值可以是0和d3dpresent_back_buffers_max之间(或d3dpresent_back_buffers_max_ex当使用Direct3D 9Ex)。范围是从0到3,如果为0,那就当成1来处理。大多数情况我们只使用一个后备缓冲。使用多个后备缓冲可以使画面很流畅,但是却会造成输入设备响应过慢,还会消耗很多内存。如果后台缓冲区的数目不能被创建,运行时将失败的方法调用和填补这个值与后台缓冲区,可以创建的次数。因此,应用程序可以调用方法两次d3dpresent_parameters结构和期望它第二次工作。
如果一个后台缓冲区无法创建失败的方法。价值backbuffercount影响组交换作用是允许的。具体地说,任何d3dswapeffect_copy交换效果需要一个后台缓冲区。
MultiSampleType d3dmultisample_type成员的枚举类型。 该值必须d3dmultisample_none除非swapeffect已设置为d3dswapeffect_discard。 方法只有交换效果d3dswapeffect_discard支持。
MultiSampleQuality 质量水平。有效的范围是0比所使用的函数返回的水平不一pqualitylevels之间checkdevicemultisampletype:。通过一个较大的值返回错误d3derr_invalidcall。配对值的渲染目标或深度模具图面和d3dmultisample_type必须匹配。
SwapEffect d3dswapeffect成员的枚举类型。运行库将保证关于缓冲区交换行为所隐含的语义;因此,如果窗口是真实的,swapeffect设置为d3dswapeffect_flip,运行时将创建一个额外的后台缓冲区和复制无论在呈现时成为前台缓冲区。d3dswapeffect_copy要求backbuffercount被设置为1。 d3dswapeffect_discard将在调试运行通过填充噪声任何缓冲后提出强制执行。
hDeviceWindow 该装置的窗口确定位置和屏幕上的后台缓冲区大小。 这是用Direct3D在后台缓冲区的内容复制到前台缓冲区中当前IDirect3DDevice9:。
Windowed true:如果应用程序运行窗口模式;false:如果应用程序运行的全屏模式。
EnableAutoDepthStencil 如果该值为真,Direct3D会管理的应用深度缓冲区。该装置将创建一个深度模具缓冲区创建时。深度模具缓冲区将被自动设置为呈现目标的装置。当器件复位,深度模具缓冲区将被自动销毁和新尺寸的重建。 如果enableautodepthstencil是真的,那么autodepthstencilformat必须是一个有效的深度模具格式。
AutoDepthStencilFormat d3dformat成员的枚举类型。
Flags 其中的一个d3dpresentflag常数。一般为0
FullScreen_RefreshRateInHz 速率的显示适配器刷新屏幕。价值取决于模式中,应用程序在运行:
PresentationInterval 在其中最大速率交换链的后台缓冲区可到了前台缓冲区。一个详细的解释模式和间隔的支持,看到d3dpresent。
CreateDevice()创建D3D设备对象
Clear()清屏
BeginScene()开始绘制
EndScene()结束绘制
Present()完成显示翻转
要用的基本函数和结构都介绍完了现在我们开始来创建我们的窗口代码如下
[cpp] view
plaincopy
- #include <d3d9.h>
- #pragma comment(lib,"d3d9.lib")
- #pragma comment(lib,"d3dx9.lib")
- #define WINDOW_CLASS "Direct3D"
- #define WINDOW_NAME "Direct3D"
- #define WINDOW_WIDTH 640
- #define WINDOW_HEIGHT 480
- #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
- #define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
- bool InitializeD3D(HWND hWnd,bool fullscreen);
- void RenderScreen();
- void Shutdown();
- LPDIRECT3D9 g_D3D=NULL;//创建Direct3D接口对象, 以便用该Direct3D对象创建Direct3D设备对象
- LPDIRECT3DDEVICE9 g_D3DDevice=NULL;//Direct3D设备对象
- LRESULT WINAPI MsgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
- {
- switch (msg)
- {
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
- break;
- case WM_KEYDOWN:
- if (wParam==VK_ESCAPE)
- {
- PostQuitMessage(0);
- }
- break;
- }//switch end
- //该函数调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理。该函数确保每一个消息得到处理。
- return DefWindowProc(hWnd,msg,wParam,lParam);
- }//MsgProc end
- int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE prevHinstance,LPSTR cmdLine,int show)
- {
- //填写窗口结构信息
- WNDCLASSEX wc=
- {
- sizeof(WNDCLASSEX),//设置结构体的字节数大小
- CS_CLASSDC,//设置窗口的样式。CS_CLASSDC: 该窗口类的所有窗口实例都共享一个窗口类DC
- MsgProc,//设置指向窗口过程函数的指针
- 0,//指定紧跟在窗口类结构后的附加字节数
- 0,//指定紧跟在窗口实例的附加字节数。
- hInstance,//指定包含窗口过程的程序的实例句柄。
- NULL,//ico图标
- NULL,//指定窗口类的光标句柄。
- NULL,//背景
- NULL,//指向菜单的指针。
- WINDOW_CLASS,//为hbrBackground成员指定一个灰色画刷句柄
- NULL//和窗口类关联的小图标。如果该值为NULL。则把hIcon中的图标转换成大小合适的小图标。
- };
- //注册窗口结构信息
- if (!RegisterClassEx(&wc))
- {
- MessageBox(NULL,"WNDCLASSEX Register failed!","Message",NULL);
- return 0;
- }
- //创建窗口
- HWND hWnd=CreateWindow(
- WINDOW_CLASS,//指向一个空结束的字符串或整型数
- WINDOW_NAME,//指向一个指定窗口名的空结束的字符串指针。
- WS_OVERLAPPEDWINDOW,//指定创建窗口的风格。
- //WS_OVERLAPPEDWINDOW:创建一个具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU WS_THICKFRAME
- //,WS_MINIMIZEBOX,WS_MAXIMIZEBOX风格的层叠窗口,与WS_TILEDWINDOW风格相同。
- 100,100,WINDOW_WIDTH,WINDOW_HEIGHT,//窗口左上角点和大小
- GetDesktopWindow(),//指向被创建窗口的父窗口或所有者窗口的句柄。
- NULL,//菜单句柄,或依据窗口风格指明一个子窗口标识。
- hInstance,//与窗口相关联的模块实例的句柄。
- NULL//指向一个值的指针,该值传递给窗口WM_CREATE消息。
- );
- //判断Direct3D初始化是否成功,false为窗口模式
- if (InitializeD3D(hWnd,false))
- {
- //显示窗口
- //SW_SHOWDEFAULT:依据在STARTUPINFO结构中指定的SW_FLAG标志设定显示状态,
- //STARTUPINFO 结构是由启动应用程序的程序传递给CreateProcess函数的。
- ShowWindow(hWnd,SW_SHOWDEFAULT);
- //更新窗口
- UpdateWindow(hWnd);
- //消息结构体
- MSG msg;
- //清空消息结构体
- ZeroMemory(&msg,sizeof(MSG));
- //开始消息循环,直到接受到WM_QUIT消息事退出
- while (msg.message!=WM_QUIT)
- {
- //一直接受消息,然后消除消息
- if (PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
- {
- //将获得的消息转换成字符消息
- TranslateMessage(&msg);
- //将转换后的消息发送给消息过程函数
- DispatchMessage(&msg);
- }//if end
- else
- {
- RenderScreen();
- }//else end
- }//While end
- }//if end
- //释放所有资源
- Shutdown();
- //销毁窗口
- UnregisterClass(WINDOW_CLASS,hInstance);
- return 0;
- }//WinMain end
- bool InitializeD3D(HWND hWnd,bool fullscreen)
- {
- D3DDISPLAYMODE displayMode;
- //创建D3D对象
- if ((g_D3D=Direct3DCreate9(D3D_SDK_VERSION))==NULL)
- {
- MessageBox(NULL,"Direct3DCreate9 Create Failed","Message",NULL);
- return false;
- }//if endl
- //获取显示器信息
- //D3DADAPTER_DEFAULT始终是主要的显示器适配器。
- if (FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&displayMode)))
- {
- return false;
- }//if end
- D3DPRESENT_PARAMETERS d3dpp;
- ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
- if (fullscreen)
- {
- d3dpp.Windowed=FALSE;
- d3dpp.BackBufferWidth=WINDOW_WIDTH;//后台缓冲区的宽
- d3dpp.BackBufferHeight=WINDOW_HEIGHT;//后台缓冲区的高
- }//if end
- else
- {
- d3dpp.Windowed=TRUE;
- }//else end
- d3dpp.BackBufferFormat= displayMode.Format;//后台缓冲区格式
- d3dpp.MultiSampleType= D3DMULTISAMPLE_NONE;//d3dmultisample_type成员的枚举类型
- //该值必须d3dmultisample_none
- //除非swapeffect已设置为d3dswapeffect_discard。方法只有交换效果d3dswapeffect_discard支持。
- d3dpp.MultiSampleQuality = 0;//质量水平。
- d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;//d3dswapeffect_discard将在调试运行通过填充噪声任何缓冲后提出强制执行。
- /*
- MultiSampleType,MultiSampleQuality,SwapEffect用来处理交换效果
- */
- d3dpp.hDeviceWindow= hWnd;//该装置的窗口确定位置和屏幕上的后台缓冲区大小。
- d3dpp.EnableAutoDepthStencil= true; //如果该值为真,Direct3D会管理的应用深度缓冲区。
- /*
- 如果EnableAutoDepthStencil是真的,那么AutoDepthStencilFormat必须是一个有效的深度模具格式。
- */
- d3dpp.AutoDepthStencilFormat= D3DFMT_D24S8;//d3dformat成员的枚举类型。
- /*
- AutoDepthStencilFormat将深度和模板缓存设置为BackBufferFormat可以使用相同值之一
- */
- d3dpp.Flags= 0;//
- d3dpp.FullScreen_RefreshRateInHz= 0;//速率的显示适配器刷新屏幕。
- d3dpp.PresentationInterval= D3DPRESENT_INTERVAL_IMMEDIATE;//在其中最大速率交换链的后台缓冲区可到了前台缓冲区。
- //创建D3D设备对象
- if (FAILED(g_D3D->CreateDevice(
- D3DADAPTER_DEFAULT,//序数所指示的显示器适配器。D3DADAPTER_DEFAULT始终是主要的显示器适配器
- D3DDEVTYPE_HAL,//在D3DDEVTYPE列举的成员,表示预设类型的驱动器类型,D3DDEVTYPE_HAL硬件加速
- hWnd,//与设备相关的窗口句柄,你想在哪个窗口绘制就写那个窗口的句柄
- D3DCREATE_SOFTWARE_VERTEXPROCESSING,
- //设定为D3DCREATE_SOFTWARE_VERTEXPROCESSING(软件顶点处理)
- //或者D3DCREATE_HARDWARE_VERTEXPROCESSING(硬件顶点处理) ,
- //使用前应该用d3dcaps来检测用户计算机是否支持硬件顶点处理功能。
- &d3dpp,//一个D3DPRESENT_PARAMETERS 类型的变量,用于指定将要创建设备的各种信息
- &g_D3DDevice//一个DIRECT3DDEVICE9类型的指针用来返回创建的设备
- )))
- {
- return false;
- }//if end
- return true;
- }//InitializeD3D end
- void RenderScreen()
- {
- g_D3DDevice->Clear(
- 0,//要清楚的矩形数目,0表示整个屏幕
- NULL,//定义想要清楚屏幕区域矩形链表,NULL表示整个屏幕
- D3DCLEAR_TARGET,//标识要清除的内容的标识符
- D3DCOLOR_XRGB(0,0,0),//清除后背景颜色
- 1.0f,//要设定的深度值
- 0//要设定的模板值
- );
- //开始绘制
- g_D3DDevice->BeginScene();
- /*
- 要渲染对象
- */
- //结束绘制
- g_D3DDevice->EndScene();
- //完成显示
- g_D3DDevice->Present(
- 0,//正在显示的原始矩形,如果不使用交换链该值为空NULL
- 0,//一个指针,他指向要渲染的最终矩形
- 0,//正在显示的窗口的窗口句柄。由于没有用到交换链,所以对正在使用的窗口句柄而言,该值设为空NULL
- //这个正在使用的窗口句柄是在Direct3D初始化过程中为D3DPRESENT_PARAMETERS对象设置的窗口句柄
- 0//缓存区域,表示要更新的最小区域。没涉及到交换链,该值为空
- );
- }//RenderScreen end
- void Shutdown()
- {
- SAFE_RELEASE(g_D3DDevice);
- SAFE_RELEASE(g_D3D);
- }//Shutdown end
为方便理解,里面的注释也基本解释了。基本的DirectD3D窗口创建也就这样了。