CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7

Threaded View

  1. #1
    Join Date
    May 2002
    Posts
    1,798

    SDI with multiple views - an old problem revisited

    Some time ago I had developed an SDI application that allowed switching to different views, one a CView and the other a CRichEditView. I did this with the help of an old text by Brain and Lovette, 'Developing Professional Applications...Prentice Hall, 1996 ISBN 0-13-616343-2 (see pp 398, Handling Multiple Views on One Document. Regretably, I have lost the code for this application and no longer can remember the tricks involved in accomplishing this. I have gotten so far as to get an application that does most of what I want, but cannot get the views to switch during runtime.

    One can proceed as follows:

    1 - Use the Wizard to create an SDI app
    2 - Add Class (s) CView1, CView2, ... using desired base classes
    3 - Include the header files for each of the new views to the application _App.cpp file
    4 - In the _App::InitInstance() function, redesign the document templates so that
    they look something like this, noting that each view has it's own unique CSingleDocTemplate
    class pointer (pDocTemplate1, pDocTemplate2, ...), unique menu ID (IDR_TYPE_STDVIEW,
    IDR_TYPE_RICHVIEW, ...), while in this case the views are sharing the same document class
    (CVistasDoc), and Main Frame class (CMainFrame), each view template has it's unique
    RUNTIME_CLASS designation (CView1, CView2, ...).

    Code:
    	CSingleDocTemplate* pDocTemplate1;
    	pDocTemplate1 = new CSingleDocTemplate(
    		IDR_TYPE_STDVIEW,
    		RUNTIME_CLASS(CVistasDoc),
    		RUNTIME_CLASS(CMainFrame),       // main SDI frame window
    		RUNTIME_CLASS(CView1));
    	if (!pDocTemplate1)
    		return FALSE;
    	AddDocTemplate(pDocTemplate1);
    
    
    	CSingleDocTemplate* pDocTemplate2;
    	pDocTemplate2 = new CSingleDocTemplate(
    		IDR_TYPE_RICHVIEW,
    		RUNTIME_CLASS(CVistasDoc),
    		RUNTIME_CLASS(CMainFrame),       // main SDI frame window
    		RUNTIME_CLASS(CView2));
    	if (!pDocTemplate2)
    		return FALSE;
    	AddDocTemplate(pDocTemplate2);
    5 - In the String Table, copy the IDR_MAINFRAME entry and paste it again into the String Table to
    produce IDR_MAINFRAME1, IDR_MAINFRAME2, ..., then rename these new entries according to what
    you named the unique doc template IDs (IDR_TYPE_STDVIEW, IDR_TYPE_RICHVIEW, ...)

    6 - In the Menu resources, copy IDR_MAINFRAME and paste it again into the Menus to produce
    IDR_MAINFRAME1, IDR_MAINFRAME2, ..., then rename these menus to correspond to the new
    doc templates (IDR_TYPE_STDVIEW, IDR_TYPE_RICHVIEW, ...) Note that these menus do not have
    to be identical and can be edited at a later time as desired.

    7 - To each of the new view menus, add items to select the other views (you could omit the item
    for it's own view). Then add an event handler for each of the menu view items to the _App,
    as well as an update command handler.

    8 - You may delete permanently the original IDR_MAINFRAME menu and String Table entries and
    the associated original _View.h and _View.cpp files without causing any problems.


    This works quite nicely. Now the trick is to be able to switch views during runtime. Some clue might be had by exmining the beautiful interface presented in an article by Yuantu Huang:

    Simple to Use, Yet Powerful Graphics Classes by By Yuantu Huang - July 23, 2000 http://www.codeguru.com/article.php/c2231

    Using this approach (bearing in mind that Huang's interface is MDI and not SDI), I tried using this on my SDI app Vistas with two views cleverly named View1 and View2, a CView derived view and a CRichEditView derived view respectively. Each view has the other view as a choice in it's menu. The menu handlers are handled in the Vistas.cpp (the App file) which looks like this:
    Code:
    BEGIN_MESSAGE_MAP(CVistasApp, CWinApp)
    	// ..
    	ON_COMMAND(ID_VIEW1, &CVistasApp::OnView1)
    	ON_COMMAND(ID_VIEW2, &CVistasApp::OnView2)
    	ON_UPDATE_COMMAND_UI(ID_VIEW1, &CVistasApp::OnUpdateView1)
    	ON_UPDATE_COMMAND_UI(ID_VIEW2, &CVistasApp::OnUpdateView2)
    END_MESSAGE_MAP()
    
    //..
    
    void CVistasApp::OnView2()
    {
    	POSITION curTemplatePos = GetFirstDocTemplatePosition();
    
    	while(curTemplatePos != NULL)
    	{
    		CDocTemplate* curTemplate = 
    			GetNextDocTemplate(curTemplatePos);
    		CString str;
    		curTemplate->GetDocString(str, CDocTemplate::docName);
    		if(str == _T("Vistas"))
    		{
    			curTemplate->OpenDocumentFile(NULL);
    			return;
    		}
    	}
    	AfxMessageBox("Can not create the View2 frame window!");
    }
    which shows the routine that is supposed to bring up View2 from the menu selection in View1.

    It all compiles and runs but always with the little dialog box giving you a choice of selecting one or the other view. Once you select a view, the menu selection of the other view fails with the warning:
    Cannot create the ViewN frame window!
    Searching Codeguru for 'SDI Mulitiple Views' elicits 231 hits, most of which seem not to understand the question at hand and tend to be quite critical of the questioner. It is said elsewhere that there is an old Microsoft example called 'CheckBook'. Try Googling that. Nor can I find it in the current batch of MSDN samples (though it could be hidden in there somewhere).

    Since I beleive that I have solved a portion of the problem, what remains is
    1 - how to get rid of the initial choice dialog
    2 - how to call the various views from menu selections

    I should mention that my String Table entries for the two views are identical (unlike those of Huang). I am not sure whether or not that is the problem, but the template doc strings in my app are the same, namely 'Vistas'.


    Code:
    IDR_TYPE_STDVIEW | Vistas\n\nVistas\nVistas Files (*.txt)\n.txt\nVistas.Document\nVistas.Document
    IDR_TYPE_RICHVIEW | Vistas\n\nVistas\nVistas Files (*.txt)\n.txt\nVistas.Document\nVistas.Document
    Oh yes, anyone interested in this problem should consult the article:
    Multiple Views Using SDI by Richard Stringer, December 1998
    http://www.codeguru.com/cpp/w-d/doc_...icle.php/c3341

    I and others cannot get Stringer's code to work, but the discussion is interesting and I particularly like the statement Stringer makes which I have included to counter Victor's comment about 'reinventing the wheel when MDI does just that' ---

    There are many advantages to using a CView derived class over a dialog based application. Many times however there is more information than screen space or the program just needs logical seperation of elements. MDI ( Multiple Document Interface) is the standard method of achiving this but many designers do not care for it. It tends to get messy quickly. Most of the time what is needed is a generalized easy way to have a SDI ( Single Document Interface) framework and the ability to switch the active view when needed. This article describes such a method.

    I have appended my sample app in the hope that someone will find it interesting and useful enough to post a solution to the problem.

    Attached Files Attached Files
    Last edited by Mike Pliam; November 5th, 2010 at 06:15 PM.
    mpliam

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured