Cum elimin un tip de document din CFileDialog ?

Intrebari legate de programarea cu biblioteci precum MFC, ATL, WTL si GDI+.
Post Reply
mesajflaviu
Membru++
Membru++
Posts: 686
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Cum elimin un tip de document din CFileDialog ?

Post by mesajflaviu » 03 Sep 2011, 21:49

Acest post este de fapt continuarea celui de aici. La acest proiect de test am mai adaugat un tip de document (cu clasa view bazata pe CHtmlView) :

Code: Select all

	CMultiDocTemplate* pDocTemplate;
	pDocTemplate = new CMultiDocTemplate(
		IDR_TESTTYPE,
		RUNTIME_CLASS(CTestDoc),
		RUNTIME_CLASS(CChildFrame), // custom MDI child frame
		RUNTIME_CLASS(CTestView));
	AddDocTemplate(pDocTemplate);

	pDocTemplate = new CMultiDocTemplate(
		IDR_TESTTYPE,
		RUNTIME_CLASS(CTest2Doc),
		RUNTIME_CLASS(CChildFrame), // custom MDI child frame
		RUNTIME_CLASS(CTest2View));
	AddDocTemplate(pDocTemplate);
dar pentru ca am doua Document Template-uri, la File/Open, in fereastra CFileDialog am acel filtru .xyz de doua ori ... nu ca ar incurca dar este putin inestetic.
Intrebarea mea este, unde anume in framework trebuie sa lucru ca sa nu mai am acel filtru de doua ori ?
Multumesc.
P.S. Atasaz si proiectul de test.
Attachments
Test.zip
(87.27 KiB) Downloaded 163 times



User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Cum elimin un tip de document din CFileDialog ?

Post by Silviu Ardelean » 04 Sep 2011, 02:30

Sterge din CTestApp::InitInstance() a doua creare de obiect CMultiDocTemplate() (unul din cele doua obiecte enumerate de tine).
Ai mai multe obiecte documents template-uri doar daca vrei sa suporti mai multe tipuri de fisiere in aplicatie.

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Cum elimin un tip de document din CFileDialog ?

Post by Ovidiu Cucu » 04 Sep 2011, 10:35

Silviu Ardelean wrote:Ai mai multe obiecte documents template-uri doar daca vrei sa suporti mai multe tipuri de fisiere in aplicatie.
Nu, Silviu, nu neaparat.
MDI NU se refera neaparat la mai multe tipuri de fisiere.
Un exemplu practic simplu: am o aplicatie care lucreaza cu un singur tip de fisier sa zicem HTML pe care vreau sa-l afisez atat intr-un browser (HTML view) cat si ca plain text (edit view). Nu vreau/nu-mi place (sau asa spun cerintele) sa folosesc un splitter sau sa comut view-urile cu un tab ci mai bine afisez fiecare view intr-un frame MDI-child separat.

Daca ne uitam la constructorul lui CMultiDocTemplate observam:
  • Un ID de resurse comun pentru un meniu, icon, tabela de acceleratori si un string.
  • O clasa document care tine datele si face serializarea unui fisier de un tip dat.
  • O clasa (MDI child) frame in care va sta bine-mersi un view.
  • O clasa view care afiseaza continutul documentului.
Intr-o aplicatie MDI, pot avea orice combinatii jongland cu cele patru de mai sus, printre care un singur tip de document cu mai multe tipuri de view-uri, asa cum vrea Flaviu.
In implementarea de baza, framework-ul MFC e destul de "saracut" insa iti da posibilitatea s-o imbunatatesti dupa cum este necesar intr-o aplicatie data. De aceea MFC-ul are o multime de functii virtuale pe care poti sa le suprascrii punand in ele ce vrea muschii tai.

By default, la "Open" si "Save As", framework-ul isi face datoria in modul cel mai simplu adaugand, daca gaseste, cate un filtru pentru fiecare document template (il ia din acel string din resurse al carui ID l-am pasat in constructorul lui CMultiDocTemplate).
Ar fi mai multe metode de a rezolva problema data de Flaviu.

Una e sa pasam alt ID de resurse pentru template-urile care nu necesita filtru iar in resursa string corespunzatoare nu punem filtru.
De exemplu IDR_TESTTYPE2:
\nTest\nTest\n\n\nTest.Document\nTest Document
Dupa cum vezi, a disparut filtrul ("Test Files (*.xyz)" si ".xyz") care era in IDR_TESTTYPE.
Pare cea mai simpla metoda insa nu este intotdeaua si cea mai potrivita.
De ce? Pentru ca ID-ul acesta este comun pentru mai multe resurse si cel mai probabil vor trebui "dublate" si celelalte (menu, icon, etc.).

