Link to home
Start Free TrialLog in
Avatar of paulburns
paulburns

asked on

managing multiple doc templates

i have an SDI app with multiple doc templates. they are created in CWinApp::InitInstance like this...

CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
  IDR_MAINFRAME,
  RUNTIME_CLASS(CPEDoc),
  RUNTIME_CLASS(CMainFrame),   // main SDI frame window
  RUNTIME_CLASS(CPEView));
AddDocTemplate(pDocTemplate);

// note: the following template is _not_ registered with
//  the framework.
m_pImageTemplate = new CSingleDocTemplate(
  IDR_IMAGEFRAME,
  RUNTIME_CLASS(CPEDoc),
  RUNTIME_CLASS(CImageFrame),
  RUNTIME_CLASS(CImageView));

the second template is for displaying a popup mini frame window which shows a bitmap image rendering of the document.

there is a menu command to create and display this window which has code like this...

void CMainFrame::OnViewFormatImage()
{
  CPEApp* pApp = (CPEApp*) AfxGetApp();

  CPEDoc* pDoc = (CPEDoc*) GetActiveDocument();
  ASSERT(pDoc);

  CImageFrame* pFrame = (CImageFrame*) pApp->m_pImageTemplate->CreateNewFrame(pDoc, NULL);
  ASSERT(pFrame);
  ASSERT(pFrame->IsKindOf(RUNTIME_CLASS(CImageFrame)));

  pApp->m_pImageTemplate->InitialUpdateFrame(pFrame, pDoc);
}

this all works ok but here's the problem:
1. how do i determine if this window is currently displayed; all i seem to have access to is the doc template instance: m_pImageTemplate.
2. if it is displayed then how do i close it?
Avatar of trestan
trestan
Flag of Canada image

I have a suggestion that you define CImageFrame* pFrame; in your .h file and pFrame = NULL; in the .cpp file. When it is created, Check pFrame != NULL and you know it is there. Can you use pFrame->DestroyWindow() to close it? And set it to NULL again.
Avatar of naveenkohli
naveenkohli

1. Get the current active view and check its type.

CWnd *pMainWnd = AfxGetMainWnd ();

CView *pView = static_cast<CFrameWnd *>(pMainWnd)->GetActiveFrame ()->GetActiveView ();

if (pView->IsKindOf (RUNTIME_CLASS (CImageView)) {
TRACE (_T ("Image view already active\n"));
}

2.To close a view, post a WM_CLOSE message to its frame.

CImageFrame* pFrame;

pFrame->PostMessage (WM_CLOSE);
Avatar of paulburns

ASKER

sorry, that code dont work: the frame i want to close may not be the active one.

Then we can take the alternate approach..
1. Go through each and every view associated with the active document and see if that view is valid or not.

CWnd *pWnd = AfxGetMainWnd ();
ASSERT_KINDOF (CFrameWnd, pWnd);
CFrameWnd *pFrame = statoc_cast<CFrameWnd *> (pWnd);
CFrameWnd *pActiveFrame = pFrame->GetActiveFrame ();

CDocument *pDoc = pActiveFrame->GetActiveDocument ();

POSITION pos = pDoc->GetFirstViewPosition ();

while (pos != NULL) {
CView *pView = pDoc->GetNextView (pos);
if (pView != NULL && pView->IsKindOf (RUNTIME_CLASS (CImageView)) {
// the image view is active.
}
}
After getting if the image view is active or not, try using DestroyWindow on that view.

pImageView->DestroyWindow ();

Good Luck!
Trestan sort of suggested the approach I propose.  IMHO the doc/view architecture is an impediment to using MFC (MFC is an impediment to programming Windows, and Windows is just an impediment to using a PC, etc.)  In my doc/view applications, I create global pointers to each view so that I can access them anywhere and anytime I need to without worrying about how to find them (which is a bigger problem than writing the code usually).  

In this case, I would create a CImageFrame* as a global variable.  Initialize it to NULL at program startup, and then save the view pointer when the view is initially created.  When you need to find the view, you know where it is and can do things like test whether it is open because it is global and always available.  You can call any member function in the view using the pointer.  When you close/destroy the view, set the pointer to NULL again so you know it is not there.  

Forget about messing around with the doc/view rigamarole and live happily ever after.
i don't know how good is the idea of using global variables. that points out that there is something wrong with the design of application. its alsways a bad programming practice to rely on global variables. it totally defeats the purpose of OOD. especially the objects which directly affect ur view. and how will you manage the access from different threads.

may be its my way of thinking...

good luck!!

I chose to use the doc-view architecture in this case because it seemed logical: i just needed to display a different view of the document. Also MFC does have some good features here (IMHO): view creation/destruction is managed automatically and there is a standard doc-view communication method - UpdateAllViews, OnUpdate, etc.

The only thing unusual in my case is that i'm using a different frame as well as a different view.

Trestan's idea works and is the simplest so i'll stick with that. But this doc-view stuff does seem a bit odd: the doc template is used to create the frame/doc/view connection but then doesn't seem to be used at all after that?!?

Anyway, thanks everyone for all the help. Trestan, points are yours.

ASKER CERTIFIED SOLUTION
Avatar of trestan
trestan
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial