[cpp] view plaincopyprint? 1. DIMOUSESTATE g_diMouseState = {0}; 2. ::ZeroMemory(&g_diMouseState,sizeof(g_diMouseState));
3. Device_Read(g_pMouseDevice,(LPVOID)&g_diMouseState,sizeof(g_diMou
seState)); 4.
5. //按住鼠标左键并拖动,为平移操作
6. staticFLOAT fPosX =0.0f, fPosY = 30.0f, fPosZ = 0.0f; 7. if(g_diMouseState.rgbButtons[0] & 0x80) 8. {
9. fPosX+=g_diMouseState.lX * 0.08f; 10. fPosY+=g_diMouseState.lY * -0.08f; 11. }
七、详细注释的源代码欣赏
首先需要说明的是,本篇文章配套的源代码中用到了我们目前还未讲到的一点技术,就是X模型的载入。源代码中X模型的载入相关的代码大家如果看不懂没关系,请锁定浅墨的博客,后面一定会有相关技术精彩的讲解的。
然后这篇文章中的demo我们对细节部分做了升级,新加了三个功能,他们分别是:
1.在窗口左上角智能读取运行的机器使用的显卡名称。 2.在窗口左下角给出了帮助信息。
3. 在窗口左上角给出了模型当前的三维坐标。
下面我们分别来对这三个新功能进行讲解:
1.在窗口左上角智能读取运行的机器使用的显卡名称。
这个其实很简单,借助一个GetAdapterIdentifier方法就可以了。这个方法可以获取获取显卡的厂商类型等信息。原型如下:
[cpp] view plaincopyprint?
1. HRESULT GetAdapterIdentifier( 2. [in] UINT Adapter, 3. [in] DWORD Flags,
4. [out] D3DADAPTER_IDENTIFIER9*pIdentifier 5. );
注意到第三个参数类型是一个D3DADAPTER_IDENTIFIER9结构体,这个结构体的第三个参数Description就保存着显卡的名称的char类型的字符串。思路也就是围绕着这个GetAdapterIdentifier方法来的,用GetAdapterIdentifier方法取得显卡的名称的char类型的字符串,然后转换成wchar_t类型并在显卡名称之前拼接上“当前显卡型号:”字样,然后把结果存在全局的字符串数组g_strAdapterName中,最后在Render函数中用TextOut写出来就可以了。另外注意一点,因为
IDirect3D9::GetAdapterIdentifier是IDirect3D9中的方法,而在我们的代码中IDirect3D9接口对象仅局部存在于Direct3D_Init( )方法中,所以我们绝大部分实现代码是在这个Direct3D_Init( )方法中完成的。具体做法咱们直接看代码,这可是每行都详细注释的代码:
首先是一个全局变量:
[cpp] view plaincopyprint?
1. wchar_t g_strAdapterName[60]={0};
//包含显卡名称的字符数组
然后就是Direct3D_Init( )方法中的功能实现代码:
[cpp] view plaincopyprint?
1. //获取显卡信息到g_strAdapterName中,并在显卡名称之前加上“当前显卡型号:”
字符串
2. wchar_tTempName[60]=L\当前显卡型号:\; //定义一个临时字符串,
且方便了把\当前显卡型号:\字符串引入我们的目的字符串中 3. D3DADAPTER_IDENTIFIER9Adapter; //定义一个
D3DADAPTER_IDENTIFIER9结构体,用于存储显卡信息
4. pD3D->GetAdapterIdentifier(0,0,&Adapter);//调用
GetAdapterIdentifier,获取显卡信息
5. int len =MultiByteToWideChar(CP_ACP,0,Adapter.Description
, -1, NULL, 0);//显卡名称现在已经在Adapter.Description中了,但是其为char类型,我们要将其转为wchar_t类型
6. MultiByteToWideChar(CP_ACP, 0,Adapter.Description, -1, g
_strAdapterName,len);//这步操作完成后,g_strAdapterName中就为当前我们的显卡类型名的wchar_t型字符串了
7. wcscat_s(TempName,g_strAdapterName);//把当前我们的显卡名加
到“当前显卡型号:”字符串后面,结果存在TempName中
8. wcscpy_s(g_strAdapterName,TempName);//把TempName中的结果
拷贝到全局变量g_strAdapterName中,大功告成~
最后就是在Direct3D_Render函数中调用一下DrawText显示出来了:
[cpp] view plaincopyprint?
1. //显示显卡类型名
2. g_pTextAdaperName->DrawText(NULL,g_str
AdapterName,-1,&formatRect,
3. DT_TOP| DT_LEFT, D3DXCOLOR(1.
0f, 0.5f, 0.0f, 1.0f));
2.在窗口左下角给出帮助信息。
其实非常简单,就是定义一些LPD3DXFONT接口对象,然后在Objects_Init()函数中用D3DXCreateFont创建不同的字体,最后在Direct3D_Render全DrawText出来就行了。
3. 在窗口左上角给出了模型当前的三维坐标。
其实也非常简单,就是用swprintf_s把世界矩阵g_matWorld的几个分量格式化到一个静态的wchar_t类型的字符串中,然后DrawText出来就可以了。
实现代码如下:
[cpp] view plaincopyprint?
1. staticwchar_tstrInfo[256] = {0};
2. swprintf_s(strInfo,-1,L\模型坐
标: (%.2f,%.2f, %.2f)\,g_matWorld._41, g_matWorld._42, g_matWorld._43);
3. g_pTextHelper->DrawText(NULL,strInfo, -1, &formatRect, DT_SINGLELINE| DT_NOCLIP | DT_LEFT,D3DCOLOR_RGBA(135,239,136,255));
还有一点,因为考虑到咱们的Direct3D_Render()函数中的代码随着讲解的不断深入,代码越来越多,越来越杂,越来越乱。所以我们给他配了一个搭档Direct3D_Update(),跟即时绘制没有直接联系但是需要即时调用的,如按键后的坐标的更改,按键后填充模式的更改等等相关的代码,都放在Direct3D_Update()中了,这样就给Direct3D_Render()绘制函数减了负,看起来更加清晰。
因为也是即时调用,所以Direct3D_Update()在消息循环中与Direct3D_Render()平起平坐了:
[cpp] view plaincopyprint?
1. //消息循环过程
2. MSGmsg = { 0 }; //初始化msg
3. while(msg.message !=WM_QUIT ) //
使用while循环 4. {
5. if(PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) //
查看应用程序消息队列,有消息时将队列中的消息派发出去。 6. {
7. TranslateMessage(&msg ); //
将虚拟键消息转换为字符消息
8. DispatchMessage(&msg ); //
该函数分发一个消息给窗口程序。 9. } 10. else 11. {
12. Direct3D_Update(hwnd); //调用更
新函数,进行画面的更新
13. Direct3D_Render(hwnd);
//调用渲染函数,进行画面的渲染 14. }
15. }
最后一点,DirectInput使用五步曲的第四步,即获取按键状态并进行响应就是在Direct3D_Update中实现的:
[cpp] view plaincopyprint?
1. void Direct3D_Update( HWND hwnd) 2. {
3. // 获取键盘消息并给予设置相应的填充模式
4. if (g_pKeyStateBuffer[DIK_1] & 0x80) // 若数字键1被
按下,进行实体填充
5. g_pd3dDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID
);
6. if (g_pKeyStateBuffer[DIK_2] & 0x80) // 若数字键2被
按下,进行线框填充
7. g_pd3dDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREF
RAME); 8. 9.
10. // 读取鼠标输入
11. ::ZeroMemory(&g_diMouseState, sizeof(g_diMouseState)); 12. Device_Read(g_pMouseDevice, (LPVOID)&g_diMouseState, sizeof(
g_diMouseState)); 13. 14.
15. // 读取键盘输入
16. ::ZeroMemory(g_pKeyStateBuffer, sizeof(g_pKeyStateBuffer));
17. Device_Read(g_pKeyboardDevice, (LPVOID)g_pKeyStateBuffer, si
zeof(g_pKeyStateBuffer)); 18. 19. 20. 21.
22. // 按住鼠标左键并拖动,为平移操作
23. static FLOAT fPosX = 0.0f, fPosY = 30.0f, fPosZ = 0.0f; 24. if (g_diMouseState.rgbButtons[0] & 0x80) 25. {
26. fPosX += g_diMouseState.lX * 0.08f; 27. fPosY += g_diMouseState.lY * -0.08f; 28. } 29. 30.