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:
-
Enlarge
standard CFileDialog.
This can be done by subblussing CFileDialog
class and overiding OnInitDialog member function
-
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:
class CFileDialogEx : public CFileDialog
{
DECLARE_DYNAMIC(CFileDialogEx)
public:
int m_nSubType;
CStatic m_Static;
CComboBox m_Combo;
CFileDialogEx(BOOL bOpenFileDialog,
LPCTSTR lpszDefExt = NULL,
LPCTSTR lpszFileName = NULL,
DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
LPCTSTR lpszFilter = NULL,
CWnd* pParentWnd = NULL);
protected:
virtual BOOL OnInitDialog();
afx_msg void OnDestroy();
DECLARE_MESSAGE_MAP()
};
Our first
tucancode.net is done by adding handler for WM_INITDIALOG:
BOOL CFileDialogEx::OnInitDialog()
{
CFileDialog::OnInitDialog();
char szText[120];
const UINT iExtraSize = 50;
CWnd *wndDlg = GetParent();
RECT Rect;
wndDlg->GetWindowRect(&Rect);
wndDlg->SetWindowPos(NULL, 0, 0,
Rect.right - Rect.left,
Rect.bottom - Rect.top + iExtraSize,
SWP_NOMOVE);
CWnd *wndComboCtrl = wndDlg->GetDlgItem(cmb1);
wndComboCtrl->GetWindowRect(&Rect);
wndDlg->ScreenToClient(&Rect);
Rect.top += 60;
Rect.bottom += 120;
Rect.left += 50;
m_Combo.Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWN
| CBS_SORT | WS_VSCROLL | WS_TABSTOP,
Rect, wndDlg, IDC_MYCOMBOBOX);
m_Combo.SetFont(wndComboCtrl->GetFont(), TRUE);
m_Combo.SetFocus();
CWnd *wndStaticCtrl = wndDlg->GetDlgItem(stc2);
wndStaticCtrl->GetWindowRect(&Rect);
wndDlg->ScreenToClient(&Rect);
Rect.top += 60;
Rect.bottom += 80;
Rect.right += 40;
m_Static.Create("Proba", WS_CHILD | WS_VISIBLE, Rect,
wndDlg, IDC_MYSTATIC);
m_Static.SetFont(wndComboCtrl->GetFont(), TRUE);
for (int i=0; i < 3; i++) {
sprintf(szText, "Subtype%d", i);
wndDlg->SendDlgItemMessage(IDC_MYCOMBOBOX, CB_INSERTSTRING,
(WPARAM) (-1), (LPARAM) (szText));
if (m_nSubType == i)
wndDlg->SetDlgItemText(IDC_MYCOMBOBOX, szText);
}
sprintf(szText, "File SubType Format");
wndDlg->SetDlgItemText(IDC_MYSTATIC, szText);
return TRUE;
}
Second tucancode.net
is done by adding message handler for WM_DESTROY message:
void CFileDialogEx::OnDestroy()
{
CFileDialog::OnDestroy();
char szText[40];
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()
{
CFileDialogEx filedialog(FALSE, NULL, GetTitle(),
OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY
| OFN_OVERWRITEPROMPT,
NULL);
filedialog.m_nSubType = m_nDocSubType;
filedialog.m_ofn.lpstrTitle =
"User added controls - Save File As";
if (filedialog.DoModal() == IDOK)
{
m_nDocSubType = filedialog.m_nSubType;
char szText[100];
sprintf(szText, "Document will be saved under "
"subtype %d", m_nDocSubType);
AfxMessageBox(szText);
}
}
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
|