CustomUI: C# 快速入门指南
DirectX SDK 中的 C# CustomUI 示例快速指南。
引言
因此,您决定编写下一个大型游戏。您已经成功运行了一个不错的虚拟世界和玩家模型。然后现实来了,您没有用户界面!几个小时后,您最终看到了 DirectX SDK 中的 CustomUI 示例。现实再次来临,这个示例几乎没有文档!
弄懂 CustomUI 示例的最佳方法是尝试使用它。我写这篇指南是为了快速介绍我在自己摸索过程中发现的一些内容。这或许能帮助您开始自己的摸索之旅。
CustomUI 项目可能是 DirectX SDK 中最有趣且最有用的示例,因为几乎所有游戏都需要某种用户界面。我花了一些时间阅读和分析该示例的 C# 版本,并在这里分享我学到的知识。
设计
设计人员基本上是模仿 Windows 控件对其进行建模。有一个 Dialog
类,可以容纳一组控件。初始化对话框后,您可以使用 Dialog
类提供的几种方法将其添加到其中。
图 1 – 图显示您可以同时拥有多个对话框。对话框 A 有两个控件,对话框 B 有三个控件。请注意,控件不能存在于对话框之外。
该示例使用 sampleFramework
,这是一个执行 DirectX 应用程序所有基本操作的类。实际上,使用它来启动游戏是个不错的方法。sampleFramework
拥有许多方法来执行各种任务,这些超出了本指南的范围。但是,有两个回调函数您应该了解:OneFrameMove
和 OnFrameRender
。OnFrameMove
应包含更改屏幕状态但不绘制它的代码,例如处理游戏事件。OnFrameRender
应包含实际绘制场景的代码。
向对话框添加控件
查看第 394 行的以下代码
Checkbox clearEdit = sampleUi.AddCheckBox(ClearEditControl,
"This checkbox controls whether the edit control " +
"text is cleared when Enter is pressed.",
150, 460, 430, 24, false);
这会将一个复选框控件添加到 sampleUi
对话框中,并返回添加的复选框。第一个参数是 ID(ClearEditControl
是在第 59 行声明的静态 int
),第二个是复选框旁边的文本描述。第四、五、六、七个参数是控件的位置和大小,最后一个参数用于设置控件是否为对话框的默认控件。
控件的位置相对于对话框。例如,如果对话框位于位置 (50,100),而对话框内的控件位于 (10,10),则控件的屏幕位置将是 (60, 110)。
另一件需要注意的事情是,sampleUi
的 AddCheckBox
方法只是一个包装器,它调用 AddControls
来设置复选框并将其添加到对话框中。对于其他控件也有类似的包装方法。
控件渲染
对于您添加的每个对话框,都需要在 OnFrameRender
回调函数中调用其 OnRender
方法。这样,对话框就会被绘制,并且对话框内所有控件的 OnRender
方法都会根据需要被调用。控件的 OnRender
是绘制实际控件的地方。
DXUTControls.dds 文件包含用于绘制某些控件的纹理。它在对话框初始化时加载,并加载到 DialogResourceManager
中。DialogResourceManager
确保所有对话框使用的资产只有一份副本,以节省内存。
控件以图层形式绘制。例如,按钮控件有一个绘制按钮形状的图层,还有一个绘制按钮文本的图层。每个图层都有一个 Element
对象,用于定义绘制时要使用的纹理或字体。InitializeDefaultElements
方法定义了每个图层的默认设置。
控件创建
有一个基类 Control
,所有控件都从中派生。该基类包含所有控件共有的基本属性。控件在 dxmutgui.cs 中创建,必须继承基类 Control
。应使用自定义代码重写 OnRender
方法来绘制控件。
绘图
控件可以通过控件的 Parent
属性访问其父对话框。Dialog
包含所有绘图功能,包括 DrawText
、DrawSprite
、DrawText
和 DrawRectangle
。它们都将 Element
类作为参数。
Element
类包含有关要使用的纹理或字体的索引等信息,但它本身不包含实际的纹理或字体。实际的纹理和字体存储在 DialogResourceManager
类中。这确保了同一纹理或字体始终只有一个加载副本。
要编写文本,您需要调用对话框的 DrawText
方法,传入文本、Element
以及指定位置(相对于对话框)的矩形。DrawText
将使用传入的 Element
来确定要用于渲染的字体。
同样,要绘制纹理,您需要调用对话框的 DrawSprite
方法,传入一个 Element
(其中包含纹理的索引)和一个包含位置信息的矩形。
用户输入处理
您可能知道,Windows 使用消息在内部通信。sampleFramework
的 MessageProc
可以截获这些消息。然后,您可以调用对话框的 MessageProc
方法,该方法会将其转发给控件的 MsgProc
方法。消息被分解并处理,然后调用 HandleKeyboard
和 HandleMouse
。派生控件可以重写 HandleKeyboard
和 HandleMouse
方法来添加键盘和鼠标处理。
因此,当您添加自己的对话框时,您需要添加一个条目来调用对话框的 MessageProc
。这是来自第 340 行的一个示例
// Give the dialog a chance to handle the message first
noFurtherProcessing = hud.MessageProc(hWnd, msg, wParam, lParam);
if (noFurtherProcessing)
return IntPtr.Zero;
处理控件的事件
处理控件事件非常简单。您只需创建一个方法来处理事件,并使用 EventHandler
将其绑定到控件的事件。例如
edit.Changed += new EventHandler(OnEditChanged);
edit
是一个文本框。当其文本更改时,将调用 OnEditChanged
。事件绑定应在将控件添加到对话框后调用。