Solved

Creating Multiple Views of different types in SDI

Posted on 2000-02-24
10
464 Views
Last Modified: 2013-11-20
I have an SDI application. I am trying to have multiple views of different types (Classes) for the same document. I do not want to use CSplitterWnd since it forces me to have the multiple views within one main window. I would like to have the multiple views in different windows, as if they were child windows of the main windows so I would be able to make them overlap min.mximize, etc.
Please advise.
Thank you.
0
Comment
Question by:Zainal062797
10 Comments
 
LVL 10

Accepted Solution

by:
RONSLOW earned 200 total points
ID: 2556214
Sounds like you want a hybrid SDI/MDI app.

There are examples of these at www.godeguru.com

I'll give you the addresses shortly
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2556254
go to

http://www.codeguru.com/doc_view/index.shtml

there are a number of articles there under the "View management" heading, including:

MultiSingle (MSDI) Document interface - Lanz Jean-Claude (1998/08/06)
MultiSingle (MSDI) Document interface with DAO doc - Lanz Jean-Claude (1998/08/06)
Multiple Views Using SDI - Richard Stringer (1998/12/02)
SDI Interface with Multi-Views and Multi-Splitters - Jean-Claude Lanz (1999/02/14)
Switching to other view in a doc-view application - Jorge Lodos (1999/03/02)
Multiple frame windows in SDI application - Ole Lennert (1999/04/03)

Good hunting !!

0
 
LVL 3

Expert Comment

by:V_Bapat
ID: 2557839
Do you want functionality like Outlook Express where you double click on the mail message and a new window open with the message?

If yes, then read on.

1. You have to create and maintain a pointer list of the windows. You should add FrameWnd pointer to the list when ever you open a new window and remove it is closed.
2. To create a new window, call CreateNewFrame(...).

These are two basic functionality you have to implement. Rest is not much. Feel free to ask if you have more queries.

All the best.

Vicky
0
 
LVL 3

Expert Comment

by:V_Bapat
ID: 2557872
Take a look at this article from Microsoft Knowledge Base.
http://support.microsoft.com/support/kb/articles/Q100/9/93.ASP

To get this article by mail, send a blank mail to mshelp@microsoft.com with Q100993 in the subject line.

Vicky
0
 

Author Comment

by:Zainal062797
ID: 2558911
Thank you for your advice V_Bapat. However, I am using SDI, and when I try to create the second view, the program crashes. It seems like your solution works only for MDI. Please let me know if there is a way around this.

Thank you.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 10

Expert Comment

by:RONSLOW
ID: 2560335
Did you check out the examples at codeguru? They all give SDI with multiple views.
0
 
LVL 4

Expert Comment

by:pagladasu
ID: 2562144
You can have multiple views in a SDI application. Create the other
views separately by inserting a new class. Make sure that this class is
derived from the appropriate view class. Assume that this view is called
CMyNewView.

Add the following protected instance variable and member function
in the CMainFrame class.

protected:
enum show {MYVIEW=1, DEFVIEW=2};
void SwitchView(show nView);

Add the following menu option : MyView  (mapped to OnMyView) and
DefaultView (mapped to OnDefView)

Write the following code for OnMyView
void CMainFrame::OnMyView()
{
// TODO: Add your command handler code here
SwitchView(MYVIEW);
}

Similarly this code goes for OnDefView
void CMainFrame::OnDefView()
{
// TODO: Add your command handler code here
SwitchView(DEFVIEW);
}

Here is the code for SwitchView
void CMainFrame::SwitchView(show nView){
CView * poldview=GetActiveView();
CView * pnewview=(CView *)GetDlgItem(nView);
if(pnewview==NULL){
switch(nView){
case MYVIEW:
pnewview=(CView *)new CMyNewView;
break;
case DEFVIEW:
pnewview=(CView *)new CMyAppView;
break;
}
CCreateContext context;
context.m_pCurrentDoc=poldview->GetDocument();
pnewview->Create(NULL,NULL,0L,CFrameWnd::rectDefault,this,nView,&context);
pnewview->OnInitialUpdate();
}
SetActiveView(pnewview);
pnewview->ShowWindow(SW_SHOW);
poldview->ShowWindow(SW_HIDE);
poldview->SetDlgCtrlID(poldview->GetRuntimeClass()==
RUNTIME_CLASS(CMyAppView)?DEFVIEW:MYVIEW);
pnewview->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
RecalcLayout();
}

Also add these handlers:
void CMainFrame::OnUpdateViewDefView(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(!GetActiveView()->IsKindOf(RUNTIME_CLASS(CMyAppView)));
}

void CMainFrame::OnUpdateViewMyNewView(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->Enable(!GetActiveView()->IsKindOf(RUNTIME_CLASS(CMyNewView)));
}

Hope this helps
pagladasu

0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2562348
The above has one view window and simply changes the type of view displayed in that window.  This is not what is wanted (from what I understand of the question).

I have a more generalised method for this in my apps ... you only need to change (or add) a line for each view type to have as many views as you want.

My example works within a splitter, which is not in the specs of this app, but thought someone may find it useful.  It allows you to change the type of view in each splitter pane.

One day I'll add a lookup table from ID to runtime class to make it truly extensible and stick it in my utility library .. but here it is (a bit different from the above - mainly because of splitter support):

void CMainFrame::OnViewSelect(UINT id) {
  // work out the type of view required
  // from the ID given
  CRuntimeClass* pViewClass = NULL;
  switch (id) {
  // add to and/or change these lines
  // for additional classes
  case ID_VIEW_1: pViewClass = RUNTIME_CLASS(CView1); break;
  case ID_VIEW_2: pViewClass = RUNTIME_CLASS(CView2); break;
  }
  // don't know what class to create
  if (! pViewClass) return;
  // Get pointer to CDocument object so
  // that it can be used in the
  // creation process of the new view
  CDocument* pDoc = GetActiveDocument();
  if (! pDoc) return;
  // if no old view, then cannot change
  CView* pOldView = GetActiveView();
  if (! pOldView) return;
  // get pointer to splitter (parent)
  // must be
  CSplitterWnd* pSplitter = static_cast<CSplitterWnd*>(pOldView->GetParent());
  if (! pSplitter || ! pSplitter->IsKindOf(RUNTIME_CLASS(CSplitterWnd))) return;
  // find which pane
  int row,col;
  if (pSplitter->IsChildPane(pOldView,&row,&col)) {
    int w,h,minw,minh;
    pSplitter->GetColumnInfo(col,w,minw);
    pSplitter->GetRowInfo(row,h,minh);
    // set flag so that document will
    // not be deleted when view is
    // destroyed
    {
      BOOL bAutoDelete = pDoc->m_bAutoDelete;
      pDoc->m_bAutoDelete=false;    
      pOldView->DestroyWindow();
      pDoc->m_bAutoDelete=bAutoDelete;
    }
    // Create new view
    CCreateContext context;
    context.m_pNewViewClass=pViewClass;
    context.m_pCurrentDoc=pDoc;
    context.m_pNewDocTemplate=NULL;
    context.m_pLastView=NULL;
    context.m_pCurrentFrame=NULL;
    if (! pSplitter->CreateView(row,col,pViewClass,CSize(w,h),&context)) {
      ::AfxMessageBox("Could not create view");
    } else {
      CView* pNewView = static_cast<CView*>(pSplitter->GetPane(row,col));
      SetActiveView(pNewView);
      pNewView->SendMessage(WM_INITIALUPDATE,0,0);
      pSplitter->SetColumnInfo(col,w,minw);
      pSplitter->SetRowInfo(row,h,minh);
      pSplitter->RecalcLayout();
      pNewView->UpdateWindow();
    }
  }
}
0
 
LVL 3

Expert Comment

by:V_Bapat
ID: 2564229
Zainal:
>> It seems like your solution works only for MDI.

It is for SDI. What I missed out in my last post is that you have to create a DocTemplate.
I am using this method in my Project. This is a snippet from my CWinApp derived class.

      // Register the application's document templates.  Document templates
      //  serve as the connection between documents, frame windows and views.

// DocTemplate created by AppWizard

      CSingleDocTemplate* pDocTemplate;
      pDocTemplate = new CSingleDocTemplate(
            IDR_MAINFRAME,
            RUNTIME_CLASS(CNetpowerDoc),
            RUNTIME_CLASS(CNetpowerFrameWnd),       // main SDI frame window
            RUNTIME_CLASS(CNetpowerView));
      AddDocTemplate(pDocTemplate);

      {
            // BLOCK: doc template registration
            // Register the document template.  Document templates serve
            // as the connection between documents, frame windows and views.
            // Attach this form to another document or frame window by changing
            // the document or frame class in the constructor below.
            m_pPolicyEditorDocTemplate = new CSingleDocTemplate(
                  IDR_CHILDFRAME,
                  RUNTIME_CLASS(CPolicyEditorDoc),              // Document class
                  RUNTIME_CLASS(CPolicyEditorFrm),          // Child frame class
                  RUNTIME_CLASS(CPolicyEditorView));       // View class
            AddDocTemplate(m_pPolicyEditorDocTemplate);
      }

You have to create document, view and frame window classes derived from CDocument, CView(or what your requirement is) and CFrameWnd respectively.

It is a bit complicated and to understand it properly, you have to understand what and how CDocManager(undocumented class) class works.


Vicky
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2566985
Did you check out the examples at codeguru?

They all give SDI with multiple views.

Please check them out and let me know what you think.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Process filename extension 3 156
fizzArray  challenge 1 47
noX challenge 17 76
unix example issues 18 49
Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now