In a previous post, I showed how to read input from the debug serial port on a Windows CE device.  As promised then, I will now use that to create a simple menu driven application.  When I say simple, I really mean that there are better ways to do it.  What I am going to develop here works, but quite frankly it is a little cumbersome to maintain, more on that later.

My plan here is to have a generic function that will display the menu and wait for valid user input.  It will then return the menu selection as an index to the caller.  So if the function is to be generic, seems like we should pass in an array of strings to be displayed as the menu.

I named the function MenuHandler() and set the input argument to be a TCHAR **, a pointer to an array of pointers to TCHAR.  The last entry of which is a NULL pointer.  The return value is an int which is the index of the item that was selected from the menu.

 int MenuHandler( TCHAR **MenuList )

So now let's "display" the menu, or really output it on the debug serial port.  For that it is a loop through the MenuList until we find the NULL pointer outputtng the menu as we go.  For each string in the menu we will assign a lower case alpha character to it, which the user will enter to select the menu item.  Nothing too exciting or unusual about this:

 int Count;
 for( Count = 0; MenuList[ Count ] != NULL; Count++ )
 {
  RETAILMSG(1, (TEXT("\t%c : %s\r\n"),
   'a' + Count,
   MenuList[ Count ] ));
 }

It occured to me that each menu will have one thing in common, that is that it need a way to return to the previous menu.  Keeping it simple, I will call that "Quit" and automatically append Quit to each menu after displaying the menu:

 RETAILMSG(1, (TEXT("\t%c : %s\r\n"), 'a' + Count, TEXT("Quit")));

So now, the value Count is the number of menu items currently displayed.  We will use that to validate the input.

Now it is time to get the input from the user.  Of course, I will use the GetInput() function that I talked about last time:

 int keyPress;
 keyPress = GetInput();

That gets us the user input when it comes in on the debug serial port.  Now we just need to check that it is valid for this menu.  Remember that when we output the menu, I assigned a lower case alpha character to each menu item:

 if( keyPress >= 'a' && keyPress <= ('a' + Count ))
  return( keyPress - 'a' );


Now we have a way to display the menu, get input and validate it.  Of course if the input is not valid, we need to loop and wait for the input again.  I found that it is important that when this occurs that we display the menu again.  This is becuase we are using the debug serial port which means that we could be getting other output displayed messing up what the user is seeing.  So this gives a simple way for the user to request a redraw.

Remember that function that I added last time that clears the input, ClearInput().  Time to use that also.  If the user has pressed any keys before using the menu, those will be used as input, so let's clear them out.

The final function looks like this:


int MenuHandler( TCHAR **MenuList )
{
 int Count;
 int  keyPress;
 ClearInput();
 do
 {
  for( Count = 0; MenuList[ Count ] != NULL; Count++ )
  {
   RETAILMSG(1, (TEXT("\t%c : %s\r\n"),
    'a' + Count,
    MenuList[ Count ] ));
  }
  RETAILMSG(1, (TEXT("\t%c : %s\r\n"), 'a' + Count, TEXT("Quit")));
  keyPress = GetInput();
  if( keyPress >= 'a' && keyPress <= ('a' + Count ))
   return( keyPress - 'a' );
  
 } while (TRUE);
}


Next time, I will finish this up with a function that has a menu and handles the user input.

Copyright © 2008 – Bruce Eitman
All Rights Reserved