Programming

How to Create a Custom View to Wrap Your Own Control

This article was originally published on CodeGuru.com on January 30, 2000.

Environment: VC++ 5.0, SP3, Win95

Download sample code (16K)

One of the questions that I see posted to microsoft.public.vc.mfc frequently is "How do I use my CListCtrl (or CTreeCtrl, CListBox, etc.) -derived control with a CListView (or CTreeView, etc.)?" As Zafir Anjum pointed out in his article "How do I use a derived CListCtrl with a CListView?", you don't. He provided the option of deriving your class from CListView or CTreeView, instead of the corresponding control class, and adding all of the desired customization to your newly derived view class.

Zafir's approach works with controls for which MFC provides a view class. However, if MFC doesn't provide a corresponding view class, or if you want to use your nice new control in both a view and a dialog, that solution is less than perfect. While you can use a CView-derived class in a dialog, it's cumbersome. Instead, I suggest that you leave all of the customization in the control-derived class and simply roll your own custom CView-derived class for it. It's really quite easy to do. The following example uses a CListCtrl-derived class.

Step 1: Derive a custom class from CView

This is easily done with the Class Wizard. Simply click on the "Add" button and choose "New class...". Select CView as the base class and enter a name for your derived class.

Step 2: Add a member variable of your custom control class

protected:
CMyListCtrl m_ListCtrl;

Step 3: Override the OnCreate() function of your CView-derived class

Override this function and add code to create your control.

// When OnCreate is called for the view, we create the
// CMyListCtrl instance that will occupy the client area
// of the view.


int CMyListView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;

// Create the style
DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | LVS_REPORT;
// Create the list control. Don't worry about specifying
// correct coordinates. That will be handled in OnSize()
.
BOOL bResult = m_ListCtrl.Create(dwStyle, CRect(0,0,0,0), this, IDC_LIST1);

return (bResult ? 0 : -1);
} //OnCreate

Step 4: Override the OnSize() function of your CView-derived class

Override this function and add code to resize the control so that it occupies the entire client area of the CView-derived class.

// Override OnSize to resize the control to match the view
void CMyListView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
if (::IsWindow(m_ListCtrl.m_hWnd))
m_ListCtrl.MoveWindow(0, 0, cx, cy, TRUE);
}//OnSize

Step 5 (Optional): Override the OnInitialUpdate() function of your CView-derived class

If you wish, override this function and call any member functions of your control needed to initialize it. I usually create a member function in my control named Init() that reads in any data and adds it to the control. This function can be called either from CMyView::OnInitialUpdate() or CMyDialog::OnInitDialog().

void CMyListView::OnInitialUpdate()
{
CView::OnInitialUpdate();
m_ListCtrl.Init();
}//OnInitialUpdate
 


Praise

" Recently we realized that after switching hosts our contact page was acting weird.  We struggled w/ the programming and finally called in the bug guns: Celtic Wolf.  Not only did they advise us on the programming, they also helped us technically.  The page is now working and it's secure. "

Kathy Strauss
Creative Director, Principal
ImageWerks
http://www.imagewrks.net