Cum pot accesa un alt document deschis ?

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

Cum pot accesa un alt document deschis ?

Post by mesajflaviu » 19 Apr 2011, 14:35

Intr-o aplicatie MDI , am doua tipuri de document :

Code: Select all

CMy1Doc  // derivat din CDocument
CMy1View // derivat din CFormView
si

Code: Select all

CMy2Doc  // derivat din CDocument
CMy2View // derivat din CFormView
Deschid CMy1View ( cu CMy1Doc ) , si apoi deschid CMy2View ( cu CMy2Doc ) ... cum pot accesa CMy1Doc din CMy2View , pentru a putea apela :

Code: Select all

CMy1Doc::UpdateAllViews(NULL,(LPARAM)2,NULL);
?
Multumesc .



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

Re: Cum pot accesa un alt document deschis ?

Post by mesajflaviu » 19 Apr 2011, 14:44

Ideal ar fi sa nu aduc in fata CMy1View ca sa pot accesa CMy1Doc ...

Dragos Cojocari
Membru++
Membru++
Posts: 789
Joined: 11 Jul 2007, 14:11

Re: Cum pot accesa un alt document deschis ?

Post by Dragos Cojocari » 19 Apr 2011, 15:06

O metoda e sa iterezi DocTemplate din applicatie, apoi documentele ptr fiecare.

http://msdn.microsoft.com/en-us/magazine/cc188734.aspx

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

Re: Cum pot accesa un alt document deschis ?

Post by mesajflaviu » 19 Apr 2011, 15:43

Merge brici ! Multam !

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

Re: Cum pot accesa un alt document deschis ?

Post by Ovidiu Cucu » 19 Apr 2011, 15:44

Asa cum Dragos a zis deja, poti enumera template-urile din aplicatie cu GetFirstDocTemplatePosition si GetNextDocTemplate.
Apoi, pentru fiecare template, obtii documentul (documentele) cu GetFirstDocPosition si GetNextDoc.

Cel mai bine are fi sa pui o functe in clasa aplicatiei (derivata din CWinApp):

Code: Select all

class CMyMDIApp : public CWinApp
{
//...
public:
   void UpdateAllViews(CView* pSender, LPARAM lHint = 0L, CObject* pHint = NULL);
//...
};

Code: Select all

void CMyMDIApp::UpdateAllViews(CView* pSender, LPARAM lHint, CObject* pHint)
{
   POSITION posDocTemplate = GetFirstDocTemplatePosition();
   while(NULL != posDocTemplate)
   {
      CDocTemplate* pDocTemplate = GetNextDocTemplate(posDocTemplate);
      POSITION posDoc = pDocTemplate->GetFirstDocPosition();
      while(NULL != posDoc)
      {
         CDocument* pDoc = pDocTemplate->GetNextDoc(posDoc);
         pDoc->UpdateAllViews(pSender, lHint, pHint);
      }
   }
}
Acuma, sa zicem ca userul a schimbat ceva intr-un view si este nevoie de facut update la toate celelalte.
Facem cam asa:

Code: Select all

void CMyWhateverView::OnSomethingChanged() 
{
   CMyMDIApp* pApp = (CMyMDIApp*)AfxGetApp();
   CView* pSender = this; // exclude this view from updating (or NULL if not exclude).
   LPARAM lHint = 0L;     // change this if need a hint about what has been changed 
   CObject* pHint = NULL; // change this if need info about what has been changed

   pApp->UpdateAllViews(pSender, lHint, pHint);
}

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

Re: Cum pot accesa un alt document deschis ?

Post by mesajflaviu » 19 Apr 2011, 15:53

Excelenta rezolvarea ... eu am facut in modul urmator :

Code: Select all

		POSITION pos2,pos = theApp.GetFirstDocTemplatePosition();
		while(pos)
		{
			CDocTemplate* pDocTemplate = (CDocTemplate*)theApp.GetNextDocTemplate(pos);
			pos2 = pDocTemplate->GetFirstDocPosition();
			while(pos2)
			{
				CMy2Doc* pDoc = (CMy2Doc*)pDocTemplate->GetNextDoc(pos2);
				if(pDoc)pDoc->UpdateAllViews(NULL,(LPARAM)2,NULL);
			}
		}
dar am observat ceva : ori e deschis sau nu documentul , pDoc -ul e valid ... cum as putea stii daca e deschis sau nu acel document ?

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

Re: Cum pot accesa un alt document deschis ?

Post by Ovidiu Cucu » 19 Apr 2011, 16:07

mesajflaviu wrote:dar am observat ceva : ori e deschis sau nu documentul , pDoc -ul e valid ... cum as putea stii daca e deschis sau nu acel document ?
Mai exact, ce vrei sa spui cu "deschis"?

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

Re: Cum pot accesa un alt document deschis ?

Post by mesajflaviu » 19 Apr 2011, 16:12

Vreau sa zic ca si daca nu deschid CMy1View , acel pDoc ( de tip CMy1Doc ) e valid ...

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

Re: Cum pot accesa un alt document deschis ?

Post by Ovidiu Cucu » 19 Apr 2011, 16:32

NU-i adevarat!
Probabil te induce in eroare acel cast la CMy2Doc* aiurea, degeaba si in general destul de periculos.
Ia fa urmatorul test:
mesajflaviu wrote:

Code: Select all

//...
   while(pos2)
   {
      CMy2Doc* pDoc = (CMy2Doc*)pDocTemplate->GetNextDoc(pos2);
      if(pDoc) /////// pDoc->UpdateAllViews(NULL,(LPARAM)2,NULL);
      {
         if( ! pDoc->IsKindOf(RUNTIME_CLASS(CMy2Doc)))
         {
            AfxMessageBox(_T("Tzapoiul cat casoiul."));
         }
      }
//...
Apoi uita-te te rog cu mai multa atentie la functia scrisa de mine si fii mai atent cum faci casturile.

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

Re: Cum pot accesa un alt document deschis ?

Post by Ovidiu Cucu » 19 Apr 2011, 17:23

Un pic mai explicit.
Nu ai nevoie sa faci acele casturi (chiar in varianta safe cu dynamic_cast sau MFC-style, cu IsKindOf) nici macar daca trebuie sa faci o filtrare dupa documente.
Functia CView::OnUpdate are acel minunat membru lHint.
Ai putrea sa tii o "lista cu hinturi" sa zicem intr-un enum din clasa aplicatiei:

Code: Select all

class CMyMDIApp : public CWinApp
{
//...
public:
   enum e_UpdateHints
   {
      UH_DATABASE_CHANGED,
      UH_USERNAME_CHANGED,
      UH_SALARY_CHANGED,
      // and so on.
   };
Acuma, daca in CMy1View ma intereseaza ca s-a modificat baza de date sau userul fac asa:

Code: Select all

void CMy1View::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
{
   //...
   switch(lHint)
   {
   case CMDITestApp::UH_DATABASE_CHANGED:
      // do stuff.
      break;
   case CMDITestApp::UH_USERNAME_CHANGED:
      // do another stuff.
      break;

   // default:
      // ... do nothing
   }
}
Daca in CMy2View ma intereseaza numai ca s-a schimbat salariul:

Code: Select all

void CMy2View::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
{
   //...
   switch(lHint)
   {
   case CMDITestApp::UH_SALARY_CHANGED:
      // do stuff.
      break;

   // default:
      // ... do nothing
   }
}
S.a.m.d.

Mai departe, nici celalalt parametru, pHint, n-ar fi de neglijat.
S-ar putea la un moment dat sa te intrebi "Oare cum accesez date din CMy2Doc din CMy1View? sau viceversa?".
Ei bine, nu-i nevoie. Poti pune in pHint un pointer la o stuctura (derivata din CObject) cu tot ce-ti trebuie.

Si in fine, cum am zis in primul post, daca vrei sa updatezi view-uri pe toata aplicatia (indiferent de template) e bine ca functia aia s-o pui in clasa derivata din CWinApp sa s-o vezi de peste tot, sa eviti implementarea ei in N-shpe locuri si/sau sa te apuci de incrucisat headere de sa te doara capul. ;)

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

Re: Cum pot accesa un alt document deschis ?

Post by mesajflaviu » 20 Apr 2011, 15:40

Faina treaba ... un lucru e sigur : cu cat aprofundezi MFC-ul , cu atat il gasesti mai elegant !

Post Reply