8、DXUT框架

Copyright © MikeFeng QQ: 76848502
温故而知新,前面的DXUT框架我只看了一个外壳,我觉得这次框架的亮点就在于它对于图形界面的支持。如果说Win32 API SDK中gdi部分是主旋律,那么MFC就是一个流行歌曲作家发挥之后完成的作品,而DXUT的图形框架则继承了Platform SDK中的风格,代码行间给人一种高贵的感觉。-,-扯远了,拉回来。因为gdi函数都是C API,不利于代码的重用,DXUT框架则把他们包装成了C++的类,以便于用户继承更改控件特性。D3D的知识学到这里基本上可以看懂DXUT框架了,所以不必担心,但要是不理解Windows消息机制的话还是不行。先了解一下DXUT中关于控件部分的设计架构比较好。这次看的代码大部分集中在DXUTgui.h和DXUTgui.cpp中。控件类的继承关系图是这样的:8、DXUT框架常用的控件大致都已经囊括在内,如果有特殊需要的话可以依葫芦画瓢从CDXUTControl继承。和这些控件有关系的还有几个重要的类,一个是CDXUTDialog,这个类负责纪录一个对话框的所有属性以及它上面的所有控件信息。另一个是CDXUTDialogResourceManager,这个类保存了所有注册过的对话框链表,以及这些对话框共享的资源。另外CDXUTElement这个类保存了需要渲染的元素信息,经常会在渲染函数中用到,最后一个类是可动态增长的链表类CGrowableArray< TYPE >。这个模版类写的不错,不光能用在DXUT框架中,还可以用于很多其他场合。具体的代码太多了,这里挑重要的讲解。1.CDXUTDialogAdd系列函数。在初始化一个CDXUTDialog之后就是往这个对话框中添加控件了。在以前的例子中通常是在InitApp函数中调用对话框的Add系列函数来给对话框添加控件的。例如g_HUD.Init( &g_DialogResourceManager);g_HUD.SetCallback(OnGUIEvent);intiY= 10;g_HUD.AddButton(IDC_TOGGLEFULLSCREEN,L"Toggle full screen", 35,iY, 125, 22 );前面两句分别是初始化和设定消息处理回调函数,最后一句是Add系列函数,这个用来在对话框特定位置添加一个特定控件。2CDXUTDialog::MsgProc这个函数是处理对话框消息的。具体处理的消息包括该对话框的移动消息,优先处理焦点控件的消息,对话框大小和移动消息,获得焦点消息,键盘、鼠标消息,以及鼠标丢失消息。了解这些有助于我们充分利用这些功能,并添加自己想要的功能。3.控件的初始化和显示每个控件都有其特定的属性。如果程序为每种控件定义一些默认属性,可以省去我们重复定义的很多麻烦。了解这些我们可以在此基础上修改这些默认属性,使你的控件更加个性化。在DXUT中控件的默认属性是按照这样的步骤定义和应用的。在初始化对话框的函数CDXUTDialog::Init中调用InitDefaultElements()为每种控件设定默认属性。将这些默认属性添加到CDXUTDialog::m_DefaultElements中用户代码调用Add系列函数添加控件。这个Add函数调用CDXUTDialog::AddControl函数,并完成这个控件的一些设置。CDXUTDialog::AddControl函数调用CDXUTDialog::InitControl初始化控件,并将该控件添加至对话框的CDXUTDialog::m_Control控件列表中。CDXUTDialog::InitControl函数中遍历对话框的默认控件列表,并找到和要添加控件类型相同的默认控件,获得它的属性并将其设定到这个控件对象中。这个操作由CDXUTControl::SetElement函数来完成。在CDXUTControl的继承类(例如CDXUTButton)的Render函数中使用这些属性并且通过CDXUTDialog的DrawSprite函数画出图形,用CDXUTDialog的DrawText画出文字。要做一个漂亮的界面肯定少不了对控件的背景进行设置,例如用来显示文字的static控件,如果能用圆形表示那多好。但遗憾的是CDXUT框架中没有给我们提供这些功能,需要我们自己去实现。它甚至没有给我们提供映射纹理的功能,而仅仅是提供了修改控件背景和前景字体颜色的功能。这些信息都放在空间的m_Elements属性中,并由上述过程初始化。控件的显示在上面第六步有说明,就是调用DrawSprite和DrawText来实现。4.对话框的初始化和显示DXUT框架中的对话框和GDI的有相似的地方,又有不同的地方。最大的不同就在于DXUT框架中的对话框是通过Draw函数画出来的,因此每一桢都需要进行渲染,并且这些对话框是在主窗口内;而GDI的对话框是弹出式的,因此不属于原窗口。对话框的初始化在CDXUTDialog::Init系列函数中。这个函数除了注册给CDXUTDialogResourceManager之外还进行了纹理的设置。在默认情况下框架在OnCreateDevice时调用CDXUTDialogResourceManager的CreateTexture函数从内存创建纹理,而如果在CDXUTDialog::Init函数中指定了纹理路径,或者指定使用资源中的纹理时,程序就从指定地点获得纹理。对话框采用一个列表来维护它的纹理,在通常情况下只有这个列表中只有一个纹理,除非用户调用相关函数手动添加。这个纹理是在显示控件的时候作为参数传给DrawSprite的,因此并不会用来作为对话框背景。对话框的显示使用CDXUTDialog::OnRender函数来实现。这个函数很关键,研究这个函数可以知道一个对话框是如何渲染的。和gdi应用程序不一样,DXUT框架是通过Draw函数将控件画出来的,因此您可以按照喜欢的方式自己设定按钮等控件的样子。可以想象CDXUTDialog::OnRender的主要任务就是调用每个控件的OnRender函数。在调用这些OnRender函数之前可以先将这个对话框的背景画好。因此这个函数的伪代码看起来就是这样子的:进行一些判断;为对话框背景设定渲染状态和纹理阶段状态;禁用顶点shader和像素shader,并且画出对话框背景;再次设定纹理阶段状态,为画控件做准备;调用各控件的Render函数画出各控件,对于获得焦点的控件做特殊处理;这个函数使用了状态块来记录设定过的状态,以备后用。5.CD3DSettingDlg研究CD3DSettingDlg类可以学会如何使用上面的这些框架实现一个自己的对话框。我们可以在一个对话框上画另一个对话框,也可以选择在整个画面中只画一个对话框。这些可以在主回调函数OnFrameRender中设定。例如在处理CD3DSettingDlg对话框的Active属性值被设定为true的时候不处理其他对话框的渲染。if(g_SettingsDlg.IsActive() ){g_SettingsDlg.OnRender(fElapsedTime);return;}在主回调函数MsgProc处理消息的时候,如果CD3DSettingDlg已经处理过则不再传递给其他函数。if(g_SettingsDlg.IsActive() ){g_SettingsDlg.MsgProc(hWnd,uMsg,wParam,lParam);return0;}CD3DSettingDlg::Init初始化CD3DSettingDlg::CreateControls添加控件CD3DSettingDlg::OnCreateDevice设定消息处理回调函数CD3DSettingDlg::StaticOnEvent消息处理回调函数,调用OnEventCD3DSettingDlg::OnEvent消息处理函数CD3DSettingDlg::OnRender渲染……在游戏中经常要进行游戏状态的切换,用户通过输入来出发某个游戏状态切换时,我们就可以重新绘制场景,而设计一个类似于CD3DSettingDlg来实现是一个不错的注意。由于CreateControls函数和OnEvent函数在不同的场景中代码不同,因此可以在基类中将其设为virtual。可以根据需要将OnRender, OnXXX系列函数设为虚函数,以便子类实现相应功能。原文链接: https://www.cnblogs.com/doublesnke/archive/2011/06/09/2076645.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/27000

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午4:35
下一篇 2023年2月8日 上午4:36

相关推荐