MFC Solution to Explanding the CFileDialog Common Dialog

Introduction

This article explains how to expand the CFileDialog common dialog box. Although there are similar articles elsewhere on the Internet, none of them resolved the problem of adding user controls in CFileDialog in an MFC manner (without hook procedures, which are not encouridged by MFC any more).

In this article you'll find a way how to add one static control and one combo box control to CFileDialog standard dialog. The sample code is of no particular use as the problem is general, but briefly explains concept, and what is more important, I am using similar code in my applications.

TASKS

To add two controls to CFileDialog dialog box, we have to do following:
  1. Enlarge standard CFileDialog. This can be done by subblussing CFileDialog class and overiding OnInitDialog member function
  2. To retrieve information from additional controls, you must override OnDestroy() member function.

SAMPLE

The sample included here shows CFileDialogEx class, derived from CFileDialog using classwizard. Added member variable, m_nSubType, is used for displaying possible document subtypes. Choosen value is saved in the same variable and passed to document m_nDocSubType variable. CComboBox and CStatic objects are added for purpose of our sample.There are two message handlers that override standard WM_INITDIALOG and WM_DESTROY messages for CFileDialogEx object:
///////////////////////////////////////////
// CFileDialogEx dialog
class CFileDialogEx : public CFileDialog
{
 DECLARE_DYNAMIC(CFileDialogEx)

public:
 int m_nSubType;
 CStatic m_Static;
 CComboBox m_Combo;  // our combo box control

 // TRUE for FileOpen, FALSE for FileSaveAs
 CFileDialogEx(BOOL bOpenFileDialog, 
  LPCTSTR lpszDefExt = NULL,
  LPCTSTR lpszFileName = NULL,
  DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
  LPCTSTR lpszFilter = NULL,
  CWnd* pParentWnd = NULL);

protected:
 //{{AFX_MSG(CFileDialogEx)
 virtual BOOL OnInitDialog();
 afx_msg void OnDestroy();
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
};
Our first task is done by adding handler for WM_INITDIALOG:
BOOL CFileDialogEx::OnInitDialog() 
{
 CFileDialog::OnInitDialog();
 
 // TODO: Add extra initialization here

 // We need to enlarge standard CFileDialog to make space 
 // for our controls idea from Christian Skovdal Andersen 
 // article - Customizing CFileDialog
 char szText[120];
    
 // This variable should be changed acording to your wishes
 const UINT iExtraSize = 50;
 // Get a pointer to the original dialog box.
 CWnd *wndDlg = GetParent();
 RECT Rect;

 wndDlg->GetWindowRect(&Rect);
 // Change the size of FileOpen dialog
 wndDlg->SetWindowPos(NULL, 0, 0, 
                        Rect.right - Rect.left, 
                        Rect.bottom - Rect.top + iExtraSize, 
                        SWP_NOMOVE);

 // Standard CFileDialog control ID's are defined in 
 // Do not forget to include  in implementation file

 // cmb1 - standard file name combo box control
 CWnd *wndComboCtrl = wndDlg->GetDlgItem(cmb1); 

 wndComboCtrl->GetWindowRect(&Rect);
 wndDlg->ScreenToClient(&Rect); // Remember it is child controls

 // Put our control(s) somewhere below HIDDEN checkbox
 // Make space for 3 different subtypes
 Rect.top += 60;
 Rect.bottom += 120;
 Rect.left += 50;

 // Our control is CComboBox object

 // IMPORTANT: We must put wndDlg here as hWndParent, 
 // NOTE: "this" as written in Microsoft documentation 
 // example

 // NOTE: IDC_MYCOMBOBOX and IDC_MYSTATIC must be defined 
 // (best in resource.h)
 m_Combo.Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWN 
  | CBS_SORT | WS_VSCROLL | WS_TABSTOP,
  Rect, wndDlg, IDC_MYCOMBOBOX);

 // save new control font according to other controls font
 m_Combo.SetFont(wndComboCtrl->GetFont(), TRUE);
 m_Combo.SetFocus();

 // We also need Static Control. Get coordinates from 
 // stc3 control
 CWnd *wndStaticCtrl = wndDlg->GetDlgItem(stc2);
 wndStaticCtrl->GetWindowRect(&Rect);
 wndDlg->ScreenToClient(&Rect);
 Rect.top += 60;
 Rect.bottom += 80;
 Rect.right += 40;

 // our static control
 m_Static.Create("Proba", WS_CHILD | WS_VISIBLE, Rect, 
  wndDlg, IDC_MYSTATIC);

 m_Static.SetFont(wndComboCtrl->GetFont(), TRUE);

 // Now, fill up static control and combo control
 // Our ComboBox control will offer three diffirent file 
 // subtypes. Current file subtype is held in m_nSubType 
 // member variable which will hold resulting (final) subtype, 
 // also.
 for (int i=0; i < 3; i++) {
  sprintf(szText, "Subtype%d", i);
  wndDlg->SendDlgItemMessage(IDC_MYCOMBOBOX, CB_INSERTSTRING,
   (WPARAM) (-1), (LPARAM) (szText));
  // Set displayed subtype to sybtype format of working file
  if (m_nSubType == i)
   wndDlg->SetDlgItemText(IDC_MYCOMBOBOX, szText);
 }
 // Add some general text for static box
 sprintf(szText, "File SubType Format");
 wndDlg->SetDlgItemText(IDC_MYSTATIC, szText);
 
 return TRUE;  // return TRUE unless you set the focus 
               // to a control
               // EXCEPTION: OCX Property Pages should 
               // return FALSE
}
Second task is done by adding message handler for WM_DESTROY message:
void CFileDialogEx::OnDestroy() 
{
 CFileDialog::OnDestroy();
 
 // TODO: Add your message handler code here
 char szText[40];

 // get/save SaveAs file subtype
 if (GetParent()->GetDlgItemText(IDC_MYCOMBOBOX, 
  szText, sizeof(szText)) > 0)
 {
   m_nSubType = szText[strlen(szText)-1] - '0';
 }
}

