原文地址: http://blog.chinaunix.net/uid-8193682-id-2513440.html
作者: David Howe
因实际需要,要子类化一个已经编写好的CTreeView中的CTreeCtrl,以实现特定的功能。。。
确切的说,我需要的功能是:在对这个CTreeView进行节点的增加、删除、修改时,要做一些额外的工作,举个最简单的例子:写日志记录。------当然,可以在所有进行上述操作的地方去添加写日志的功能,但如果牵扯的地方很多,不愿一一进行修改的话,子类化确实是一个最顺理成章的想法!
上网搜了一下,发现有不少人提出这样的问题,不过怎么就没找到谁把具体方法写出来!?(也没怎么认真去搜),于是,只有自己研究了,然后写一篇文,以后谁再有此问题就可以搜的到了。为此专门起了个容易被搜到的贴切标题。^^
下面是实现的核心代码:
----------------------------------MyTreeView.h----------------------------------
CNewTreeCtrl m_wndNewTreeCtrl; // 新的CTreeCtrl对象,将用它来子类化CMyTreeView中的CTreeCtrl控件。 BOOL m_bSubclassed; // 是否已经被我们子类化过的标志,初始化为FALSE // 需要重载这个函数,确保在子类化前后调用它,都会返回正确的结果 CTreeCtrl& GetTreeCtrl() const { if (m_bSubclassed) return (CTreeCtrl&)m_wndNewTreeCtrl; // 若子类化了,返回新的引用 else return CTreeView::GetTreeCtrl(); // 若未子类化,调用默认处理 } |
----------------------------------MyTreeView.cpp----------------------------------
void CMyTreeView::OnInitialUpdate() { CMyTreeView::OnInitialUpdate(); // // 进行子类化的代码 // CTreeCtrl& tree = GetTreeCtrl(); // 得到CTreeCtrl对象的引用 HWND hwndTreeCtrl = tree.m_hWnd; // 记录下它的句柄,下面马上会用到 tree.UnsubclassWindow(); // 因为这个窗口已经是子类化过的(用Spy++可以看出来),要先进行UnsubclassWindow m_wndNewTreeCtrl.SubclassWindow(hwndTreeCtrl); // 现在实现我的子类化 m_bSubclassed = TRUE; // 设置标志 // 下面这句很重要,否则很多API调用会认为CMyTreeView内部的控件窗口句柄无效 m_hWnd = m_wndNewTreeCtrl.m_hWnd; // 修正CMyTreeView的m_hWnd成员变量 } |
OK,现在可以通过在CNewTreeCtrl类中重载一些CTreeCtrl的成员函数来实现需要的功能了!