Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
106 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

  Contents

 Introduction
 GUI Controls
 We'll Need

 Breaking It Down
 Static Controls
 Pushbuttons
 Carets and The
 Textbox Control

 Progress Bars
 Sliders and
 Scrollbars

 Listbox Control
 Conclusion

 Printable version

 


  The Series

 Part I
 Part II
 Part III
 Part IV

 

Carets and The Textbox Control

I chose to implement a very simple textbox control. It just captures keys, and does no scrolling - but you might want something more complex, say, a control that accurately handles the home, end, insert, and delete keys, or maybe even one with support for cutting, copying, and pasting, via the windows clipboard.

But before we can have a textbox, we need a caret. In case you're not familiar with the terminology, a caret is another word for a cursor - that's right, that little blinking vertical bar. Carets tell the user where the text they type is going to go.

For the purposes of my GUI, I've made things simple - I've ordained that the active window is the window that has the caret, period. This is how most GUIs behave, and seems to be the best solution. Also, my GUI, like Windows, considers the "caption" of the textbox to be the text that's actually in the box.

So how do you implement the caret? Well, I decided that since it's a given that the caret always going to be drawn inside the active window, and that the caret will only appear if the active window is a textbox, it makes sense to consider the caret drawing code part of the textbox and implement it inside the textbox's draw function. This makes it really easy to implement - simply use an integer to represent an index into the character array of the window caption, and your textbox has all the information it needs to properly draw the caret.

Which means, basically, that if you're a textbox, all you have to do to render yourself is draw a border around your client area, draw your window caption inside this border, and then, if you're the active window, draw your caret at the correct position. In my GUI, the maximum length of a string inside a textbox is governed by the size of the textbox window, meaning that I don't have to deal with scrolling the text within the box. You, however, might want to some way for the user to scroll through the contents of a textbox, allowing them to enter a very long string in a very small box.

By far the most difficult thing about a textbox is the keyboard processing that comes with it. Once we have a key, it's easy to create a wm_keypressed() virtual function, and call it, and it's easy to implement the textbox handler for wm_keypressed() so that it processes the key, and either tacks it onto the end of the window caption, or processes special keys (backspace, etc. - this is where your heavyweight string class pays for itself), and moves the caret.

The hard part is getting the key in the first place. Windows provides no less than three completely different ways to query the keyboard - the WM_KEYDOWN event, the GetKeyboardState() and GetAsyncKeyState() functions, and of course, DirectInput. I used the DirectInput method, simply because I already had done most of the heavy-lifting associated with DirectInput back when I implemented the mouse cursor, and because getting the keyboard state through DirectInput seemed to me the cleanest and most elegant solution.

To use DirectInput's keyboard functionality, the first thing you need to do is set up a keyboard device. This is incredibly similar to how we set up the DirectInput mouse device way back in Part I of this article. Basically, the only difference here is that instead of telling DirectInput to treat our new device as a mouse, we're telling it to treat it as a keyboard (duh). If you've gone through DirectInput for the mouse, doing the same stuff again for the keyboard should be easy.

Once we've got our keyboard device we can query it.

To actual determine if a key was "hit" requires slightly more work. Basically, to determine which keys are pressed, you need two snapshots of all 101 key states - you need a snapshot from the last frame, and a snapshot from this frame. The keys that are down in this frame but not down last frame are the keys that have been "pressed," and they're the keys you should send out wm_keypressed() "messages" for.

Onto progress bars…


Next : Progress Bars