IMPLEMENTATION

Probably you'll add message handler for ID_EDIT_SAVEAS menu item:
void CMyFileDialogDoc::OnFileSaveAs() 
{
 // TODO: Add your command handler code here
 
 // Call our Save As dialog box
 CFileDialogEx filedialog(FALSE, NULL, GetTitle(),
  OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY 
  | OFN_OVERWRITEPROMPT,
  NULL);

 // pass document subtype to our SaveAs dialog box
 filedialog.m_nSubType = m_nDocSubType;

 filedialog.m_ofn.lpstrTitle = 
  "User added controls - Save File As";

 // display our dialog
 if (filedialog.DoModal() == IDOK)
 {
  // get/save document subtype
  m_nDocSubType = filedialog.m_nSubType;
  
  char szText[100];
  sprintf(szText, "Document will be saved under "
   "subtype %d", m_nDocSubType);

  AfxMessageBox(szText);

  // do your own SaveAs procedure or call document default
  // CDocument::OnSaveDocument()
 }
 
 // error handling (if any)
 // ...
}
Comparing this with hook procedures and user-added templates, that I had to prepare in my earlier API samples, this seems to be much elegant. Only problem was bad Microsoft documentation that used "this" pointer instead of parent window (as explained earlier) while creating user controls. Also, you cannot override OnOK() member function in CFileDialog dialog as you can do that in other dialogs. You should check/save data from your controls in OnDestroy() message handler.

I included demo project that shows trivial use of CFileDialogEx class, but it should be used only as reference for your own purposes.

Downloads

Download demo project - 19 Kb


Comments

  • Does this way to expanding FileDialog still works under Seven+

    Posted by Bernard on 03/13/2013 07:22am

    Works fine under XP, but no success under seven

    Reply
  • Does this way to expanding FileDialog still works under Seven+

    Posted by Bernard on 03/13/2013 07:20am

    Works fine under XP, but no success under seven !

    Reply
  • Interesting

    Posted by snareenactina on 01/04/2013 02:58am

    acquiring China 14.6%, France 11.4%, South Africa 6.4%, India 5.4%, Bahrain 4.6%, US 4.3%, Singapore 4.1% (2009) Haiti's new government faces an enormous economic challenge. Haiti is the poorest country in the Western Hemisphere and among the poorest countries in the world. Two thirds of Haiti's eight million citizens live in poverty. Half of its adult population is illiterate. Only a quarter of its children attend school. Since a brief spike in the 1970's, Haiti's economy has experienced a steady decline as a result of rapacious government policies and, possibly well intentioned, but destructive international sanctions. Thank you for sharing this. It was an eye-opening and powerful read for me. quid Malaysia showed improvements in its online procedures for starting a business, speedy registration of properties and notable ease in tax procedures especially with the introduction of online tax submissions. bethe Free Press Apps for iPhone, Android now available. hamset We are all never going to agree 100 percent on everything. But hopefully by debating the issues things are starting to become more clear for all of us. unconvinced On 1 April 1998, Festus Mogae succeeded Quett Masire after the latter stepped down. Mogae was subsequently elected president in the 16 October 1999 polls with 54.3% of the National Assembly vote. He faced a number of issues such as environmental degradation, the need to diversify the economy, and political power struggles within the ruling party. negligencei Has he given a reason why? Are the banks having liquidity problems again? lankas Follow us: tiraa Well over all this was a fun game. What i didn’t like about this game is all you do basically is press a button and wait for the outcomes. Sure your castle changes and you get more people but over all its the same movement for the people ALL THE TIME and the background changes every level but it is a boring and bleak background. And everytime you battle there is no movement and the sound is the same whenever somebody gets hit. I know that seems like a lot of bad things but overall its a fun addicting game. I think that it was fun because you dont get the same outcome twice, theres a lot of levels, and you get to manage your people, buy items, and change locations. I think this game is great mainly for kids because adults wont be as easily entertained by it, but does give about a half an hour of fun every so often. ENJOY!

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Flash technology is becoming more prominent in the storage industry. Offering superior speed and reliability when compared to traditional hard disk drives – flash storage is a flexible and increasingly cost-effective technology that can be used to optimize enterprise storage environments. This ebook explores the many uses and benefits of flash storage technology in the enterprise. Check it out to discover and learn all you need to: Optimize storage performance Leverage server flash as storage cache …

  • Live Event Date: August 20, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT When you look at natural user interfaces as a developer, it isn't just fun and games. There are some very serious, real-world usage models of how things can help make the world a better place – things like Intel® RealSense™ technology. Check out this upcoming eSeminar and join the panel of experts, both from inside and outside of Intel, as they discuss how natural user interfaces will likely be getting adopted in a wide variety …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds