Click here to Skip to main content
Click here to Skip to main content

Create Sub Window for MiniView under CView

By , 18 Jul 2006
 

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

About the Author

Youngho Kim
Software Developer
Korea (Republic Of) Korea (Republic Of)
Member
I hope to help your coding processing.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalusing WS_POPUPmemberrominetb4416 Mar '09 - 3:33 
Hello,
 
Thanks for this code whitch was very helpfull for me! Big Grin | :-D
 
When using WS_POPUP like this : m_wndMiniWnd.CreateEx(WS_EX_CLIENTEDGE, NULL, "", WS_POPUP | WS_VISIBLE, clientRect, this, NULL);
every mouse message generate assertions :
ASSERT(pParentFrame == pDesktopWnd || pDesktopWnd->IsChild(pParentFrame));
in
int CView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message).
 
Indeed, it seems that MFC link diffucltly the CWnd and the CView. I succeed in resolve the problem with replacing :
class CMiniWnd : public CWnd
by
class CMiniWnd : public CFrameWnd Confused | :confused:
 
I find an easy way to remove border of the frame :
Remove WS_BORDER in the style of the view and add this after creating the Frame :
m_wndMiniWnd.ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED); Cool | :cool:
 
Thanks a lot ! Thumbs Up | :thumbsup:
GeneralAccessing the documentmemberMarcusWelby18 Jul '08 - 15:57 
I cannot access the document from the CMiniView class. pDoc is NULL.
Why doen GetDocument() return a NULL ?
 
regards,
Marcus
GeneralRe: Accessing the documentmemberMember 179310416 Oct '08 - 16:56 
this program makes windows using cwnd create function
but document have to exist CContext using RUNTIME_CLASS macro.
 
if you want get the document.
you must create CContext parameter on CWinApp class.
Generalgood !memberdavid_joung12 Feb '07 - 6:11 
it helped my codes to make formview in non-doc-frame situation.
so thank you..

QuestionHow about CWndsussAnonymous6 May '05 - 19:28 
Looks like all you want to do is embed a window inside CView. If this is the case, just inherit from CWnd instead of CView. That will fix the error when destroying window.
GeneralQustion about the snippets!!!!memberDavidRipple23 Oct '04 - 15:41 
Hi,after reading your snippets,I have some questions about the source code you supplied:
1.
 
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;
}
Do you think that the code in the second brackets would
get the chance to execute?
Then pContext = &contextT; would have no sense!!
 
2.
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
Since you return in catch_all ,the code belows the END_CATCH_ALL would be executed??
 
3.Since your solution to the problem is different from
m_wndView.Create(NULL, _T("VIEW"), WS_CHILD | WS_VISIBLE, CRect(0,0,0,0), this, 10000);
is only in CCreateContext using or not(am i right ??)
So why not place it directly in CSampleView,but using a
CMiniWnd as a trampolin??Confused | :confused:
Thank you!
GeneralRe: Qustion about the snippets!!!!memberYoungho Kim24 Oct '04 - 0:41 
1. CCreateContext class is frame when creates CObjects like a CRuntimeClass.
 
First, You have to insert about CObject properties. This case is CRuntimeClass of CMiniView. And This object is pOldView. The pOldView composed by View, Document and Document Template. You are right. CMinuView does not have Document and Template. But If you want to have Document and Document Template, You should have second brackets.
 
2. This routine have make returning NULL.
 
3. I wish to make a library. but If i does not make CMiniWnd, I must to create in CSampleView of CMiniView Creation routine. So I make for interface using CMiniWnd windows.

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 18 Jul 2006
Article Copyright 2004 by Youngho Kim
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid