Hello World Version 3: Add Command Handlers and Menu Bars

Version 3 provides a menu bar with an Alignment choice. A menu bar is the area near the top of a window, below the title bar and above the client area of the window, which contains a list of choices. By selecting the Alignment choice, the user can display a pull-down menu and align the "Hello, World!!!" text string to the left, right, or center. In addition, this version adds a status area to show the status of the text string and an event handler for the menu bar and the pull-down menu.

In covering these topics, this section shows you how to:

The main window for version 3 of the Hello World application looks like this:

[Picture]

Listing the Hello World Version 3 Files
You can find the following files in the samples/ioc/hello3 directory:

File Type of Code
ahellow3.cpp Source code for the main procedure, main window constructor, and command processing
ahellow3.hpp
Header file for the AHelloWindow and ACommandHandler classes
ahellow3.h Symbolic definitions file for the hello3.exe file
ahellow3.icc This configuration file differs on each platform.
ahellow3.rc Resource file for the hello3.exe file
ahellow3.ico Icon file for the hello3.exe file
makefile This makefile differs on each platform.

The Primary Source Code File
The ahellow3.cpp file contains the source code for the main procedure and the AHelloWindow and ACommandHandler classes. The tasks performed by this code are described in the following sections.

The AHelloWindow Class Header File
The ahellow3.hpp file, like the ahellow2.hpp file, contains the class definitions and interface specifications for the AHelloWindow and ACommandHandler classes, with a few modifications for version 3.

The Symbolic Definitions File
The ahellow3.h file contains the definitions for this application. These definitions provide the IDs for the application window components.

For version 3, the symbolic definition file contains a new window ID (WND_STATUS) for the status area and three new string IDs (STR_CENTER, STR_LEFT, and STR_RIGHT) for the text strings used in the status area. In addition, menu IDs (MI_ALIGNMENT, MI_CENTER, MI_LEFT, and MI_RIGHT) have been added for the menu bar Alignment choice and the Center, Left, and Right choices in the pull-down menu.

The Resource File
Version 3 provides a resource file, ahellow3.rc. This resource file assigns an icon and several text strings with the constants defined in the ahellow3.h file. It also contains the text strings for the menu bar. The ahellow3.h file is included in this resource file so the icon and text strings can be associated with the appropriate IDs.

The resource file for version 3 contains two primary additions. The first is the text strings that are assigned to the new string constants that were defined in ahellow3.h. These text strings are used in the status area to show the state of the static "Hello, World!!!" text string in the client area. For example, when the main window is first displayed, the "Center Alignment" text string is shown in the status area.

The second addition provides the text that appears on the menu bar (Alignment) and pull-down menu (Left, Center, and Right), indicating which choices are available. Each text string is assigned to a constant, also defined in ahellow3.h.

In an AIX or OS/2 resource file, the tilde (~) to the left of a letter in each text string indicates that the user can select those letters to select a menu item. This is an ampersand (&) in the Windows .rc file. In addition, the Windows .rc file uses the extended menu as follows:

WND_MAIN  MENUEX 
  BEGIN
    POPUP     "&Alignment"               ,  MI_ALIGNMENT
      BEGIN
        MENUITEM  "&Left"                    ,  MI_LEFT
        MENUITEM  "&Center"                  ,  MI_CENTER
        MENUITEM  "&Right"                   ,  MI_RIGHT
      END
  END

These are shortcut keys for the application. For example, the sample bevaves in the same way if you either press R or choose Right from the pull-down menu.

VisualAge C++ provides tools for converting Windows, AIX, and OS/2-style resources. See Convert Application Resources for more information about the resource file conversion tools.

The Icon File
The ahellow3.ico file is used as both the title bar icon and the icon that displays when the application is minimized. This icon is the same as for version 2.

VisualAge C++ provides tools for converting Windows, AIX, and OS/2 bitmaps and icons. See Convert Application Resources for more information about the bitmap and icon conversion tools.

Explore Hello World Version 3
The following sections describe each of the tasks performed by version 3 of the Hello World application that have not been described for previous versions.

Construct the AHelloWindow Object
Version 3 has made the following additions to the main window:

The following sections describe these additions.

Create a Status Line
The status line shows the text string alignment status. Use the IStaticText class to create the static text control to display a text string in a status area. The status area is a small rectangular area that is usually located at the top of a window, below the menu bar.

In the ahellow3.cpp file, an IStaticText object, called statusLine, is created with this instance of the AHelloWindow class as the parent and owner as follows:

AHelloWindow :: AHelloWindow(const unsigned long windowId)
  :IFrameWindow(IFrameWindow::defaultStyle() |
                IFrameWindow::minimizedIcon,
                windowId)
  ,menuBar(windowId, this)
  ,statusLine(WND_STATUS,this,this)
  ,hello(WND_HELLO, this, this)
  ,infoArea(this)
  ,commandHandler(this)
{
  // ...
}                                

The WND_STATUS constant provides the window ID for this static text control. This constant is defined in ahellow3.h.

Specify the Location and Height of the Status Area
Use the IFrameWindow member function addExtension in the ahellow3.cpp file to specify where the status area is positioned and how high it is. For example:

AHelloWindow :: AHelloWindow(const unsigned long windowId)
  :IFrameWindow(IFrameWindow::defaultStyle() |
                IFrameWindow::minimizedIcon,
                windowId)
  ,menuBar(windowId, this)
  ,statusLine(WND_STATUS,this,this)
  ,hello(WND_HELLO, this, this)
  ,infoArea(this)
  ,commandHandler(this)
{
  // ...
  addExtension(&statusLine,
               IFrameWindow::aboveClient,
               IFont(&statusLine).maxCharHeight());
  // ...
}

The aboveClient argument of the Location enumeration specifies that the static text control displays the status area above the client window.

The maxCharHeight member function returns the status area's maximum height, based on the current font.

Create a Menu Bar
Now you can create the Alignment menu bar to display the Left, Center, and Right choices. In the header file, ahellow3.hpp, menuBar is defined as an instance of the IMenuBar class as follows:

class AHelloWindow : public IFrameWindow
{
  // ...
  private:
    IMenuBar
      menuBar;
  // ...
};                                            

The ahellow3.cpp file uses menuBar to create a new instance of that class in the main window, as follows:

AHelloWindow :: AHelloWindow(const unsigned long windowId)
  :IFrameWindow(IFrameWindow::defaultStyle() |
                IFrameWindow::minimizedIcon,
                windowId)
  ,menuBar(windowId, this)
  ,statusLine(WND_STATUS,this,this)
  ,hello(WND_HELLO, this, this)
  ,infoArea(this)
  ,commandHandler(this)
{
  // ...
}

The WND_MAIN argument identifies the following menu in the ahellow3.rc resource file:

MENU WND_MAIN                        
  BEGIN
        SUBMENU "~Alignment", MI_ALIGNMENT     
          BEGIN
            MENUITEM "~Left",       MI_LEFT     
            MENUITEM "~Center",     MI_CENTER  
            MENUITEM "~Right",      MI_RIGHT    
          END
  END

The window ID for the menu must match the window ID of the frame window.

This menu puts one choice, Alignment, on the menu bar, and provides a pull-down menu with three choices: Left, Center, and Right.

In addition, the MI_ALIGNMENT, MI_LEFT, MI_CENTER, and MI_RIGHT menu item attributes correspond to those in the resource file's string table:

MI_ALIGNMENT,"Alignment Menu"            
MI_CENTER,  "Set Center Alignment"  
MI_LEFT,    "Set Left Alignment"   
MI_RIGHT,   "Set Right Alignment"

When the user moves the selection cursor over each menu item, the text string associated with that menu item displays in the information area below the client window. For example, when the cursor is on the Right menu item, the text string "Set Right Alignment" appears in the information area. For this to work, the string ID must match the corresponding menu item ID.

Set an Initial Check Mark in the Pull-Down Menu
The pull-down menu that displays when Alignment is selected on the menu bar contains three choices for aligning the "Hello, World!!!" text string: Left, Center, and Right. Because this text string is aligned in the center of the client area when the application is created, there should be a check mark next to Center the first time the pull-down menu displays.

The checkItem member function of the IMenuBar class lets you place a check mark on a pull-down menu choice. The following line, from ahellow3.cpp, places a check mark on Center:

AHelloWindow &
  AHelloWindow :: setTextAlignment(const Alignment alignment)
{
  switch(alignment)
  {
    // ...
    case center:
      hello.setAlignment(IStaticText::centerCenter);
      statusLine.setText(STR_CENTER);
      menuBar.checkItem(MI_CENTER);
      menuBar.uncheckItem(MI_LEFT);
      menuBar.uncheckItem(MI_RIGHT);
      break;
    // ...
  }
 return (*this);
}                                  

The MI_CENTER constant is defined in the ahellow3.rc resource file as the "Center" text string for the menu. Do not confuse this with the MI_CENTER menu item attribute defined in the string table, which is used only by the information area.

Stop Handling Command Events
After your application runs, you need to stop handling command events for the frame window and delete the objects you created using the new operator. The AHellowWindow destructor does this in the ahellow3.cpp file do this:

AHelloWindow :: ~AHelloWindow()                                             
{                                                                           
  commandHandler.stopHandlingEventsFor(this);
}

Align a Text String
This section shows you how to associate commands with the menu items to align the text string.

This sample shows command processing for one of the menu items. This code, from ahellow3.cpp, calls the AHelloWindow::setTextAlignment function to center-align the "Hello, World!!!" text string in the client window:

bool  ACommandHandler :: command(ICommandEvent & cmdEvent)
{
  bool eventProcessed(true);
  switch (cmdEvent.commandId())
  {
    case MI_CENTER:
      frame->setTextAlignment(AHelloWindow::center);
      break;
    case MI_LEFT:
      frame->setTextAlignment(AHelloWindow::left);
      break;
    case MI_RIGHT:
      frame->setTextAlignment(AHelloWindow::right);
      break;
    default:
      eventProcessed=false;
  }

  return(eventProcessed);
} 

