Click here to Skip to main content
15,881,413 members
Articles / Desktop Programming / MFC
Article

Create Sub Window for MiniView under CView

Rate me:
Please Sign up or sign in to vote.
1.62/5 (15 votes)
18 Jul 20061 min read 71.3K   2K   19   7
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


Written By
Software Developer
Korea (Republic of) Korea (Republic of)
I hope to help your coding processing.

Comments and Discussions

 
GeneralQustion about the snippets!!!! Pin
DavidRipple23-Oct-04 15:41
DavidRipple23-Oct-04 15:41 
GeneralRe: Qustion about the snippets!!!! Pin
Youngho Kim24-Oct-04 0:41
Youngho Kim24-Oct-04 0:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.