Let see how to create a CMFCListCtrl in a CDockablePane, or actually can also be implemented in most CWnd such as CMainFrame.
The Steps
1. Let say I have a class name CNodePane derived from CDockablePane.
2. The CMainFrame have a member of CNodePane m_nodePane.
3. CNodePane has readily incorporate all necessary functions needed as shown in the previous post; Pane: Creating Dockable Pane
The Steps
1. Add a member to CNodePane, namely CListCtrl m_nodeList. This is also what people call subclass CListCtrl into CNodePane.
#pragma once #include "afxdockablepane.h" class CNodePane : public CDockablePane { public: CNodePane(void); ~CNodePane(void); protected: CMFCListCtrl m_nodeList; // Add This public: DECLARE_MESSAGE_MAP() };
2. Write CNodePane::OnCreate(). In this function which will be call by Framework when a object of CNodePane (in this case m_nodePane) is created. Take this opportunity to create the m_nodeList window. Hint: use VS auto message code generator, find WM_CREATE message.
int CNodePane::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CDockablePane::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here CRect rect; GetClientRect(&rect); if(!m_nodeList.Create(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_VSCROLL | LVS_REPORT, rect, this, ID_NODE_LIST)) { TRACE0("Failed to create Nodes List\n"); return -1; } m_nodeList.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); return 0; }
3. Write CNodePane::OnSize() to handle the change of size of m_nodeList window when m_nodePane window is resize. Actually, we use this function to give actual size of m_nodeList window. Although m_nodePane.Create() required a data of CRect as the m_nodePane window size, we usually give a dump data, such as CRect(0,0,0,0). The actual size will be supply during CNodePane::OnSize() via m_nodeList.SetWindowPos()
void CNodePane::OnSize(UINT nType, int cx, int cy) { CDockablePane::OnSize(nType, cx, cy); // TODO: Add your message handler code here CRect rect; GetClientRect(&rect); m_nodeList.SetWindowPos(NULL, rect.left+50, rect.top+50, rect.Width()-60, rect.Height()-60, SWP_NOACTIVATE | SWP_NOZORDER); // as you can see my m_nodeList is not fully fill the m_nodePane Window Client Area }
4. If you fill all m_nodePane window Client Area with m_nodeList window, then your CListCtrl is ready to handle data manipulation.
5. However if m_nodeList window only occupy partial of m_nodePane window, you need to handle CNodePane::OnEraseBkgnd() which is filling the background by repainting back.
BOOL CNodePane::OnEraseBkgnd(CDC* pDC) { // TODO: Add your message handler code here and/or call default CRect rt; GetClientRect(&rt); CBrush br; br.CreateStockObject(WHITE_BRUSH); pDC->SelectObject(&br); pDC->Rectangle(&rt); // I just fill all the BG with white brush return CDockablePane::OnEraseBkgnd(pDC); }
6. You also need to call Invalidate() in last line of CNodePane::OnSize() to call the necessary function including CNodePane::OnPaint() and CNodePane::OnEraseBkgnd().
void CNodePane::OnSize(UINT nType, int cx, int cy) { CDockablePane::OnSize(nType, cx, cy); // TODO: Add your message handler code here CRect rect; GetClientRect(&rect); m_nodeList.SetWindowPos(NULL, rect.left+50, rect.top+50, rect.Width()-60, rect.Height()-60, SWP_NOACTIVATE | SWP_NOZORDER); Invalidate(); //Add this }
Note:
1. As NodePane.cpp may use ID resource when you call m_nodeList.Create(), don’t forget to #include “resource.h” or you will have the following error
Error 1 error C2065: 'ID_NODE_LIST' : undeclared identifier