11
Aug
2009

In unele aplicatii este necesara modificarea dialogului comun care permine selectia fisierelor, pentru a contine controale suplimentare. De exemplu in cazul imaginilor se poate dori o previzualizare. In acest articol voi explica cum se poate extinde acest dialog.

Exista cateva lucruri ce trebuie facute pentru a extinde un dialog. In primul rand trebuie creat un template de dialog. Acest template trebuie sa aiba cateva stiluri setate (se pot seta din editorul de resurse):

  • WS_CHILD, necesar pentru ca dialogul este un copil al celui parinte
  • WS_CLIPSIBLINGS, necesar pentru ca dialogul copil sa nu se deseneze peste cel parinte
  • DS_3DLOOK, folosit pentru ca si parintele are acest stil, si cele doua dialoguri ar trebui sa arate la fel (pentru consistenta)
  • DS_CONTROL, permite navigarea cu TAB sau sageti printre controalele de pe dialogul copil

Atunci cand se foloseste template-ul trebuie setate cateva lucruri in structura OPENFILENAME:

  • daca template-ul este o resursa intr-o aplicatie sau un DLL:
    • Flags trebuie sa contina OFN_ENABLETEMPLATE
    • hInstance trebuie sa indice spre modulul care contine resursa
    • lpTemplateName trebuie sa contina numele template-ului.
  • daca template-ul este deja in memorie, atunci:
    • Flags trebuie sa contina OFN_ENABLETEMPLATEHANDLE
    • hInstance trebuie sa indice spre obiectul din memorie care contine (reprezinta) template-ul

Exemplul de mai jos arata cum se poate instantia un dialog de fisiere extins dintr-un template cu numele "DIALOG_PREVIEW":

CFileDialog fileDialog(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("All files (*.*)|*.*||"));

fileDialog.m_ofn.Flags |= OFN_ENABLETEMPLATE;
fileDialog.m_ofn.hInstance = AfxGetInstanceHandle();
fileDialog.m_ofn.lpTemplateName = _T("DIALOG_PREVIEW");

fileDialog.DoModal();

Dialogul original este redimensionat, astfel incat noile controale sa aiba loc. Mai jos este exemplificat modul in care se face acest lucru:

  • In mod implicit, toate controalele de pe template sunt pozitionate sub controalele dialogului original. In imaginile de mai jos se pot vedea template-ul si dialogul extinst.

  • Daca template-ul contine un control static cu ID-ul stc32 (definit in DLG.H), atunci toate controalele vor fi repozitionate in functie de acesta (considerat o referinta pentru controalele originale).

Pentru a pozitiona controalele la dreapta dialogului original, template-ul ar trebui sa arate ca mai jos, cu controlul stc32 la stanga tuturor controalelor.

Dialogul de fisiere extins va arata astfel:

Template pentru preview 4
Vezi imaginea la dimenisunea normala

De remarcat ca in imaginile de mai sus controlul stc32 are o margine pentru al face remarcat in template, iar pe de alta parte pentru a pune in evidenta controalele dialogului original intre cele ale dialogului final.

Pentru a da o folosinta acestor controale, ar trebui creata o clasa derivata din CFileDialog. Aceasta va contine handlere pentru notificarile legate de controale si toata logica folosirii acestor controale aditionale.

class CPreviewFileDialog : public CFileDialog
{
	DECLARE_DYNAMIC(CPreviewFileDialog)

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

protected:
	DECLARE_MESSAGE_MAP()
};
IMPLEMENT_DYNAMIC(CPreviewFileDialog, CFileDialog)

CPreviewFileDialog::CPreviewFileDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
		DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) :
		CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd)
{
	m_ofn.Flags |= OFN_ENABLETEMPLATE;
	m_ofn.hInstance = AfxGetInstanceHandle();
	m_ofn.lpTemplateName = _T("DIALOG_PREVIEW");
}

CPreviewFileDialog::~CPreviewFileDialog()
{
}

BEGIN_MESSAGE_MAP(CPreviewFileDialog, CFileDialog)
END_MESSAGE_MAP()

Folosing aceasta clasa, exemplul initial de instantiere a unui dialog modificat s-ar transforma in:

CPreviewFileDialog fileDialog(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("All files (*.*)|*.*||"));

fileDialog.DoModal();

Implementarea functionalitatii de previzualizare este dincolo de scopul acestui articol (si se poate face in diverse moduri). Ce trebuie retinut este modul in care se construieste template-ul pentru controalele aditionale si cum se instantiaza un dialog de fisiere extins.