The following code shows the setTextAlignment function from the AHelloWindow class:

AHelloWindow &
  AHelloWindow :: setTextAlignment(const Alignment alignment)
{
  switch(alignment)
  {
    case left:
      hello.setAlignment(IStaticText::centerLeft);
      statusLine.setText(STR_LEFT);
      menuBar.uncheckItem(MI_CENTER);
      menuBar.checkItem(MI_LEFT);
      menuBar.uncheckItem(MI_RIGHT);
      break;
    case center:
      hello.setAlignment(IStaticText::centerCenter);
      statusLine.setText(STR_CENTER);
      menuBar.checkItem(MI_CENTER);
      menuBar.uncheckItem(MI_LEFT);
      menuBar.uncheckItem(MI_RIGHT);
      break;
    case right:
      hello.setAlignment(IStaticText::centerRight);
      statusLine.setText(STR_RIGHT);
      menuBar.uncheckItem(MI_CENTER);
      menuBar.uncheckItem(MI_LEFT);
      menuBar.checkItem(MI_RIGHT);
      break;
 }
 return (*this);
} 

The preceding code does the following:

Add Text for a Status Line
The status area text strings are specified in the resource file, as shown in the following code:

MI_CENTER,  "Set Center Alignment"       
MI_LEFT,    "Set Left Alignment"             
MI_RIGHT,   "Set Right Alignment"       

The following code, from ahellow3.cpp, gets the "Center Alignment" text string from the resource file and puts it in the static text control for the status area:

AHelloWindow &
  AHelloWindow :: setTextAlignment(const Alignment alignment)
{
  switch(alignment)
  {
    // ...
    case center:
      hello.setAlignment(IStaticText::centerCenter);
      statusLine.setText(STR_CENTER);
      menuBar.checkItem(MI_CENTER);
      menuBar.uncheckItem(MI_LEFT);
      menuBar.uncheckItem(MI_RIGHT);
      break;
    // ...
  }
 return (*this);
}                                  

Instantiate the Command Handler
In version 3, the AHelloWindow class contains an ICommandHandler derived class, called ACommandHandler. This is necessary because, for the first time, this application handles events. In this case, the events are the commands that align the "Hello, World!!!" text string.

The following code in ahellow3.cpp creates a command handler from the ACommandHandler class:

AHelloWindow :: AHelloWindow(const unsigned long windowId)
  :IFrameWindow(IFrameWindow::defaultStyle() |
                IFrameWindow::minimizedIcon,
                windowId)
  ,menuBar(windowId, this)
  ,statusLine(WND_STATUS,this,this)
  ,hello(WND_HELLO, this, this)
  ,infoArea(this)
  ,commandHandler(this)
{
  // ...
  commandHandler.handleEventsFor(this);
  // ...
}

The second line of codein the preceding example contains the handleEventsFor member function inherited from the ICommandHandler class. Use this member function to set the event handler for the application. In this case, the this argument is specified.

This member function is available because the header file ahellow3.hpp includes the icmdhdr.hpp library header file, which contains the ICommandHandler class as follows:

#ifndef _AHELLOW3_
#define _AHELLOW3_

#include <iframe.hpp>
#include <istattxt.hpp>
#include <iinfoa.hpp>
#include <imenubar.hpp>
#include <icmdhdr.hpp>

Add Command Processing
The next statements construct the command handler from a pointer to the AHelloWindow that events will be handled for. The ahellow3.cpp file uses the ACommandHandler to create a command handler, as follows:

ACommandHandler :: ACommandHandler(AHelloWindow *helloFrame)                
   :frame(helloFrame)                       
{
}

Depending on the command event ID, you need to call the AHelloWindow::setTextAlignment function with the appropriate AHelloWorld::Alignment enumerator, as shown in the following sample from ahellow3.cpp:

bool                                                              
  ACommandHandler :: command(ICommandEvent & cmdEvent)                      
{                                                                           
  bool eventProcessed(true);     

  switch (cmdEvent.commandId()) {                                           
    case MI_CENTER:                                                         
      frame->setTextAlignment(AHelloWindow::center);                            
      break;                                                                
    case MI_LEFT:                                                           
      frame->setTextAlignment(AHelloWindow::left);                              
      break;                                                                
    case MI_RIGHT:                                                          
      frame->setTextAlignment(AHelloWindow::right);                             
      break;                                                                
    default:                                     
      eventProcessed=false;           
  }                                                     
 
  return(eventProcessed);                                                   
} 

The AHelloWorld::Alignment enumerator is defined in the ahellow3.hpp file:

class AHelloWindow : public IFrameWindow
{
  public:

    enum Alignment
    {
      left, center, right
    };

  // ...
};

ngrelc.gif
Resources
Windows
Events and Event Handlers

ngrelt.gif
Convert Application Resources
Add Menus to your Application
Add a Menu Bar
Write an Event Handler
Task and Samples Cross-Reference Table

ngrelr.gif (548 bytes)
IEvent
IHandler
IMenu