Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Create Sub Window for MiniView under CView

0.00/5 (No votes)
18 Jul 2006 1  
This Article is make of a CView under CView using CWnd control

Sample Image - sample.jpg

Introduction

This source make CView window under CView using CWnd control. You need Visual C++ 7.1 to read this source project. I create this project on Visual Studio .NET 2003.

Description

Many people wish to make multiful window on CView or any other View(CScrollView, CEditView, CFormView, etc...) without new frame and splitter window. How to make this window? Many people think about Create(...) Function.

Many People make Create function for new window creation, like this

CView m_wndView;

m_wndView.Create(NULL, _T("VIEW"), WS_CHILD | WS_VISIBLE, CRect(0,0,0,0), this, 10000);

But this method occur the error while destory window because DestoryWindow procedure. This real method need to help RUNTIME_CLASS. We seem to create always View, Document, Frame.

My Method

My method using RUNTIME_CLASS at CWnd creattion. First, You make CWnd window at basic CView Window. I called this window CMiniWnd from CWnd.

First, You make CWnd control at your View.

void CsampleView::OnInitialUpdate()
{
 CView::OnInitialUpdate();

 // View size

 CRect clientRect;
 GetClientRect(&clientRect);
 clientRect.SetRect(clientRect.right -110, clientRect.top+10, clientRect.right-10, clientRect.top +110);

 m_wndMiniWnd.Create(NULL, _T("MINI"), WS_VISIBLE | WS_CHILD, clientRect, this, IDR_MINIWND);

 m_wndMiniWnd.ShowWindow(SW_SHOW);

}

void CsampleView::OnSize(UINT nType, int cx, int cy)
{
 CView::OnSize(nType, cx, cy);

 if(m_wndMiniWnd.GetSafeHwnd())
 {
  CRect clientRect;
  GetClientRect(&clientRect);
  clientRect.SetRect(clientRect.right -110, clientRect.top+10, clientRect.right-10, clientRect.top +110);

  m_wndMiniWnd.MoveWindow(clientRect);
 }
}

Second, You make CWnd control like this from CWnd control class.

// MiniWnd.h

#pragma once
#include "miniview.h"



// CMiniWnd


class CMiniWnd : public CWnd
{
 DECLARE_DYNAMIC(CMiniWnd)

public:
 CMiniWnd();
 virtual ~CMiniWnd();

protected:
 DECLARE_MESSAGE_MAP()
public:
 CMiniView* m_wndView;
 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
 CMiniView* CreateView(CRuntimeClass * pViewClass, const RECT & lprect, CCreateContext * pContext);
 CMiniView* GetActiveView(void);
 afx_msg BOOL OnEraseBkgnd(CDC* pDC);
 afx_msg void OnPaint();
 void RecalcLayout(void);
 afx_msg void OnSize(UINT nType, int cx, int cy);
};
// MiniWnd.cpp


#include "stdafx.h"

#include "sample.h"

#include "MiniWnd.h"

#include ".\miniwnd.h"



// CMiniWnd


IMPLEMENT_DYNAMIC(CMiniWnd, CWnd)
CMiniWnd::CMiniWnd()
: m_wndView(NULL)
{
}

CMiniWnd::~CMiniWnd()
{
}


BEGIN_MESSAGE_MAP(CMiniWnd, CWnd)
 ON_WM_CREATE()
 ON_WM_ERASEBKGND()
 ON_WM_PAINT()
 ON_WM_SIZE()
END_MESSAGE_MAP()

int CMiniWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CWnd::OnCreate(lpCreateStruct) == -1)
  return -1;

 CRect rect;
 GetClientRect(rect);

 CRuntimeClass* pNewViewClass;
 pNewViewClass = RUNTIME_CLASS(CMiniView);

 // create the new view

 CCreateContext context;
 context.m_pNewViewClass = pNewViewClass;


 CMiniView* pNewView = CreateView(pNewViewClass, rect,  &context);

 if (pNewView != NULL)
 {
  // the new view is there, but invisible and not active...

  pNewView->ShowWindow(SW_SHOW);
  pNewView->OnInitialUpdate();
  pNewView->SetActiveWindow();

  RecalcLayout();
 }
 return 0;
}

