YOU CAN CODE!

 

With The Case Of UCanCode.net  Release The Power OF  Visual C++ !   HomeProducts | PurchaseSupport | Downloads  
XD++ Library
DocVizor
TFC Library
Free Products
Technical Support
UCanCode.net


Get Ready to Unleash the Power of UCanCode .NET


UCanCode Software focuses on general application software development. We provide complete solution for developers. No matter you want to develop a simple database workflow application, or an large flow/diagram based system, our product will provide a complete solution for you. Our product had been used by hundreds of top companies around the world!

"100% source code provided! Free you from not daring to use components because of unable to master the key technology of components!"


MFC Examples: MFC Solution to Explanding the CFileDialog Common Dialog

 
Milan Markovic 
January 30, 2000 

Introduction

Open Multiple Files

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.

Tucancode.netS

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 tucancode.net 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 tucancode.net 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

 

 

Copyright ?1998-2007 UCanCode.Net Software , all rights reserved.
Other product and company names herein may be the trademarks of their respective owners.

Please direct your questions or comments to webmaster@ucancode.net