File Open and Save As Dialogs for MFC Applications Using GDI+


Introduction

The CGdiplusFileOpenDialog and CGdiplusFileSaveAsDialog classes offer an easy way to implement File Open and Save As dialogs in MFC applications that use GDI+.

The main features are:

  • They dynamically load information about the supported image decoders/encoders and construct the file filters list.
  • They get the current image encoder identifier (CLSID) to be used in GDI+ functions that require it as an argument.
  • They check and validate the file name and extension.

You can find more details in the class descriptions and demo application.

Hierarchy Chart

The CGdiplusFileDialog Class

CGdiplusFileDialog is derived from the MFC CFileDialog class and is an abstract base class for CGdiplusFileOpenDialog and CGdiplusFileSaveAsDialog. It performs the following tasks:

  • Encapsulates an array containing information about supported decoders/encoders (m_arrCodecInfo)
  • Implements the base function TranslateFilter that converts an MFC-like file filter (using the ‘|’ character as a separator) into an OPENFILENAME structure file filter (using ‘\0’ as a separator)
  • Declares two pure virtual functions, FillCodecInfoArray and ConstructMFCStyleFilter; in the derived classes, the overridden functions perform specific operations
  • Overrides CFileDialog::DoModal; before calling base class function, it
    • Checks whether the GDI+ library is initialised
    • Calls the FillCodecInfoArray, ConstructMFCStyleFilter, and TranslateFilter functions

The CGdiplusFileOpenDialog Class

CGdiplusFileOpenDialog implements the File Open common dialog.

  • Overrides CGdiplusFileDialog::FillCodecInfoArray and calls Gdiplus::GetImageDecoders to fill an array of information about available decoders:
    • Name of the file format (for example, “JPEG”)
    • Used extensions (for example, “*.JPG;*.JPEG;*.JPE;*.JFIF”)
    • Default extension to be used in Save As dialog (for example, “JPG”)
    • Decoder identifier (CLSID)
  • Overrides CGdiplusFileDialog::ConstructMFCStyleFilter that constructs an “MFC style” filter (using a ‘|’ as a separator); an additional “All GDI+ supported” filter item is added

Example

#include "GdiplusFileOpenDialog.h"
// ...
bool CFoo::LoadImage(Image*& pImage)
{
   bool bLoaded = false;
   CGdiplusFileOpenDialog dlgFile;
   if(IDOK == dlgFile.DoModal())
   {
      CString strPathName = dlgFile.GetPathName();
      pImage = Image::FromFile(strPathName.AllocSysString());
      Status status = pImage->GetLastStatus();
      if(Ok == status)
      {
         bLoaded = true;
      }
   }
   return bLoaded;
}

The CGdiplusFileSaveAsDialog Class

CGdiplusFileSaveAsDialog implements the File Save As common dialog.

  • Overrides CGdiplusFileDialog::FillCodecInfoArray and calls Gdiplus::GetImageEncoders to fill an array of information about available encoders:
    • Name of the file format (for example, “BMP”)
    • Used extensions (for example, “*.BMP;*.DIB;*.RLE”)
    • Default extension to be used in Save As dialog (for example, “BMP”)
    • Decoder identifier (CLSID)
  • Overrides CGdiplusFileDialog::ConstructMFCStyleFilter that constructs the “MFC style” filter (using a ‘|’ as a separator)
  • Overrides CFileDialog::OnInitDone and CFileDialog::OnTypeChange to set the default extension and store the default encoder identifier (m_clsid member variable)
  • Implements the public method GetCodecCLSID; the codec CLSID can further be passed to the Gdiplis::Image::Save function
  • Overrides CFileDialog::OnFileNameOK to perform file name extension checking:
    • If the file name has no extension, the default extension and CLSID is used
    • If the file name has an extension and can be found in the codec info array, that extension and the corresponding CLSID will be used instead of the default
    • If the file name has an extension and cannot be found in the codec info array, it returns TRUE and the dialog remains displayed to allow the user to enter another file name

Example

#include "GdiplusFileSaveAsDialog.h"
// ...
bool CFoo::SaveImage(Image* pImage)
{
   bool bSaved = false;
   CGdiplusFileSaveAsDialog dlgFile;
   if(IDOK == dlgFile.DoModal())
   {
      CLSID clsid = dlgFile.GetCodecCLSID();
      CString strPathName = dlgFile.GetPathName();
      Status status = pImage->Save(strPathName.AllocSysString(),
                                   &clsid);
      if(Ok == status)
      {
         bSaved = true;
      }
   }
   return bSaved;
}

More by Author

Must Read