CMiniView* CMiniWnd::CreateView(CRuntimeClass * pViewClass, const RECT & lprect, CCreateContext * pContext)
{
#ifdef _DEBUG
 ASSERT_VALID(this);
 ASSERT(pViewClass != NULL);
 ASSERT(pViewClass->IsDerivedFrom(RUNTIME_CLASS(CWnd)));
 ASSERT(AfxIsValidAddress(pViewClass, sizeof(CRuntimeClass), FALSE));
#endif
 
 BOOL bSendInitialUpdate = FALSE;

 CCreateContext contextT;
 if (pContext == NULL)
 {
  // if no context specified, generate one from the currently selected

  //  client if possible

  CMiniView* pOldView = NULL;
  if (pOldView != NULL && pOldView->IsKindOf(RUNTIME_CLASS(CMiniView)))
  {
   // set info about last pane

   ASSERT(contextT.m_pCurrentFrame == NULL);
   contextT.m_pLastView = pOldView;
   contextT.m_pCurrentDoc = pOldView->GetDocument();
   if (contextT.m_pCurrentDoc != NULL)
    contextT.m_pNewDocTemplate =
    contextT.m_pCurrentDoc->GetDocTemplate();
  }
  pContext = &contextT;
  bSendInitialUpdate = TRUE;
 }

 CWnd* pWnd;
 TRY
 {
  pWnd = (CWnd*)pViewClass->CreateObject();
  if (pWnd == NULL)
   AfxThrowMemoryException();
 }
 CATCH_ALL(e)
 {
  TRACE0("Out of memory creating a splitter pane.\n");
  // Note: DELETE_EXCEPTION(e) not required

  return (CMiniView*) NULL;
 }
 END_CATCH_ALL

  ASSERT_KINDOF(CWnd, pWnd);
 ASSERT(pWnd->m_hWnd == NULL);       // not yet created


 DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_BORDER;//AFX_WS_DEFAULT_VIEW |;


 // Create with the right size (wrong position)

 CRect rect(lprect);
 if (!pWnd->Create(NULL, NULL, dwStyle,
  rect, this, 0, pContext))
 {
  TRACE0("Warning: couldn't create client pane for splitter.\n");
  // pWnd will be cleaned up by PostNcDestroy

  return (CMiniView*) NULL;
 }

 // send initial notification message

 if (bSendInitialUpdate);
 //              pWnd->SendMessage(WM_INITIALUPDATE);

 m_wndView = (CMiniView*) pWnd;
 return m_wndView;
}

CMiniView* CMiniWnd::GetActiveView(void)
{
 return m_wndView;
}

BOOL CMiniWnd::OnEraseBkgnd(CDC* pDC)
{
 return FALSE;
}

void CMiniWnd::OnPaint()
{
 CPaintDC dc(this); // device context for painting

}

void CMiniWnd::RecalcLayout(void)
{
 CWnd* pWnd = (CWnd*) GetActiveView();
 CRect rect;
 GetClientRect(&rect);
}

void CMiniWnd::OnSize(UINT nType, int cx, int cy)
{
 CWnd::OnSize(nType, cx, cy);

 if(m_wndView->GetSafeHwnd());
 {
  CRect rcView(0, 0, cx, cy);
  m_wndView->MoveWindow(rcView);
 }
}

Create SubWindow

You see the OnCreate Function and CreateView Function.

OnCreate Function is make CRuntimeClass and CCreateContect. You need this member at that CreateView Function. CRuntimeClass member make CMiniView from CView type. and CCreateContect member insert pNewViewClass using CRuntimeClass.

 CRuntimeClass* pNewViewClass;
 pNewViewClass = RUNTIME_CLASS(CMiniView);

 // create the new view

 CCreateContext context;
 context.m_pNewViewClass = pNewViewClass;

and Create View window on CWnd control at CreateView Function.

 CMiniView* pNewView = CreateView(pNewViewClass, rect,  &context);

Next step is to make visible and initialization of window.

 if (pNewView != NULL)
 {
  // the new view is there, but invisible and not active...

  pNewView->ShowWindow(SW_SHOW);
  pNewView->OnInitialUpdate();
  pNewView->SetActiveWindow();

  RecalcLayout();
 }

Real Action

Real Action method is CreateView function.

CMiniView* CMiniWnd::CreateView(CRuntimeClass * pViewClass, const RECT & lprect, CCreateContext * pContext)
{
#ifdef _DEBUG
 ASSERT_VALID(this);
 ASSERT(pViewClass != NULL);
 ASSERT(pViewClass->IsDerivedFrom(RUNTIME_CLASS(CWnd)));
 ASSERT(AfxIsValidAddress(pViewClass, sizeof(CRuntimeClass), FALSE));
#endif
 
 BOOL bSendInitialUpdate = FALSE;

 CCreateContext contextT;
 if (pContext == NULL)
 {
  // if no context specified, generate one from the currently selected

  //  client if possible

  CMiniView* pOldView = NULL;
  if (pOldView != NULL && pOldView->IsKindOf(RUNTIME_CLASS(CMiniView)))
  {
   // set info about last pane

   ASSERT(contextT.m_pCurrentFrame == NULL);
   contextT.m_pLastView = pOldView;
   contextT.m_pCurrentDoc = pOldView->GetDocument();
   if (contextT.m_pCurrentDoc != NULL)
    contextT.m_pNewDocTemplate =
    contextT.m_pCurrentDoc->GetDocTemplate();
  }
  pContext = &contextT;
  bSendInitialUpdate = TRUE;
 }

 CWnd* pWnd;
 TRY
 {
  pWnd = (CWnd*)pViewClass->CreateObject();
  if (pWnd == NULL)
   AfxThrowMemoryException();
 }
 CATCH_ALL(e)
 {
  TRACE0("Out of memory creating a splitter pane.\n");
  // Note: DELETE_EXCEPTION(e) not required

  return (CMiniView*) NULL;
 }
 END_CATCH_ALL

  ASSERT_KINDOF(CWnd, pWnd);
 ASSERT(pWnd->m_hWnd == NULL);       // not yet created


 DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_BORDER;//AFX_WS_DEFAULT_VIEW |;


 // Create with the right size (wrong position)

 CRect rect(lprect);
 if (!pWnd->Create(NULL, NULL, dwStyle,
  rect, this, 0, pContext))
 {
  TRACE0("Warning: couldn't create client pane for splitter.\n");
  // pWnd will be cleaned up by PostNcDestroy

  return (CMiniView*) NULL;
 }

 // send initial notification message

 if (bSendInitialUpdate);
 //              pWnd->SendMessage(WM_INITIALUPDATE);

 m_wndView = (CMiniView*) pWnd;
 return m_wndView;
}

This Function Key point is pWnd = (CWnd*)pViewClass->CreateObject(); line. This line make object of CMiniView using predefine type.

And the other function make movable action and get ActiveView pointer.

CView Window

// MiniView.h

#pragma once

// CMiniView


class CMiniView : public CView
{
 DECLARE_DYNCREATE(CMiniView)

public:
 CMiniView();         
 virtual ~CMiniView();

public:
 virtual void OnDraw(CDC* pDC);      
#ifdef _DEBUG
 virtual void AssertValid() const;
 virtual void Dump(CDumpContext& dc) const;
#endif

protected:
 DECLARE_MESSAGE_MAP()
public:
 virtual void OnInitialUpdate();
 afx_msg void OnSize(UINT nType, int cx, int cy);
};
// MiniView.cpp


#include "stdafx.h"

#include "sample.h"

#include "MiniView.h"

#include ".\miniview.h"



// CMiniView


IMPLEMENT_DYNCREATE(CMiniView, CView)

CMiniView::CMiniView()
{
}

CMiniView::~CMiniView()
{
}

BEGIN_MESSAGE_MAP(CMiniView, CView)
 ON_WM_SIZE()
END_MESSAGE_MAP()


// CMiniView Draw


void CMiniView::OnDraw(CDC* pDC)
{
 CDocument* pDoc = GetDocument();
 pDC->TextOut(0, 0, "Hello");
}


// CMiniView DEBUG.


#ifdef _DEBUG
void CMiniView::AssertValid() const
{
 CView::AssertValid();
}

void CMiniView::Dump(CDumpContext& dc) const
{
 CView::Dump(dc);
}
#endif //_DEBUG


void CMiniView::OnInitialUpdate()
{
 CView::OnInitialUpdate();

}

void CMiniView::OnSize(UINT nType, int cx, int cy)
{
 CView::OnSize(nType, cx, cy);
}

 

 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here