CTREEVIEW中子类化CTREECTRL的问题

来源:互联网  时间:2016/7/2 17:56:38

关于网友提出的“ CTREEVIEW中子类化CTREECTRL的问题”问题疑问,本网通过在网上对“ CTREEVIEW中子类化CTREECTRL的问题”有关的相关答案进行了整理,供用户进行参考,详细问题解答如下:

问题: CTREEVIEW中子类化CTREECTRL的问题
描述:

自己试验写了个treectrl的自绘,希望将ctreeview中自带的树控件进行替换; 我在.h文件中

	TC_CUSTOMCctrl	m_ctrl;
由于自带的控件获取方式
	CTreeCtrl &tc = GetTreeCtrl();

然后再之后
	BOOL	bSus = m_ctrl.SubclassWindow(tc.GetSafeHwnd());
然后此处报错,是我的m_ctrl = 0,应该是哪里的步骤没做 以下是我自定义的tree
// TC_CUSTOMCctrl.cpp : 实现文件
//
#include "stdafx.h" #include "LV_CUSTOM.h" #include "TC_CUSTOMCctrl.h"
<>
// TC_CUSTOMCctrl IMPLEMENT_DYNAMIC(TC_CUSTOMCctrl, CTreeCtrl) TC_CUSTOMCctrl::TC_CUSTOMCctrl() {

}
TC_CUSTOMCctrl::~TC_CUSTOMCctrl()
{
} BEGIN_MESSAGE_MAP(TC_CUSTOMCctrl, CTreeCtrl) //如果绘图操作不需要父窗口参与,可以使用该控件的 ON_NOTIFY_REFLECT 宏处理它的 NM_CUSTOMDRAW 消息。
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &TC_CUSTOMCctrl::OnNMCustomdraw)
END_MESSAGE_MAP() // TC_CUSTOMCctrl 消息处理程序

void TC_CUSTOMCctrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult) { // TODO: 在此添加控件通知处理程序代码 //在该结构中,有1项变量为DWORD dwDrawStage; 绘画段, //  The following table shows the global Drawstage values. //  Value                    Description //  CDDS_POSTERASE           After the erasing cycle is complete. 擦除控件后 //  CDDS_POSTPAINT           After the painting cycle is complete.  绘制控件后
//  CDDS_PREERASE            Before the erasing cycle begins. 擦除控件前
//  CDDS_PREPAINT            Before the painting cycle begins. 绘制控件前
//  The following table shows the global Drawstage values. //  Value                    Description
//  CDDS_ITEM Indicates     that the dwItemSpec, uItemState, and lItemParam members are valid.  //  CDDS_ITEMPOSTERASE      After an item has been erased. 一个项被擦除后
//  CDDS_ITEMPOSTPAINT      After an item has been drawn.  一个项被绘制好后
//  CDDS_ITEMPREERASE       Before an item is erased.  一个项被擦除前 //  CDDS_ITEMPREPAINT       Before an item is drawn. 一个项被绘制前
//于是,这样便有了绘制时机的抉择,若是过早,则会被后来的给覆盖掉;太迟,由于先前有了一次的本身绘制,后面的自绘再增加后 //会造成闪烁,降低效率
//解决的方法是在一项被绘制前,指定*pResult为CDRF_SKIPDEFAULT,跳过默认绘制。这样就可以在绘制前这一个阶段来绘制了,不会被覆盖。 //再来说说擦除和绘制的顺序,一次绘制控件里的循环顺序,是以CDDS_PREPAINT开始,CDDS_POSTPAINT结束的 // 擦除和绘制的顺序很好理解,谁先谁后,试想,比如我要绘制一个控件。那么这个状态就是绘制前,然后再擦除。
//所以顺序是CDDS_PREPAINT->CDDS_PREERASE->CDDS_POSTERASE->CDDS_POSTPAINT LPNMCUSTOMDRAW pNMCD = reinterpret_cast(pNMHDR);
LPNMTVCUSTOMDRAW lpnmcd = (LPNMTVCUSTOMDRAW) pNMCD;
if (CDDS_PREPAINT == lpnmcd->nmcd.dwDrawStage) { *pResult = CDRF_NOTIFYITEMDRAW; return; }
else if (CDDS_ITEMPREPAINT == lpnmcd->nmcd.dwDrawStage)
{ CRect rcItem(pNMCD->rc); //item zone
POINT ptItem; ptItem.x = rcItem.left+1;
/> ptItem.y = rcItem.top+1;
UINT uFlags; HTREEITEM hItem = HitTest(ptItem,&uFlags); //item handle
if (!hItem) {
*pResult = CDRF_DODEFAULT; return; } CRect rcClient; GetClientRect(&rcClient); rcItem.left = 0;
rcItem.right = rcClient.right; rcItem.NormalizeRect();
HDC hdc = pNMCD->hdc;
CDC dc; dc.Attach(hdc);
int nSave = dc.SaveDC(); dc.FillSolidRect(&rcItem,RGB(234,245,212));<> CString strText; strText = GetItemText(hItem);
rcItem.left +=30;
dc.SetTextColor(RGB(0,0,0));
dc.SetBkMode(TRANSPARENT); CFont font;
font.CreateFont(12,
0,0,0,
FW_NORMAL, FALSE, FALSE, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_SWISS,
TEXT("宋体")); dc.SelectObject(&font);<> dc.DrawText(strText,strText.GetLength(),&rcItem,DT_VCENTER);
rcItem.left -=30; dc.RestoreDC(nSave); dc.Detach(); *pResult = CDRF_SKIPDEFAULT;<> return; } *pResult = CDRF_DODEFAULT;
return; }
.h文件
#pragma once<>
// TC_CUSTOMCctrl class TC_CUSTOMCctrl : public CTreeCtrl {
DECLARE_DYNAMIC(TC_CUSTOMCctrl)<> public: TC_CUSTOMCctrl(); virtual ~TC_CUSTOMCctrl();
protected: DECLARE_MESSAGE_MAP() public:
afx_msg void OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult); };
/>

解决方案1:

CTreeView 里可没有m_ctrl这个成员哦 CTreeCtrl &tc = GetTreeCtrl(); 这个应该是获取单实例的函数 所以你这么做是行不通的

解决方案2:

怎么不用CFormView+CTreeCtrl来替代CTreeView,不是更简单一些吗?

解决方案3:

时间不对么?是在OnInitialUpdate中子类化的么

上一篇请教,WTL环境中想搞个带按钮的listview
下一篇VC如何在CComboBox中实现类似编辑框提示。
明星图片
相关文章
《 CTREEVIEW中子类化CTREECTRL的问题》由码蚁之家搜集整理于网络,
联系邮箱:mxgf168#qq.com(#改为@)