Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

CustomUI: C# Quickstart Guide

0.00/5 (No votes)
31 Jul 2005 1  
A quick guide to the C# CustomUI sample from the DirectX SDK.

Introduction

So you decided to write that next big game. You got a nice virtual world and a player model up and running. Then reality struck, you got no user interface! Hours later, you end up looking at the CustomUI sample from the DirectX SDK. Reality struck #2, there’s like almost no documentation for this sample!

The best way to figure out the CustomUI sample is to tinker around with it. I wrote this guide as a quick read on the things that I’ve found during my own tinkering session. This may help you on your own tinkering adventure.

The CustomUI project is probably the more interesting and useful sample from the DirectX SDK because nearly every game needs some sort of user interface. I’ve spent some time reading and analyzing the C# version of the sample, and I’ll try to share what I have learned here.

Design

The people who designed it basically modeled it after a Windows control. There’s a Dialog class that can hold a collection of controls. After initializing the dialog, you can add controls to it using several methods provided by the Dialog class.

Sample screenshot

Figure 1 – The figure shows that you can have more than one dialog on the screen. Dialog A has two controls, while Dialog B has three controls. Note that controls cannot exist outside of a dialog.

The sample uses the sampleFramework which is just a class that performs all of the basic operations common to DirectX applications. It’s actually not a bad way to start your game using it. The sampleFramework has many methods to perform various tasks, and is beyond the scope of this guide. However, there are two callback functions that you should be aware of, OneFrameMove, and OnFrameRender. OnFrameMove should contain code that changes the state of the screen but does not draw it such as processing game events. OnFrameRender should contain code that actually draws the scene.

Adding a Control to the Dialog

Take a look at the following code from line 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);

This adds a checkbox control to the sampleUi dialog and returns the added checkbox. The first parameter is the ID (ClearEditControl is a static int declared on line 59), the second is a description of the text next to the checkbox. The fourth, fifth, sixth, and seventh are the position and size of the control, and the last parameter is to set whether the control is the default control for the dialog.

The position of the control is relative to the dialog. For example, if the sialog is at position (50,100) and a control inside the dialog is set at (10,10), the control’s screen position would be (60, 110).

Another thing to note is that the AddCheckBox method of sampleUi is just a wrapper that just calls on AddControls to set the checkbox and add it to the dialog. There are other wrapper methods for the rest of the controls.

Control Rendering

For every dialog you add, you need to call its OnRender method in your OnFrameRender callback function. From there, the dialog is drawn, and all the controls inside the dialog OnRender are called as necessary. The control’s OnRender is where the actual control is drawn.

The DXUTControls.dds file contains the texture that is used to draw some of the controls. It is loaded on dialog initialization and is loaded into the DialogResourceManager. The DialogResourceManager makes sure that there’s only one copy of the assets used by all dialogs to conserve memory.

Controls are drawn in layers. For example, the button control has a layer that draws the button shape, and a layer that draws the button text. There’s an Element object for each layer which defines what texture or font to use for drawing. The InitializeDefaultElements method defines the default setting for each layer.

Control Creation

There’s a base Control class that all controls derive from. This base class contains the basic properties common in all controls. Controls are created in dxmutgui.cs and must inherit the base Control class. The OnRender method should be overridden with custom code to draw the control.

Drawing

Controls have access to their parent dialog via the control’s Parent property. Dialog contains all the drawing functionality including DrawText, DrawSprite, DrawText, and DrawRectangle. They all take an Element class as a parameter.

The Element class contains information such as indexes to the texture or font to use, but does not contain the actual texture or font. The actual textures and fonts are stored in the DialogResourceManager class. This ensures that there’s only one copy of the same texture or font loaded at all times.

To write text, you would call the dialog’s DrawText method passing in the text, Element, and rectangle specifying the position (relative to the dialog). DrawText would use the Element passed in to determine which font to use for rendering.

Likewise, to draw a texture, you would call the dialog’s DrawSprite method passing in an Element (which contains the index to the texture) and the rectangle containing position information.

User Input Processing

As you probably know, Windows communicates internally by using messages. sampleFramework’s MessageProc can intercept these messages. You then call the dialog’s MessageProc method which in turn relays it to the control’s MsgProc method. The messages are broken up and processed, and calls are made to HandleKeyboard and HandleMouse. Derived controls can override the HandleKeyboard and HandleMouse methods to add keyboard and mouse handling.

So, when you add your own dialog, you need to add an entry to call the dialog’s MessageProc. Here’s an example from line 340:

// Give the dialog a chance to handle the message first
noFurtherProcessing = hud.MessageProc(hWnd, msg, wParam, lParam);

if (noFurtherProcessing)
    return IntPtr.Zero;

Handling a Control’s Events

Handling control events is pretty simple. You just create a method for handling the event and bind it to the control’s event with an EventHandler. For example:

edit.Changed += new EventHandler(OnEditChanged);

edit is a textbox. When its text is changed, OnEditChanged will be called. Event binding should be called after adding the control to the dialog.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here