It just depends on how deep you want to go with this. A very simple, rudimentary implementation would be one where the GUI can ONLY go one level deep so you don't have to manage convoluted ownership privileges and object relationships. However, in general, they key to a good UI is to keep it as *decentralized* as possible. Where the relationships from one "thing" to another "thing" are very loose and easily modified. This normally leads to an object relationship in where there may be 100 or so very small class objects for GUI objects (radio buttons, labels, scroll bars, etc) and the importance is based on their relationship to the parent.
This can be accomplished very easily *IF* you are extremely comfortable with polymorphic design characteristics. So the most important thing to do first, is to figure out what type of THINGS GUI's have. Windows, buttons, radio buttons, labels, title bars (or not?), drop down menus, are these things clickable, non-clickable? Is there an event associated with a click, etc etc. So at the top level it becomes pretty apparent that there are two main distinctions you have to make (there are 2 fundamental broad objects to a UI): The WINDOW, and the OBJECT. The window is nothing, the window is your pretty GUI wrapper that looks nice, can be moved around, can be minimized, maximized, and so forth. This is an easy container to write because it's not really related to other windows, and they're normally see as individual entities. GUI Objects, however, are your buttons, labels, radio buttons, etc... Objects distinguish themselves (normally) from windows in that they are almost ALWAYS tied to "action". They DO something. These actions are easily defined by modifiable and user-specifiable callback functions. For every object, for every type of event ("OnMouseUp", "OnMouseDown", "OnKeyUp", "OnKeyDown", etc) there is SOME event that has to take place. When OBJECTS are created they are registered to a particular callback function that will do something whenever an action that concerns it has taken place.
So THAT relationships requires a little more information about the primary GUI container. Which is simply an interface to the GUI system as a whole....it's the gears that keep everything together. The GUI container contains an extremely fast doubly ended linked list of Window objects. And in turn, all window objects contain an extremely fast doubly ended linked list of Objects. So the relationship is "Windows have Objects and UI has windows". This linked list is sorted from back to front (for transparency purposes), which lends itself well because then automatically the top level window is the active one. When an event comes through (which GUI constantly monitors for mouse clicks and keypresses), the UI container will first look at the top level window to see that you've clicked inside it's bounds (simple bounding box check). If so, the window must search through it's object list to determine if an object owns this action (another bounding box check). The doubly linked list is fantastic for this because you can search from the front forwards and from the back backwards at the same time. You can subdivide this action to happen 4x....you can subdivide that action to happen 8x (divide and conquer)...8 pointers going forwards and backwards can pinpoint a window that has 100 (or more) objects VERY quickly. Anyways, if the mouse click has happened within the bounds of an object, it's callback function is executed and ....something...happens....whatever that may be.
The objects themselves, whether they are radio buttons, buttons, text boxes, list boxes, scroll bars, etc....are ALL derived from a generic base object class. Where every child can redefine render methods, and event methods. Event methods are mouse clicks and keypresses usually. The base class holds everything common to everything that is an object, like x, y, width, height, isVisible, callback func ptr (if it has one...for instance text fields probably wouldnt need one), etc. The relationships between windows and objects is very easily expressed and when creating a window, the UI class returns a handle. Then to create an object you do this via the window object directly: window* myWin = gui->GetWindow(windowHandle); window->CreateButton(new_button). Or indirectly... gui->CreateObject(windowHandle) which assigns an object to a window.
Here is an extremely simple, unoptimized version of kindof what happens there:
http://pastebin.com/m5e28cc7b
You'll see as you hash it out, that the best way to represent things in a UI is as arbitrary and decentralized as possible. The UI doesn't KNOW anything about List boxes, or radio buttons, or buttons, or title bars....it only KNOWS about objects. Objects only have meaning given context and in a good polymorphic design, the Object can be a few things

Irregardless of WHAT they are they ALL perform action and return back. In this way, it allows for extraordinarily generic code and very generic containers which minimize size and maximize readability.
So that's kindof a rough guide on how we implemented ours. This is what it looks like.
Fullsize:
http://s119.photobucket.com/albums/o121 ... titled.png