Custom Control derived from CWnd won't paint inside CFormView Wind
 
Hi all. 
I'm wanting to use a CFormView in a Doc/View project that contains several 
comboboxes, textboxes, and a custom control. The custom control is not 
painting when I run the program.
Using the dialog resource editor, I have created a resource called 
IDD_AZURE_FORM, and placed my common controls on it. In addition, I have 
dropped a custom control on it, and set the following properties:
Class = CDualTreeViewerCtrl
Disabled = False
ExtendedStyle = 0x0
Group = False
ID = IDC_DUALTREE
Style = 0x50010000
Tabstop = True
Visible = True
Prior to this, I had created a CWnd derived window called CDualTree that 
will be used for my custom control. The following code it the CDualTree 
header:
#pragma once
#define DUALTREEVIEWER_CLASSNAME _T("CDualTreeViewerCtrl")
class CDualTree : public CWnd
{
    DECLARE_DYNAMIC(CDualTree)
public:
    CDualTree();
    virtual ~CDualTree();
public:
    virtual void OnDraw(CDC* pDC);
protected:
    BOOL RegisterWindowClass();
protected:
    DECLARE_MESSAGE_MAP()
};
The following file is the implementation file. Please note I'm registering 
the window in the Constructor.
IMPLEMENT_DYNAMIC(CDualTree, CWnd)
CDualTree::CDualTree()
{
    RegisterWindowClass();
}
CDualTree::~CDualTree()
{
}
void CDualTree::OnDraw(CDC* pDC)
{
    // paint code omitted...
}
BOOL CDualTree::RegisterWindowClass()
{
    WNDCLASS wndcls;
    HINSTANCE hInst = AfxGetInstanceHandle();
    // Register Window Class on first time use.
    if (!(::GetClassInfo(hInst, DUALTREEVIEWER_CLASSNAME, &wndcls)))
    {
        wndcls.style            = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
        wndcls.lpfnWndProc      = ::DefWindowProc;
        wndcls.cbClsExtra       = wndcls.cbWndExtra = 0;
        wndcls.hInstance        = hInst;
        wndcls.hIcon            = NULL;
        wndcls.hCursor          = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
        wndcls.hbrBackground    = (HBRUSH) (COLOR_3DFACE + 1);
        wndcls.lpszMenuName     = NULL;
        wndcls.lpszClassName    = DUALTREEVIEWER_CLASSNAME;
        if (!AfxRegisterClass(&wndcls))
        {
            AfxThrowResourceException();
            return FALSE;
        }
    }
    return TRUE;
}
BEGIN_MESSAGE_MAP(CDualTree, CWnd)
END_MESSAGE_MAP()
Now, from what I have been able to find out online, the steps required to 
sync these two up is the following:
From the resource editor, I generate a CFormView class using the class 
wizard. I then add a member variable for my Custom Control using the Add 
variable function.
The following class header for CAzureView is the result of those two actions:
#pragma once
#include "dualtree.h"
class CAzureView : public CFormView
{
protected: // create from serialization only
    CAzureView();
    DECLARE_DYNCREATE(CAzureView)
public:
    enum{ IDD = IDD_AZURE_FORM };
// Attributes
public:
    CAzureDoc* GetDocument() const;
// Operations
public:
// Overrides
public:
    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    virtual void OnInitialUpdate(); // called first time after construct
// Implementation
public:
    virtual ~CAzureView();
#ifdef _DEBUG
    virtual void AssertValid() const;
    virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
    afx_msg void OnFilePrintPreview();
    afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
    DECLARE_MESSAGE_MAP()
public:
    CDualTree m_dualTree;
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
};
#ifndef _DEBUG  // debug version in AzureView.cpp
inline CAzureDoc* CAzureView::GetDocument() const
   { return reinterpret_cast<CAzureDoc*>(m_pDocument); }
#endif
Please note it's created the CDualTree m_dualTree member variable.
The following is the implementation file for the header:
#include "stdafx.h"
#include "Azure.h"
#include "AzureDoc.h"
#include "AzureView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
IMPLEMENT_DYNCREATE(CAzureView, CFormView)
BEGIN_MESSAGE_MAP(CAzureView, CFormView)
    ON_WM_CREATE()
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////////
// CAzureView construction/destruction
CAzureView::CAzureView()
    : CFormView(CAzureView::IDD)
{
}
CAzureView::~CAzureView()
{
}
void CAzureView::DoDataExchange(CDataExchange* pDX)
{
    CFormView::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_DUALTREE, m_dualTree);
}
BOOL CAzureView::PreCreateWindow(CREATESTRUCT& cs)
{
    // TODO: Modify the Window class or styles here by modifying
    //  the CREATESTRUCT cs
    return CFormView::PreCreateWindow(cs);
}
void CAzureView::OnInitialUpdate()
{
    CFormView::OnInitialUpdate();
    ResizeParentToFit();
}
void CAzureView::OnRButtonUp(UINT nFlags, CPoint point)
{
    ClientToScreen(&point);
    OnContextMenu(this, point);
}
void CAzureView::OnContextMenu(CWnd* pWnd, CPoint point)
{
    theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, 
point.y, this, TRUE);
}
///////////////////////////////////////////////////////////////////////////////
// CAzureView diagnostics
#ifdef _DEBUG
void CAzureView::AssertValid() const
{
    CFormView::AssertValid();
}
void CAzureView::Dump(CDumpContext& dc) const
{
    CFormView::Dump(dc);
}
CAzureDoc* CAzureView::GetDocument() const // non-debug version is inline
{
    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CAzureDoc)));
    return (CAzureDoc*)m_pDocument;
}
#endif //_DEBUG
///////////////////////////////////////////////////////////////////////////////
// CAzureView message handlers
int CAzureView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFormView::OnCreate(lpCreateStruct) == -1)
        return -1;
    m_dualTree.Create(_T("CDualTreeViewerCtrl"), _T(""), WS_VISIBLE, 
CRect(0,0,100,100), this, 1);
    return 0;
}
The code added is the called to m_dualTree.Create() in the ::OnCreate 
function.
Now, when I run the program, the view loads fine, but the CDualTree window 
is not drawn in the middle of the CFormView. However, if I look at the window 
with Spy++, it's actually there, it's just not being painted. A break point 
on the OnDraw function is never hit.
The interesting thing is, if I remove the m_dualTree.Create call in 
CAZureView::OnCreate, I still get the same behaviour, i.e. in Spy++ the 
window is still there, just not being drawn. 
I'm not sure if the ::OnCreate call is even needed, however I thought it was 
required to set the correct styles, parent etc?
Any suggestions would be greatly appreciated!
Cheers
Jason