Using Common Dialogs

Common dialog boxes make it easier for you to develop
applications. These dialog boxes provide common, consistent functions that applications can use to help the end user increase his productivity. Although a wide range of function is available, the simplest applications can make use of these to provide a consistent look-and-feel with a minimal coding effort.

The Open Class Class Library provides several classes to enable you to use common dialog boxes. This chapter covers these classes that provide access to the Open Filename dialog, the Save As Filename dialog, and the Font Selection dialog.

A dialog box is a special, short-lived window that you use to display information and receive input from the user in a structured dialog format. The information is typically related to a particular action being performed by the application.

If you develop portable applications, use a canvas for dialog windows.


Specifying File Dialog Information

Many applications work with information stored in files.
Whenever a user wants to retrieve information stored in a file, the user must select the name of the file from which to get the data. The same holds true when the user wants to save any work that is in progress for future reference.

The file dialog enables a user to specify a file to be opened or
a file name in which current work is to be saved. It provides basic functions that you can extend to meet the requirements of your application. These basic functions give users the ability to:

The Open Class Library provides the IFileDialog and
IFileDialog::Settings classes to create and display file dialogs
in your application.

IFileDialog::Settings is a settings type class,
which defines data, styles, and attributes of a file dialog. You create IFileDialog::Settings objects and use them to create an IFileDialog object. This object governs the usage and appearance of the file dialog, as well as returning the file name choice (or choices in the case of multiple selection) that the user made.

Before you can create an IFileDialog, you first need to create an IFileDialog::Settings object. To create this settings object, follow these steps.

  1. Create a default IFileDialog::Settings object, as shown in the following example:
        IFileDialog::Settings   fsettings;
    
  2. Initialize this settings object using the member functions available. While the default settings may be suitable for many applications, most application developers modify one of more these settings. Some of the more common settings that you can change are the following:
     
    Dialog type
    The setOpenDialog and setSaveAsDialog member functions are used to specify the type of file dialog that will be displayed.
    Note: The default type of the file dialog is an Open dialog. If you want a Save As dialog, use the setSaveAsDialog member function.
    Initial file name displayed
    The setFileName member function is used to specify the initial file name that is shown when the file dialog is displayed.
    Dialog position
    The setPosition member function is used to specify the placement of the file dialog, relative to the window that owns the dialog.
    Dialog title
    The setTitle member function is used to specify the text that is displayed in the title bar of the dialog.

    The following example shows some of these being initialized for the object created in the previous example:

        
        fsettings.setSaveAsDialog();            // The dialog type is Save As,
        fsettings.setFileName( "example.txt" ); // the initial filename displayed is example.txt,
        fsettings.setTitle( STR_MYAPP );        // and the title is loaded from a resource file
    

Now that you have a settings object created, you can create an IFileDialog object. There are several ways to construct an IFileDialog object, but in general you need to provide the owner and parent windows and a settings object. Optionally, you can provide different dialog styles to control the appearance and functionality of the dialog, but these have defaults and do not need to be modified for many applications. The IFileDialog object can be constructed using the following statements:

IFileDialog* fdialog = new IFileDialog( // Create file open dialog
                       desktopWindow(), // parent is desktop 
                       this,            // owner is me
                       fsettings );     // use the settings defined above.

When the dialog is dismissed, you need to check the actions of the end user to determine if he has selected any file names to be used by your application. You can test the response from the file dialog using the pressedOK member function. This member functions returns true if the user ended the dialog by pressing the OK push button. It returns false if the user pressed Cancel or an error occurred. The test can be done with the following statement:

    if ( fdialog.pressedOK() )

If the end user pressed OK, then the file name (or names)
selected can be retrieved from the dialog using the fileName member function. This function returns the fully qualified file name, which includes drive and directory information. For a single selection style of the file dialog, the following statement is used:

    IString fname = fdialog.fileName();

For a multiple selection style of the file dialog, the following statements are used:

    
    int count = fdialog.selectedFileCount();  // Retrieve # of files selected
    int i;
    for ( i=1; i <= count; i++ )              // For each file selected,
    {                                         //  retrieve the fully-qualified
      IString fname = fdialog.fileName(i);    //  file name into a string
      ...                                     // Process it
    }                                         //  and then get the next one


For a complete code sample, see the openFile member function in the ahello6.cpp file (Hello World version 6). The Hello World samples are in the \samples\ioc directory.

Creating a File Dialog

The following example demonstrates creating both an Open file dialog and a Save As file dialog.

  1. Define the main window and a command handler to handle menu command events, as follows:
    class MyCommandHandler : public ICommandHandler {   public:
         MyCommandHandler( MyWindow* theOwner );
         virtual
            ~MyCommandHandler();
         virtual bool
            command( ICommandEvent& event );
     
      private:
         MyWindow
           *owner,
           *parent;
    };
     
    class MyWindow : public IFrameWindow
    {
       public:
          MyWindow();
     
       private:
           ITitle title;
           IMenuBar menu;
           MyCommandHandler cmds;
    };
    


  2. Create the main window:
    MyWindow::MyWindow() :
              IFrameWindow( ID_MAIN ),
              title( this, "File Dialog Example" ),
              menu( ID_MENU, this ),
              cmds( this )
    {
      cmds.handleEventsFor( this );
      setFocus().show();
    }
    

  3. Create the file dialogs based on the menu command events:
    bool MyCommandHandler::command( ICommandEvent& event )
    {
      bool
        rv = false;
      IMessageBox
        msgbox( owner );
     
      switch ( event.commandId() )
      {
        case ID_FILE_OPEN :
        {
          IFileDialog::Settings fileSettings;
          fileSettings.setTitle( "Open the Specified File" ); // Set open dialog title
          fileSettings.setFileName( "*.cpp" );                // Set file names to *.cpp
          IFileDialog filedlg( parent, owner, fileSettings );
          if ( filedlg.pressedOK() )
          {
            msgbox.show( IString( "You selected the file '" )
                         + IString( filedlg.fileName() )
                         + IString( "'." ),
                         IMessageBox::okButton );
          }
          break;
        }
     
        case ID_FILE_SAVEAS :
        {
          IFileDialog::Settings fileSettings;
          fileSettings.setTitle( "Save to the Specified File" );  // Set save-as dialog title
          fileSettings.setFileName( "noname.txt" );              // Set file name to noname.txt
          fileSettings.setSaveAsDialog();
          IFileDialog filedlg( parent, owner, fileSettings );
          if ( filedlg.pressedOK() )
          {
            msgbox.show( IString( "You saved the file '" )
                         + IString( filedlg.fileName() )
                         + IString( "'." ),
                         IMessageBox::okButton );
          }
          break;
        }
      }
      return rv;
    }
    


The following figure shows the file dialog created using the preceding example:



Specifying Font Dialog Information

Many applications display information to users in a variety of ways, many of them textually based. A common action that users perform is selecting a font with which to display or print this textual information. A font represents all of the characters of one style of type in one size.

The font dialog provides a dialog you can implement to enable users to view and select the font family names, styles, and sizes available in an application. It provides basic functions that you can extend to meet the requirements of your application. These basic functions give users the ability to display and select from a list of the following:

In addition, users can view their selections using a sample character string in a preview area, and interact with a modal or modeless font dialog.

The Open Class Library provides the IFontDialog class to create and display font dialogs in your application.

IFontDialog::Settings is a settings type class that defines data, styles and attributes of a font dialog. You create IFontDialog::Settings objects and use them to create an IFontDialog object. This object governs the usage and appearance of the font dialog, as well as returning the font chosen by the user.

Before you can create an IFontDialog, you first need to create an IFontDialog::Settings object. To create this settings object, follow these steps:

  1. Create an IFontDialog::Settings object, passing it the initial font to be used, as shown in the following example:
        
        IFont tempFont( &hello );        // Create a font from the hello window
        IFontDialog::Settings            // Create the initial settings object
          fsettings( &tempFont );        //  from the font
    


  2. Initialize this settings object using the many member functions available. While the default settings are suitable for many applications, most application developers modify one of more these settings. Some of the more
    common settings that you can change are the following:
    Preview text
    The setPreviewText member function is used to specify the text string that is used to demonstrate how the selected font will look if selected.
    Dialog position
    The setPosition member function is used to specify the placement of the font dialog, relative to the window that owns the dialog.
    Dialog title
    The setTitle member function is used to specify the text that is displayed in the title bar of the dialog.

    The following example shows these being initialized for the object created in the previous example:

        fsettings.setPreviewString( "ABCDabcd" );  // Use this string to demo type,
        fsettings.setPosition( IPoint( 50, 20 ) ); // position at 50,20 in owner,
        fsettings.setTitle( "Choose font" );       // and the title is Choose font
    

Now that you have a settings object created, you can create an IFontDialog object. There are several ways you can construct an IFontDialog but in general, you need to provide the owner and parent windows and a settings object. Optionally, you can provide different dialog styles to control the appearance and functionality of the dialog, but these have defaults and do not need to be modified for many applications. The IFontDialog object can be constructed using the following statements:

    
   IFontDialog* fdialog = new IFontDialog(  // Create font dialog
      desktopWindow(),                       // Parent is desktop
      this,                                  // Owner is me
      fsettings );                           // Use the settings defined above

When the dialog is dismissed, you need to check the actions of the end user to determine if he has selected a valid font to be used by your application. You can test the response from the font dialog using the pressedOK member function. This member functions returns true if the user ended the dialog by
pressing the OK push button. It returns false if the user pressed
Cancel or an error occurred. The test can be done with the
following statement:

    if ( fdialog.pressedOK() )

If the end user did press OK, the tempFont object that was used to initialize the settings object is automatically updated to be an IFont object that reflects the users selection. Your application can now use this font to change how you display textual information to your users. This is done using either the setWindowFont member function (a function of IFont which accepts a window to apply the font to) or the setFont member function (a function of IWindow which accepts a font to apply to the window). can be used. The latter is shown in the following statement:

    hello.setFont( &tempFont );

Creating a Font Dialog

The following section describes how to create a font dialog
using the Hello World version 6 application. The following code comes from the ahellow6.cpp file:

AHelloWindow &
  AHelloWindow :: setHelloFont()                             
{                                                                        
/*------------------------------------------------------------------------|
|  Set the text in the information area from the font dialog information  |
|    string in the resource file.                                         |
|  Create a font from the current font of the hello static text object.   |
|  Create a font settings object from the tempFont object.                |
|  Set the title to be used in the font dialog from a string resource in  |
|    the resource file.                                                   |
|  Start the font dialog by creating an IFontDialog object.  The font     |
|    dialog is created as a modal dialog window with the desktopWindow    |
|    as the parent, the AHelloWindow frame as the owner, resetButton      |
|    style which supplies the user with a way to reset the fields in the  |
|    dialog, and the font settings that were just created.                |
|------------------------------------------------------------------------*/
  infoArea.setDefaultText(STR_FONTDLGT);
  IFont tempFont(&hello);                                            
  IFontDialog::Settings fontSettings(&tempFont);         
  fontSettings.setTitle(IResourceId(STR_FONTDLGT));                      
  IFontDialog fontDialog( desktopWindow(), this,                         
                          IFontDialog::resetButton, fontSettings);        

/*------------------------------------------------------------------------|
|  If the user pressed OK in the font dialog, then change the font for    |
|    the hello IStaticText object using the tempFont object that was set  |
|    by the font dialog.                                                  |
|  Reset the information area inactive text.                              |
|------------------------------------------------------------------------*/
  if (fontDialog.pressedOK())
  {
    hello.setFont(tempFont);
  }
  infoArea.setDefaultText(STR_INFO);
  return (*this);                       // Return a reference to the frame
}; /* end AHelloWindow :: setHelloFont() */                   

In the preceding sample, the font in an IStaticText control is changed to the font the user selects from an IFontDialog. We accomplished this by doing the following:

  1. Creating an IFont object called tempFont that represents the font currently being used by the IStaticText control pointed to by hello
  2. Passing a pointer to the tempFont object on the constructor to an IFontDialog::Settings object called fsettings
  3. Passing the fsettings object on the IFontDialog constructor

Because fontSettings is constructed using tempFont, the IFontDialog initially displays the name, style, size, and emphasis associated with tempFont (for example, the font currently used by the IStaticText object). If the user dismisses the IFontDialog by pressing OK, then tempFont automatically updates itself to reflect the font the user chose via the IFontDialog. The setFont member function can be used to actually change the font of the IStaticText control to tempFont.

The following shows an example of a font dialog:



Hello World Version 4: Adding Dialogs and Push Buttons
Constructing Fonts
Layout Using Canvas Controls


ICanvas
IFileDialog
IFont
IFontDialog