一步一步教你实现CTreeCtrl 自绘( 二 )


正确的方法是在绘制前绘制,然后过滤点系统的默认绘制,使之不在调用 。这样我们所绘制就能看见了 。于是乎在我们的函数中多了一下几句代码 。(过滤系统的默认绘制)
if (lpnmcd ->nmcd.dwDrawStage == CDDS_PREPAINT){*pResult = CDRF_NOTIFYITEMDRAW;return;}else if (lpnmcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT){//自定义绘制*pResult = CDRF_DODEFAULT;return;}
很好,现在你已经知道了绘制的基本方法了,那么接下来你就可以加上你自己的绘制了 。
大致思路如下 。
获取当前绘制节点的信息 。如:节点状态,节点区域,节点文字等信息
需要掌握的函数:
::
BOOL (hItem,, BOOL);
返回值:
如果项是可视的则返回非零值,以及包含在中的边界矩形 。否则,返回0和没有被初始化的 。
参数:
hItem
一个tree view项的句柄 。
指向一个用来接收边界矩形的RECT结构的指针 。其中的坐标是相对于该tree view控件的左上角的 。
如果这个参数是非零值,则边界矩形值包括项的文本 。否则,它包括该项在tree view控件所占据的整个一行 。
::
(hItem ) const;
返回值:返回一个包含该项的文本的对象 。
参数:
hItem
要获取其文本的项的句柄 。
添加自己的绘制函数,如绘制图片,绘制文字等 。
::
BOOL (hItem );
返回值:
如果由hItem指定的tree项有子项则返回非零值;否则返回0 。
参数:
hItem
一个tree项的句柄 。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
如过你讨厌记住以上的这么多数据,那么恭喜你,你可以继续网下看,下面介绍另一种实现自绘的方法.通过重写消息来实现自绘,也是我最终实现自绘的方法 。因为我发现通过上面的方法来实现自绘解决不了我的问题 。闪烁和热点,也许是我自己的能力有限 。大家可以分享一下你们是如何解决我遇到的问题的 。
原理:
我们获取树形控件的数据结构和DC,然后我们自己来定义绘制的规则 。这里就可以发挥你的DIY兴趣了,想怎么画就怎么画 。
很好,下面让我们进入另一种方法的介绍
首先我们要明白消息在什么情况下触发,在win32程序中,当窗口需要重绘的时候会触发消息,还有一种情况就是我们自己手动触发,手动触发的消息有两种,第一种是调用窗口无效函数(FALSE),第2种是手动发送消息 。
明白了这个我们才知道我们以后需要窗口重绘的时候怎么处理,这里说点题外话,原来在做扫雷游戏的时候,鼠标单击之后要过20多毫秒才有反应,后来查了半天原因才发现是带用重绘的问题,因为我开始单机之后没有立即调用重绘,而是没隔50毫秒调用一次 。
我们通过重写消息就能获取当前窗口的DC,在这里我们就是整个树形控件的DC,不向上面那种方法一样只获取到树形控件某节点的DC,获取整个DC要比上面那种方法操作方便一些 。
下面是方法:
void ::()

dc(this); //这句就是获取绘制的DC
现在有了DC我们就可以绘制了,在这里我们为了让它绘制的时候不闪烁我们用双缓冲,于是乎我们有了下面的代码 。
CPaintDC dc(this); // device context for paintingGetClientRect(&m_ClientRect);CBitmap bitmap;CDC MemeDc;MemeDc.CreateCompatibleDC(&dc);bitmap.CreateCompatibleBitmap(&dc, m_ClientRect.Width(), m_ClientRect.Height());CBitmap *pOldBitmap = MemeDc.SelectObject(&bitmap);DrawBack(&MemeDc);DrawItem(&MemeDc);