Wednesday, October 1, 2008

Switchig views in SDI application.

Switching More than one CView.

 

In our current project DocuMight there are  multiple file types and corresponding CView derived class .
Application type is SDI and we don’t want to edit files. I tried 3 methods for this.

1)      Using Document template
Created new CSingleDocTemplate and added using CWinApp:: AddDocTemplate() method.

2)      Dynamically creation of new View via code.
Here I found some problem in window creation and deletion. So dynamically creation method doped .

3)      Switching already created views. - I got this method from MSDN sample.

for example Let assume that we have 3 Views CImageView, CDocumentView and CDatabaseView all are derived from CView and our default view is CImageView.Following are the sample code :

#define TOTAL_NUM_VIEWS 3
enum ViewType
{
      ImageView = 0,      DocumentView = 1,
      DataBaseView = 2,

};

 

class CMainFrame : public CFrameWnd
{
 public:
    void InitViews();
 private:
  // Array of views attached to single document
  CView * m_pViews[TOTAL_NUM_VIEWS];
  void SwitchView( ViewType viewType);
  static void SwapWindowID(const HWND& hWndFirst, const HWND& hWndSecond);
  UINT m_nCurView ;
};

void CMainFrame::InitViews ()
{
    m_nCurView = 0;        // Save index of the currently active view class
    CView* pActiveView = GetActiveView();

    m_pViews[ImageView] = pActiveView;
    // no need to delete View .
    //The application automatically deletes the view when the application is closed.
    m_pViews[DocumentView] = (CView*) new CDocumentView;
    m_pViews[DataBaseView] = (CView*) new CDatabaseView;

    CDocument* pCurrentDoc = GetActiveDocument();   

    // Initialize a CCreateContext to point to the active document.
    // With this context, the new view is added to the document
    // when the view is created in CView::OnCreate().
    CCreateContext newContext ;
    newContext.m_pNewViewClass = NULL;
    newContext.m_pNewDocTemplate = NULL;
    newContext.m_pLastView = NULL;
    newContext.m_pCurrentFrame = NULL;
    newContext.m_pCurrentDoc = pCurrentDoc;
    for (int nView = 1; nView < TOTAL_NUM_VIEWS; nView++)
    {
        m_pViews[nView]->Create(NULL, NULL,(AFX_WS_DEFAULT_VIEW & ~WS_VISIBLE),
                            CRect(0,0,0,0), this,AFX_IDW_PANE_FIRST + nView, &newContext);
        m_pViews [nView]->OnInitialUpdate();
    }
}
void CMainFrame::SwapWindowID(const HWND& hWndFirst, const HWND& hWndSecond)
{
      //If GWL_ID then Retrieves the identifier of the window.
      UINT nFirstWindow   = ::GetWindowLong(hWndFirst, GWL_ID);
      UINT nSecondWindow  = ::GetWindowLong(hWndSecond, GWL_ID);
      //Set Id of window.
      ::SetWindowLong(hWndFirst, GWL_ID, nSecondWindow);
      ::SetWindowLong(hWndSecond, GWL_ID, nFirstWindow);
}
void CMainFrame::SwitchView( ViewType viewType)
{
      ASSERT( viewType >=0 && viewType < TOTAL_NUM_VIEWS );
      if ( viewType < 0 || viewType >= TOTAL_NUM_VIEWS )
            return;
      if (!m_pViews)
            return;
      CView* pNewView = m_pViews[viewType];
     

      CView* pActiveView =GetActiveView();
      if ( !pActiveView )    // No currently active view
            return;
      if ( pNewView == pActiveView )    // Already t  here
            return;
      //Swap ID's of Window.
      SwapWindowID( pActiveView->m_hWnd, pNewView->m_hWnd);
      pActiveView->ShowWindow(SW_HIDE);
      pNewView->ShowWindow(SW_SHOW);
      __super::SetActiveView(pNewView);
      __super::RecalcLayout();
      pNewView->Invalidate();
}

Steps :
1)In CwinApp call CMainFrame::InitViews() after ProcessShellCommand.
2)
on switching Event call SwitchView() method. eg: SwitchView(DataBaseView);

 

1/oct/2008

 

 

 

No comments: