YOU CAN CODE!

 

With The Case Of UCanCode.net  Release The Power OF  Visual C++ !   HomeProducts | PurchaseSupport | Downloads  
Download Evaluation
Pricing & Purchase?
E-XD++Visual C++/ MFC Products
Overview
Features Tour 
Electronic Form Solution
Visualization & HMI Solution
Power system HMI Solution
CAD Drawing and Printing Solution

Bar code labeling Solution
Workflow Solution

Coal industry HMI Solution
Instrumentation Gauge Solution

Report Printing Solution
Graphical modeling Solution
GIS mapping solution

Visio graphics solution
Industrial control SCADA &HMI Solution
BPM business process Solution

Industrial monitoring Solution
Flowchart and diagramming Solution
Organization Diagram Solution

Graphic editor Source Code
UML drawing editor Source Code
Map Diagramming Solution

Architectural Graphic Drawing Solution
Request Evaluation
Purchase
ActiveX COM Products
Overview
Download
Purchase
Technical Support
  General Q & A
Discussion Board
Contact Us

Links

Get Ready to Unleash the Power of UCanCode .NET


UCanCode Software focuses on general application software development. We provide complete solution for developers. No matter you want to develop a simple database workflow application, or an large flow/diagram based system, our product will provide a complete solution for you. Our product had been used by hundreds of top companies around the world!

"100% source code provided! Free you from not daring to use components because of unable to master the key technology of components!"


VC++ MFC Example: Multiple Document / Views, CObList

 
By Pedro Jorquera. 

An article on creation of multiple views dynamically without document/view architecture

Sample Image - dynviews.jpg

Introduction

This article presents a method for multiple dynamic views creation whithout the MFC's document/view architecture. That views could be attached to other frames, controls or dock bars.

The document/view architecture is a very useful mechanism to create robust applications that requires multiple views, but sometimes there is not necessary such funcionality. Even though creating views whithout the help of the framework is neither evident or easy. The problem lies basically in the following aspects:

  1. Derivating a class from CView does not allow creation of the views using the operator new because the constructor and destructor of the derivated class are protected.

     

  2. When the window or frame that contains the views created "by hand" is destroyed, then automatically the objects CView are destroyed and is invokated the DestroyWindow() for each one. That's why the created views can not be referenced using objects like member variables of a class but using pointers to objects, so it is necessary to use the operator new for its creation but not invoking delete because the framework will destroy that objects automatically.

     

  3. When creating multiple views dinamically there is necessary to assign valid identifiers that can not be defined using the resource editor of Visual C++. For that there must be defined a generic identifier that will be used as base for the identification of each view that will be created by the time (using something like WM_USER + idView0, WM_USER + idView1, ...).

     

Step by Step

  1. Derivate the customized view/views using the wizard of Visual C++ from CView and make public the constructor and destructor of the class. This will allow the using of the operator new in the objects creation.

     

    Collapse
    //// This view encapsulates a personalized 2D view
    class CMyView : public CView
    {
    
      class CMyPoint : public CObject  
      {		
      public:
        CMyPoint(CPoint location) { m_location = location; }
        CPoint  m_location;
      };
    
    public:
      CMyView();
      virtual ~CMyView();
    
    public:
      int  m_idView;
    
    protected:
      DECLARE_DYNCREATE(CMyView)
    
    // Attributes
    protected:
      CObList	  m_points;
    
    // Operations
    public:
    
    // Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CMyView)
      protected:
      virtual void OnDraw(CDC* pDC);      // overridden to draw this view
      //}}AFX_VIRTUAL
    
    // Implementation
    protected:
    #ifdef _DEBUG
      virtual void AssertValid() const;
      virtual void Dump(CDumpContext& dc) const;
    #endif
    
      // Generated message map functions
    protected:
      //{{AFX_MSG(CMyView)
      afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
      afx_msg void OnMouseMove(UINT nFlags, CPoint point);
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
    };
    
  2. In the frame/window/dialog class where it is desired to create and reference the views, it is necessary to add an object list/array (CObList) or a set of attributes pointer to the views so in the future could be referenced the views using those variables. In the example it is created an object CObList that stores a pointer to each view created and that object CObList is added to the dialog which is the main window.

     

    Collapse
    /////////////////////////////////////////////////////////////////////////////
    // CDynViewsDlg dialog
    
    
    enum VIEW_TYPE { VIEW_2D, VIEW_OPENGL };
    
    class CDynViewsDlg : public CDialog
    {
    // Construction
    public:
      CDynViewsDlg(CWnd* pParent = NULL); // standard constructor
    
    // Dialog Data
      //{{AFX_DATA(CDynViewsDlg)
      enum { IDD = IDD_DYNVIEWS_DIALOG };
      CTabCtrl  m_tabCtrl;
      //}}AFX_DATA
    
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CDynViewsDlg)
      protected:
      virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support
      //}}AFX_VIRTUAL
    
    // Implementation
    protected:
      void AddView(VIEW_TYPE viewType);
      void SelectTab(int nTab);
      HICON m_hIcon;
    
      // This member allows to reference any
      // dynamically created view
      CObList	  m_listViews;
    
      // Generated message map functions
      //{{AFX_MSG(CDynViewsDlg)
      virtual BOOL OnInitDialog();
      afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
      afx_msg void OnPaint();
      afx_msg HCURSOR OnQueryDragIcon();
      afx_msg void OnSelchangeTabctrl(NMHDR* pNMHDR, LRESULT* pResult);
      afx_msg void OnAddview();
      afx_msg void OnAddopenglview();
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
    };
    
  3. When is desired to create a new view, simply must be created an object of that class CView using the operator new, store the pointer to that view for lately use, search a new identifier not used for the new view and invoke create of the view using that identifier.

     

    Collapse
    // Handle for button click "Add 2D View"
    void CDynViewsDlg::OnAddview() 
    {
      AddView(VIEW_2D);
    }
    
    // Handle for button click "Add 3D/OpenGL View"
    void CDynViewsDlg::OnAddopenglview() 
    {
      AddView(VIEW_OPENGL);
    }
    
    /*
     * AddView Method:
     *
     * 1. Creates a new tab for the view
     * 2. Creates a new view dynamically of the desired type
     * 3. Asociates the id of the view with the id of the tab
     * 4. Selects the new created view and tab
     */
    void CDynViewsDlg::AddView(VIEW_TYPE viewType)
    {
      // ID of the new view
      int idNewView = m_listViews.GetCount();
    	
      // View size
      CRect clientRect;
      m_tabCtrl.GetClientRect(&clientRect);
      clientRect.DeflateRect(10, 30);
    
      // Creation 'on the fly' of the new view
      CMyView* m_pNewView;
      CString tabCaption;
    	
      switch(viewType) {
    
      case VIEW_2D:
        // The operator 'new' has not asociated delete.
        // The view will be deleted automatically by the framework
        // on the WM_DESTROY handle of the parent (the tab control)
        m_pNewView = new CMyView();
        tabCaption.Format("View %d (2D)", idNewView);
        break;
    
        case VIEW_OPENGL:
        // The operator 'new' has not asociated delete.
        // The view will be deleted automatically by the framework
        // on the WM_DESTROY handle of the parent (the tab control)
        m_pNewView = new COpenGLView();
        tabCaption.Format("View %d (OpenGL)", idNewView);
        break;
    
      };
    		
      // The new tab for the view on the tab control
      m_tabCtrl.InsertItem(idNewView, tabCaption);
      m_pNewView->m_idView = idNewView;
    
      // Creation of the view window
      if(! m_pNewView->Create(NULL, NULL, WS_VISIBLE | WS_CHILD, clientRect,
                              &m_tabCtrl, ID_VIEW_BASE + idNewView))
      {
        TRACE( "Failed view creation\n" );
      }
    
      // Using a list is easy to handle all the views created
      m_listViews.AddTail(m_pNewView);
    
      // Select the new created tab/view
      m_tabCtrl.SetCurSel(idNewView);
      SelectTab(idNewView);
    }
    
  4. Once this has been made it is possible to use the pointer to the view to achieve basic window functions like show/hide, change size, etc.

     

    /*
     * This method switchs the visibility of each
     * view, making visible only the selected view
     * asociated with the tab nTab
     *
     */
    void CDynViewsDlg::SelectTab(int nTab)
    {
      CMyView* pViewSelected = NULL;
      POSITION pos = m_listViews.GetHeadPosition();
    
      // Hide all views under the tabControl
      while(pos != NULL) {
        CMyView* pView = (CMyView*) m_listViews.GetNext(pos);
        pView->ShowWindow(SW_HIDE);
        if(pView->m_idView == nTab) pViewSelected = pView;
      };
    
      // Show the view asociated with the tab selected
      if(pViewSelected != NULL)
        pViewSelected->ShowWindow(SW_SHOW);
    }
    
  5. It is really important to remember that the objects CView created dynamically must not be deleted explicitally using the operator delete. In fact they will be automatically deleted by the framework in the WM_DESTROY message of the window that is parent of the views. In the example the parent of all the views is a tab control and when the application exits all the views are deleted and there are not any memory leaks.

     

 

Copyright ?1998-2009 UCanCode.Net Software , all rights reserved.
Other product and company names herein may be the trademarks of their respective owners.

Please direct your questions or comments to webmaster@ucancode.net