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
No comments:
Post a Comment