Hi
I've worked on a cross platform (PC\Consoles) gui system before and the what I did was run everything off a fake internal mouse pointer. For the PC the pointer position and buttons were fed in from the actual mouse whereas the consoles had two options...
1) Attach the pointer to directional controls or an analogue stick. This gave you one of those clumsy mice that are controlled by a pad and attach a pad button to left\right\middle clicks. This would get you a cross platform fuctioning interface albeit a clumsy one.
Or...
2) Move the (invisible) pointer to the center of a button. Each button had a set of controls which would tell it what to do when a direction was pressed. Imagine a menu that looked like...
START
HELP
QUIT
And the code for these two buttons was...
// if I press Down while on the startButton move the pointer to the center of the helpButton, if I press Up wrap round to the quitButton.
GuiButton_SetDownPressedAction( startButton, helpButton );
GuiButton_SetUpPressedAction( startButton, quitButton );
// if I press Down while on the helpButton move the pointer to the center of the quitButton, if I press Up move to the startButton.
GuiButton_SetDownPressedAction( helpButton, quitButton );
GuiButton_SetUpPressedAction( helpButton, helpButton );
// if I press Up while on the quitButton move the pointer to the center of the helpButton, if I press Down wrap round to the startButton.
GuiButton_SetDownPressedAction( quitButton, startButton);
GuiButton_SetUpPressedAction( quitButton, helpButton );
This way you could still tie everything to a mouse controlled system so all your highlights, click messages, etc would still work, you just set up the button presses to act like shortcuts. On a PC you could either not fire those events or make the keyboard fire them.
Button presses were handled the same, I went for a callback similar to the windows one where events were passed in so you'd attach a callback to a created window then if you press 'action' (for the PC this was mouse left click and console it was button A) everything would work like a charm. Essentially the only difference between the console and PC was having those Up, Down, Left, Right, etc set up to tell the gui where to move the mouse to. We tied those into the cursors\gamepad n the PC so you could operate the menus without needing the mouse if it suited the game.
Another thing we added was a default button when a window got focus. This was a message sent to the callback so you'd set the current pointer position to 'startButton' so that would be highlighted when you first began.
A list control was added by having it create a window and add, subtract buttons to it. The window would scroll when it needed to and the pad events were set up automatically as it was obvious which ones go to which. There was a flag to say whether it should wrap and that was it. A drop down box was exactly the same but was only visible when you clicked the drop down item. We did tinker with having the controller events set themselves up automatically but found with all the different uses the GUI was getting it was difficult to get it right all of the time. Sometimes what seemed like a logical jump turned out to be one you just didn't want to make. It also had troubles with the example above where you want a menu to wrap around.
The last thing was something we had to stick to which was while on a menu screen like the frontend in the bottom right corner for a console you'd have something like a picture of a start button with "OK" so when you pressed Start it would continue past that screen. On the PC it would be clumsy having to press a button that simulated start so we made it a standard button you click on. While the actual thing was a button, there wasn't a pad control set up that would allow the console user to get to it by pressing a direction as this would be clumsy for them. The solution was to set up a pad press to activate that button and behave like a click.
eg..
GuiButton_SetActivate( okButton, PAD_START );
and we had the same for a back button which was displayed in the lower left corner...
GuiButton_SetActivate( backButton, PAD_BACK );
We could also have PAD_START activated by pressing Enter on the keyboard for the PC and PAD_Back by pressing Escape (or by using a PC pad). Internally it just moved the pointer to the button it was on and send a click message.
Phew - I've rambled on a bit but I hope it's given you a few ideas.