Alta metoda este sa folosim in aplicatie propria clasa derivata din CDocManager (sa-i zicem CAppDocManager), in care suprascriem CDocManager::DoPromptFileName si in care aratam "Open" sau "Save As" dupa cum vrem si cu ce filtru ne convine.
Mai ramane de facut asta in clasa aplicatiei, inainte de orice apel la AddDocTemplate:

Code: Select all

BOOL CMyApp::InitInstance()
{
// ...
   // AddDocTemplate(pDocTemplate); // <-- replace this
   if (m_pDocManager == NULL)
   {
      m_pDocManager = new CAppDocManager;
   }
   m_pDocManager->AddDocTemplate(pDocTemplate);
// ...
De la caz a caz, poti opta pentru o solutie sau alta.
  1. Prima e mai aproape de cum a fost gandit framework-ul MFC insa necesita un pic de bibileala la resurse. N-ar fi asa mare dezavantaj, tinand cont de faptul ca uneori e bine sa ai de exempu un menu specific pentru un view (template) specific.
  2. A doua e mai flexibila, in sensul ca poti face usor ce vrei tu cu dialogurile "Open" si "Save As". De exemplu, poti sa bagi filtre multiple pentru un singur document template (ex: "Bitmap files" + "JPEG Files" + ... + "All supported graphic files").
  3. In fine, in anumite cazuri, nu te impiedica nimeni sa le folosesti pe amandoua.

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Cum elimin un tip de document din CFileDialog ?

Post by Silviu Ardelean » 04 Sep 2011, 12:16

Ovidiu Cucu wrote:
Silviu Ardelean wrote:Ai mai multe obiecte documents template-uri doar daca vrei sa suporti mai multe tipuri de fisiere in aplicatie.
MDI NU se refera neaparat la mai multe (tipuri de) fisiere.
Nu am spus asta. Putem avea foarte bine si aplicatii SDI care suporta mai multe tipuri de fisiere.
Ovidiu Cucu wrote: Intr-o aplicatie MDI, pot avea orice combinatii jongland cu cele patru de mai sus, printre care un singur tip de document cu mai multe tipuri de view-uri (edit, form, list etc)
Desigur.

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Cum elimin un tip de document din CFileDialog ?

Post by Ovidiu Cucu » 04 Sep 2011, 12:55

Silviu Ardelean wrote:
Ovidiu Cucu wrote:
Silviu Ardelean wrote:Ai mai multe obiecte documents template-uri doar daca vrei sa suporti mai multe tipuri de fisiere in aplicatie.
MDI NU se refera neaparat la mai multe (tipuri de) fisiere.
Nu am spus asta. Putem avea foarte bine si aplicatii SDI care suporta mai multe tipuri de fisiere.
[ off-topic ]
Uite ce e, Silviu! Nu-mi place cand cineva "o intoarce ca la Ploiesti".
Am mai mult respect pentru un "OK, sorry, am gresit (eu sau tastatura)" atunci cand cineva scoate un "porumbel". I se poate intampla oricui, inclusiv mie.
Nu te-am citat ca sa arat cu degetul sau ca sa pornesc un flame.
Incerc sa lamuresc o problema in care se fac multe confuzii si anume "ce este si cu ce se mananca multi-document template".

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Cum elimin un tip de document din CFileDialog ?

Post by Silviu Ardelean » 04 Sep 2011, 13:05

Problema este dublarea filtrului de fisiere. Iar ptr. asta continui sa sustin ca o problema este cel de-al doilea obiect doc-template adaugat.
La nivel de resurse, in proiectul de test, nu exista vreo dublura.
In situatia data (un singur tip de fisiere suportat), nu e neaparata nevoie sa ne complicam cu CMultiDocTemplate/CSimpleDocTemplate.

PS. Ovidiu, e departe de mine gandul unui flame, dar cand spui "Nu, Silviu, nu neaparat" referitor la ce am citat ulterior cred ca te refereai la persoana mea iar mie astfel de lucruri imi sunt clare - deci nu am ce sa intorc. M-am jucat si eu cu CMultiDocTemplate. Nimic nu ne opreste sa folosim CSimpleDocTemplate in SDI applications.

mesajflaviu
Membru++
Membru++
Posts: 686
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum elimin un tip de document din CFileDialog ?

Post by mesajflaviu » 07 Sep 2011, 19:54

Am rezolvat problema in felul urmator : am derivat o clasa CDocManagerExt din CDocManager, in care am suprascris DoPromptFileName(...), in CMyApp - OnInitInstance, inainte de orice AddDocTemplate am creat

Code: Select all

m_pDocManager = new CDocManagerExt;
iar in metoda DoPromptFileName :

Code: Select all

BOOL CDocManagerExt::DoPromptFileName(CString& sFileName, UINT nIDSTitle,DWORD dwFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate)
{
	CFileDialog DlgFile(bOpenFileDialog);

	CString sTitle;
	VERIFY(sTitle.LoadString(nIDSTitle));

	DlgFile.m_ofn.Flags |= dwFlags;

	CString sFilter;
	CString sDefault;

	if(pTemplate != NULL)
	{
		ASSERT_VALID(pTemplate);
		AppendFilterSuffix(sFilter, DlgFile.m_ofn, pTemplate, &sDefault);
	}
	else
	{
		// do for all doc template
		BOOL bFirst = TRUE;
		POSITION pos = m_templateList.GetHeadPosition();
		while(pos)
		{
			CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
			AppendFilterSuffix(sFilter, DlgFile.m_ofn, pTemplate, bFirst ? &sDefault : NULL);
			bFirst = FALSE;
			break;	//	we want only first kind of document
		}
	}

	// append the "*.*" all files filter
	CString sAllFilter;
	VERIFY(sAllFilter.LoadString(AFX_IDS_ALLFILTER));
	sFilter += sAllFilter;
	sFilter += (TCHAR)'\0';   // next string please
	sFilter += _T("*.*");
	sFilter += (TCHAR)'\0';   // last string
	DlgFile.m_ofn.nMaxCustFilter++;

	DlgFile.m_ofn.lpstrFilter = sFilter;
	DlgFile.m_ofn.lpstrTitle = sTitle;
	DlgFile.m_ofn.lpstrFile = sFileName.GetBuffer(_MAX_PATH);

	int nResult = DlgFile.DoModal();
	sFileName.ReleaseBuffer();

	return nResult == IDOK;
}
si merge brici. Dar proiectul de test are o problema mare : cand se deschide al doilea tip de document, din meniul File/ New Html, si apoi se inchide aplicatia, trosneste un access violation de toata frumusetea, dar numai cand este compilat in VC6 (cu sa fara SP) in Windows XP. Ciudat ...

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Cum elimin un tip de document din CFileDialog ?

Post by Ovidiu Cucu » 08 Sep 2011, 07:53

mesajflaviu wrote:...cand se deschide al doilea tip de document, din meniul File/ New Html, si apoi se inchide aplicatia, trosneste un access violation de toata frumusetea, ...
Ok, si ce se spune in handlerul lui "File/ New Html"?
Sau mai bine, ataseaza te rog un demo.

mesajflaviu
Membru++
Membru++
Posts: 686
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum elimin un tip de document din CFileDialog ?

Post by mesajflaviu » 08 Sep 2011, 08:30

De proiectul de test de la inceputul postului vorbesc, daca deschid si un document de tip CTest2Doc ( cu view-ul de tip CHtmlView ), la inchiderea aplicatiei am urmatorul
mesaj.
Last edited by mesajflaviu on 08 Sep 2011, 13:14, edited 1 time in total.

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Cum elimin un tip de document din CFileDialog ?

Post by Silviu Ardelean » 08 Sep 2011, 09:39

Ar fi util sa utilizezi fereastra de Call Stack iar tu sa te joci cu ea pentru a vedea unde o ia in balari.

mesajflaviu
Membru++
Membru++
Posts: 686
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum elimin un tip de document din CFileDialog ?

Post by mesajflaviu » 08 Sep 2011, 11:08

Pai nu mai apuc, ca dupa ce dau OK la "...Acces Violation ..." ma duce aici

mesajflaviu
Membru++
Membru++
Posts: 686
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum elimin un tip de document din CFileDialog ?

Post by mesajflaviu » 08 Sep 2011, 12:34

Sau sa ma duc pas cu pas la iesirea din aplicatie, sa vad unde e problema ? Incerc si asta.

mesajflaviu
Membru++
Membru++
Posts: 686
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum elimin un tip de document din CFileDialog ?

Post by mesajflaviu » 08 Sep 2011, 13:08

Am ajuns aici :

Code: Select all

AfxWndProcBase(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	AFX_MANAGE_STATE(_afxBaseModuleState.GetData());
	return AfxWndProc(hWnd, nMsg, wParam, lParam);  // <- Stop
}
aici se opreste codul, iar dupa inca cateva intructiuni in asamblare, crapa dupa modelul ce l-am fotografiat mai sus.

mesajflaviu
Membru++
Membru++
Posts: 686
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum elimin un tip de document din CFileDialog ?

Post by mesajflaviu » 09 Sep 2011, 21:16

Am gasit problema, daca pot spune ca a fost vreuna, fiindca pe 2 statii cu XP avea acea comportare ... era problema in CTest2View::Navigate2(...) ... nu gasesc nici o explicatie pentru asta. Oricum, vreau sa va multumesc pentru rabdare. Numai bine !

Post Reply