soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
STreeCtrl.cpp
1//////////////////////////////////////////////////////////////////////////
2// Class Name: STreeCtrl
3// Creator: JinHui
4// Version: 2012.12.16 - 1.1 - Create
5//////////////////////////////////////////////////////////////////////////
6
7#include "souistd.h"
8#include "control/STreeCtrl.h"
9
10SNSBEGIN
11
13 : m_nItemHei(20)
14 , m_nIndent(18)
15 , m_nItemMargin(4)
16 , m_hSelItem(0)
17 , m_hHoverItem(0)
19 , m_pItemBgSkin(NULL)
20 , m_pItemSelSkin(NULL)
21 , m_pIconSkin(NULL)
22 , m_pLineSkin(GETBUILTINSKIN(SKIN_SYS_TREE_LINES))
23 , m_pToggleSkin(GETBUILTINSKIN(SKIN_SYS_TREE_TOGGLE))
24 , m_pCheckSkin(GETBUILTINSKIN(SKIN_SYS_TREE_CHECKBOX))
25 , m_crItemBg(RGBA(255, 255, 255, 255))
26 , m_crItemSelBg(RGBA(0, 0, 136, 255))
27 , m_crItemText(RGBA(0, 0, 0, 255))
28 , m_crItemSelText(RGBA(255, 255, 255, 255))
31 , m_bCheckBox(FALSE)
32 , m_bRightClickSel(FALSE)
33 , m_uItemMask(0)
34 , m_nItemOffset(0)
37 , m_bHasLines(FALSE)
38 , m_pListener(NULL)
39{
40 m_bClipClient = TRUE;
41 m_bFocusable = TRUE;
42 m_evtSet.addEvent(EVENTID(EventTCSelChanging));
43 m_evtSet.addEvent(EVENTID(EventTCSelChanged));
44 m_evtSet.addEvent(EVENTID(EventTCCheckState));
45 m_evtSet.addEvent(EVENTID(EventTCExpand));
46 m_evtSet.addEvent(EVENTID(EventTCDbClick));
47}
48
52
53////////////////////////////////////////////////////////////////////////////////////////////
54
55HSTREEITEM STreeCtrl::InsertItem(LPCTSTR lpszItem, HSTREEITEM hParent, HSTREEITEM hInsertAfter)
56{
57 return InsertItem(lpszItem, -1, -1, 0, hParent, hInsertAfter);
58}
59
60HSTREEITEM STreeCtrl::InsertItem(LPCTSTR lpszItem, int nImage, int nSelectedImage, HSTREEITEM hParent, HSTREEITEM hInsertAfter)
61{
62 return InsertItem(lpszItem, nImage, nSelectedImage, 0, hParent, hInsertAfter);
63}
64
65HSTREEITEM STreeCtrl::InsertItem(LPCTSTR lpszItem, int nImage, int nSelectedImage, LPARAM lParam, HSTREEITEM hParent, HSTREEITEM hInsertAfter)
66{
67 LPTVITEM pItemObj = new TVITEM();
68
69 pItemObj->strText = lpszItem;
70 pItemObj->nImage = nImage;
71 pItemObj->nSelectedImage = nSelectedImage;
72 pItemObj->lParam = lParam;
73
74 return InsertItem(pItemObj, hParent, hInsertAfter);
75}
76
77BOOL STreeCtrl::RemoveItem(HSTREEITEM hItem)
78{
79 if (!hItem)
80 return FALSE;
81 HSTREEITEM hParent = GetParentItem(hItem);
82
83 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
84
85 BOOL bVisible = pItem->bVisible;
86 int nItemWidth = CalcMaxItemWidth(hItem);
87 int nCheckBoxValue = pItem->nCheckBoxValue;
88 if (bVisible)
89 {
90 if (GetChildItem(hItem) && pItem->bCollapsed == FALSE)
91 {
92 SetChildrenVisible(hItem, FALSE);
93 }
94 }
95
96 if (IsAncestor(hItem, m_hHoverItem))
97 m_hHoverItem = 0;
98 if (IsAncestor(hItem, m_hSelItem))
99 m_hSelItem = 0;
100 if (IsAncestor(hItem, m_hCaptureItem))
101 m_hCaptureItem = 0;
102
103 DeleteItem(hItem);
104
105 //去掉父节点的展开标志
106 if (hParent && !GetChildItem(hParent))
107 {
108 LPTVITEM pParent = GetItem(hParent);
109 pParent->bHasChildren = FALSE;
110 pParent->bCollapsed = FALSE;
111 CalcItemContentWidth(pParent);
112 }
113
114 if (m_bCheckBox && hParent)
115 {
116 //如果父节点同为不选或全选,则不用改变状态,其他情况都需要重新判断
117 if (nCheckBoxValue != GetItem(hParent)->nCheckBoxValue || nCheckBoxValue == STVICheckBox_PartChecked)
118 CheckState(hParent);
119 }
120
121 if (bVisible)
122 {
124
125 //重新计算x最大尺寸
126 if (nItemWidth == m_nContentWidth)
128
130 }
131 return TRUE;
132}
133
135{
137 m_nVisibleItems = 0;
138 m_hSelItem = 0;
139 m_hHoverItem = 0;
140 m_hCaptureItem = 0;
141 m_nContentWidth = 0;
143}
144
145HSTREEITEM STreeCtrl::GetRootItem() const
146{
147 return GetChildItem(STVI_ROOT);
148}
149
150HSTREEITEM STreeCtrl::GetNextSiblingItem(HSTREEITEM hItem) const
151{
153}
154
155HSTREEITEM STreeCtrl::GetPrevSiblingItem(HSTREEITEM hItem) const
156{
158}
159
160HSTREEITEM STreeCtrl::GetChildItem(HSTREEITEM hItem, BOOL bFirst /* =TRUE*/) const
161{
162 return CSTree<LPTVITEM>::GetChildItem(hItem, bFirst);
163}
164
165HSTREEITEM STreeCtrl::GetParentItem(HSTREEITEM hItem) const
166{
168}
169
171{
172 return m_hSelItem;
173}
174
175BOOL STreeCtrl::GetItemText(HSTREEITEM hItem, IStringT *strText) const
176{
177 if (hItem)
178 {
179 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
180 if (pItem)
181 {
182 strText->Copy(&pItem->strText);
183 return TRUE;
184 }
185 }
186 return FALSE;
187}
188
189BOOL STreeCtrl::SetItemText(HSTREEITEM hItem, LPCTSTR lpszItem)
190{
191 if (hItem)
192 {
193 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
194 if (pItem)
195 {
196 pItem->strText = lpszItem;
197 CalcItemContentWidth(pItem); //如果新的串比原来的长,没有重新计算就会出现...
198 return TRUE;
199 }
200 }
201 return FALSE;
202}
203
204BOOL STreeCtrl::GetItemImage(HSTREEITEM hItem, int *nImage, int *nSelectedImage) const
205{
206 if (hItem)
207 {
208 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
209 if (pItem)
210 {
211 if (nImage)
212 *nImage = pItem->nImage;
213 if (nSelectedImage)
214 *nSelectedImage = pItem->nSelectedImage;
215 return TRUE;
216 }
217 }
218 return FALSE;
219}
220
221BOOL STreeCtrl::SetItemImage(HSTREEITEM hItem, int nImage, int nSelectedImage)
222{
223 if (hItem)
224 {
225 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
226 if (pItem)
227 {
228 pItem->nImage = nImage;
229 pItem->nSelectedImage = nSelectedImage;
230 return TRUE;
231 }
232 }
233 return FALSE;
234}
235
236LPARAM STreeCtrl::GetItemData(HSTREEITEM hItem) const
237{
238 if (hItem)
239 {
240 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
241 if (pItem)
242 return pItem->lParam;
243 }
244 return 0;
245}
246
247BOOL STreeCtrl::SetItemData(HSTREEITEM hItem, LPARAM lParam)
248{
249 if (hItem)
250 {
251 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
252 if (pItem)
253 {
254 pItem->lParam = lParam;
255 return TRUE;
256 }
257 }
258 return FALSE;
259}
260
261BOOL STreeCtrl::ItemHasChildren(HSTREEITEM hItem) const
262{
263 if (!hItem)
264 return FALSE;
265
266 return GetChildItem(hItem) != 0;
267}
268
269int STreeCtrl::GetCheckState(HSTREEITEM hItem) const
270{
271 if (!m_bCheckBox)
272 return 0;
273
274 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
275 return pItem->nCheckBoxValue;
276}
277
278BOOL STreeCtrl::SetCheckState(HSTREEITEM hItem, BOOL bCheck)
279{
280 if (!m_bCheckBox)
281 return FALSE;
282
283 int nCheck = bCheck ? STVICheckBox_Checked : STVICheckBox_UnChecked;
284
285 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
286 if (pItem->nCheckBoxValue != nCheck)
287 {
288 pItem->nCheckBoxValue = nCheck;
289
290 //置子孙结点
292 SetChildrenState(hItem, nCheck);
293
294 //检查父结点状态
296
297 Invalidate();
298 }
299
300 return TRUE;
301}
302
303BOOL STreeCtrl::Expand(HSTREEITEM hItem, UINT nCode)
304{
305 BOOL bRet = FALSE;
307 {
308 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
309 if (nCode == TVE_COLLAPSE && !pItem->bCollapsed)
310 {
311 pItem->bCollapsed = TRUE;
312 SetChildrenVisible(hItem, FALSE);
313 bRet = TRUE;
314 }
315 if (nCode == TVE_EXPAND && pItem->bCollapsed)
316 {
317 pItem->bCollapsed = FALSE;
318 SetChildrenVisible(hItem, TRUE);
319 bRet = TRUE;
320 }
321 if (nCode == TVE_TOGGLE)
322 {
323 pItem->bCollapsed = !pItem->bCollapsed;
324 SetChildrenVisible(hItem, !pItem->bCollapsed);
325 bRet = TRUE;
326 }
327 if (bRet)
328 {
331 }
332 }
333 return bRet;
334}
335
336BOOL STreeCtrl::EnsureVisible(HSTREEITEM hItem)
337{
338 if (!VerifyItem(hItem))
339 return FALSE;
340
341 LPTVITEM pItem = GetItem(hItem);
342 if (!pItem->bVisible)
343 {
344 HSTREEITEM hParent = GetParentItem(hItem);
345 while (hParent)
346 {
347 LPTVITEM pParent = GetItem(hParent);
348 if (pParent->bCollapsed)
349 Expand(hParent, TVE_EXPAND);
350 hParent = GetParentItem(hParent);
351 }
352 }
353 int iVisible = GetItemShowIndex(hItem);
354 int yOffset = iVisible * m_nItemHei;
355 if (yOffset + m_nItemHei > m_siVer.nPos + m_rcClient.Height())
356 {
357 SetScrollPos(TRUE, yOffset + m_nItemHei - m_rcClient.Height(), TRUE);
358 }
359 else if (yOffset < m_siVer.nPos)
360 {
361 SetScrollPos(TRUE, yOffset, TRUE);
362 }
363 return TRUE;
364}
365
367{
368 OnScroll(TRUE, SB_PAGEUP, 0);
369}
370
372{
373 OnScroll(TRUE, SB_PAGEDOWN, 0);
374}
375
376////////////////////////////////////////////////////////////////////////////////////////////
377
379{
380 if (!xmlNode)
381 return FALSE;
382
384 ItemLayout();
385
386 SXmlNode xmlItem = xmlNode.child(L"item");
387
388 if (xmlItem)
389 LoadBranch(STVI_ROOT, xmlItem);
390
391 return TRUE;
392}
393
394void STreeCtrl::LoadBranch(HSTREEITEM hParent, SXmlNode xmlItem)
395{
396 while (xmlItem)
397 {
398 HSTREEITEM hItem = InsertItem(xmlItem, hParent);
399
400 SXmlNode xmlChild = xmlItem.child(L"item");
401 if (xmlChild)
402 {
403 LoadBranch(hItem, xmlChild);
404 Expand(hItem, xmlItem.attribute(L"expand").as_bool(true) ? TVE_EXPAND : TVE_COLLAPSE);
405 }
406 xmlItem = xmlItem.next_sibling(L"item");
407 }
408}
409
410void STreeCtrl::LoadItemAttribute(SXmlNode xmlItem, LPTVITEM pItem)
411{
412 for (SXmlAttr attr = xmlItem.first_attribute(); attr; attr = attr.next_attribute())
413 {
414 if (!_wcsicmp(attr.name(), L"text"))
415 pItem->strText = S_CW2T(attr.value());
416 else if (!_wcsicmp(attr.name(), L"img"))
417 pItem->nImage = attr.as_int(0);
418 else if (!_wcsicmp(attr.name(), L"selImg"))
419 pItem->nSelectedImage = attr.as_int(0);
420 else if (!_wcsicmp(attr.name(), L"data"))
421 pItem->lParam = attr.as_uint(0);
422 }
423}
424
425HSTREEITEM STreeCtrl::InsertItem(LPTVITEM pItemObj, HSTREEITEM hParent, HSTREEITEM hInsertAfter)
426{
427 SASSERT(pItemObj);
428
429 CRect rcClient;
430 GetClientRect(rcClient);
431
432 pItemObj->nLevel = GetItemLevel(hParent) + 1;
433
434 BOOL bCheckState = FALSE;
435
436 if (hParent != STVI_ROOT)
437 {
438 LPTVITEM pParentItem = GetItem(hParent);
439 if (pParentItem->bCollapsed || !pParentItem->bVisible)
440 pItemObj->bVisible = FALSE;
441
442 if (pParentItem->nCheckBoxValue != pItemObj->nCheckBoxValue)
443 bCheckState = TRUE;
444
445 if (!GetChildItem(hParent) && !pParentItem->bHasChildren)
446 {
447 pParentItem->bHasChildren = TRUE;
448 CalcItemContentWidth(pParentItem);
449 }
450 }
451
452 CalcItemContentWidth(pItemObj);
453
454 HSTREEITEM hRet = CSTree<LPTVITEM>::InsertItem(pItemObj, hParent, hInsertAfter);
455 pItemObj->hItem = hRet;
456 OnInsertItem(pItemObj);
457 if (bCheckState)
458 CheckState(hParent);
459 if (pItemObj->bVisible)
460 {
462
463 int nViewWidth = CalcItemWidth(pItemObj);
464 m_nContentWidth = smax(nViewWidth, m_nContentWidth);
466 }
467
468 return hRet;
469}
470
471HSTREEITEM STreeCtrl::InsertItem(SXmlNode xmlItem, HSTREEITEM hParent /*=STVI_ROOT*/, HSTREEITEM hInsertAfter /*=STVI_LAST*/)
472{
473 LPTVITEM pItemObj = new TVITEM();
474
475 LoadItemAttribute(xmlItem, pItemObj);
476 return InsertItem(pItemObj, hParent, hInsertAfter);
477}
478
479BOOL STreeCtrl::IsAncestor(HSTREEITEM hItem1, HSTREEITEM hItem2)
480{
481 while (hItem2)
482 {
483 if (hItem2 == hItem1)
484 return TRUE;
485 hItem2 = GetParentItem(hItem2);
486 }
487 return FALSE;
488}
489
490void STreeCtrl::SetChildrenVisible(HSTREEITEM hItem, BOOL bVisible)
491{
492 HSTREEITEM hChild = GetChildItem(hItem);
493 while (hChild)
494 {
495 LPTVITEM pItem = GetItem(hChild);
496 pItem->bVisible = bVisible;
497 m_nVisibleItems += bVisible ? 1 : -1;
498 if (!pItem->bCollapsed)
499 SetChildrenVisible(hChild, bVisible);
500 hChild = GetNextSiblingItem(hChild);
501 }
502}
503
504void STreeCtrl::SetChildrenState(HSTREEITEM hItem, int nCheckValue)
505{
506 HSTREEITEM hChildItem = CSTree<LPTVITEM>::GetChildItem(hItem);
507 while (hChildItem)
508 {
509 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hChildItem);
510 pItem->nCheckBoxValue = nCheckValue;
511 SetChildrenState(hChildItem, nCheckValue);
512 hChildItem = CSTree<LPTVITEM>::GetNextSiblingItem(hChildItem);
513 }
514}
515
516//子孙结点状态一致返回TRUE, 否则返回FALSE
517BOOL STreeCtrl::CheckChildrenState(HSTREEITEM hItem, BOOL bCheck)
518{
519 HSTREEITEM hChildItem = CSTree<LPTVITEM>::GetChildItem(hItem);
520 while (hChildItem)
521 {
522 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hChildItem);
523
524 int nCheckValue = bCheck ? STVICheckBox_Checked : STVICheckBox_UnChecked;
525 //当前结点不一致立即返回
526 if (pItem->nCheckBoxValue != nCheckValue)
527 return FALSE;
528 //检查子结点不一致立即返回
529 else if (CheckChildrenState(hChildItem, bCheck) == FALSE)
530 return FALSE;
531
532 //检查子结点兄弟结点
533 hChildItem = CSTree<LPTVITEM>::GetNextSiblingItem(hChildItem);
534 }
535 return TRUE;
536}
537
538void STreeCtrl::CheckState(HSTREEITEM hItem)
539{
540 if (hItem)
541 {
542 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
543 int nOldState = pItem->nCheckBoxValue;
544 pItem->nCheckBoxValue = STVICheckBox_UnChecked;
545 bool bHasUnChecked = false;
546 bool bHasChecked = false;
547 bool bHasPartChecked = false;
548
549 HSTREEITEM hChild = GetChildItem(hItem);
550 while (hChild)
551 {
552 LPTVITEM pChild = CSTree<LPTVITEM>::GetItem(hChild);
553 if (pChild->nCheckBoxValue == STVICheckBox_UnChecked)
554 bHasUnChecked = true;
555 else if (pChild->nCheckBoxValue == STVICheckBox_Checked)
556 bHasChecked = true;
557 else if (pChild->nCheckBoxValue == STVICheckBox_PartChecked)
558 bHasPartChecked = true;
559
560 if (bHasPartChecked || (bHasUnChecked && bHasChecked))
561 break; //已确定半选,提前结束循环
562 hChild = GetNextSiblingItem(hChild);
563 }
564
565 if (bHasPartChecked || (bHasUnChecked && bHasChecked)) //子节点有半选,则父节点也要半选
566 pItem->nCheckBoxValue = STVICheckBox_PartChecked;
567 else if (bHasChecked && !bHasUnChecked) //子节点都是全选,则父节点也是全选
568 pItem->nCheckBoxValue = STVICheckBox_Checked;
569
570 if (pItem->nCheckBoxValue != nOldState)
572 }
573}
574
576{
577 int nOffset = 0;
578 CSize sizeSkin;
579
580 m_uItemMask = 0;
581 m_rcToggle.SetRect(0, 0, 0, 0);
582 m_rcCheckBox.SetRect(0, 0, 0, 0);
583 m_rcIcon.SetRect(0, 0, 0, 0);
584
585 //计算位置
587 {
589 CSize szToggle;
590 if (m_bHasLines)
591 {
592 szToggle = CSize(m_nIndent, m_nIndent);
593 }
594 else
595 {
596 szToggle = m_pToggleSkin->GetSkinSize();
597 }
598 m_rcToggle.SetRect(nOffset, (m_nItemHei - szToggle.cy) / 2, nOffset + szToggle.cx, m_nItemHei - (m_nItemHei - szToggle.cy) / 2);
599 nOffset += szToggle.cx;
600 }
601
603 {
605 sizeSkin = m_pCheckSkin->GetSkinSize();
606 m_rcCheckBox.SetRect(nOffset, (m_nItemHei - sizeSkin.cy) / 2, nOffset + sizeSkin.cx, m_nItemHei - (m_nItemHei - sizeSkin.cy) / 2);
607 nOffset += sizeSkin.cx;
608 }
609
610 if (m_pIconSkin)
611 {
613 sizeSkin = m_pIconSkin->GetSkinSize();
614 m_rcIcon.SetRect(nOffset, (m_nItemHei - sizeSkin.cy) / 2, nOffset + sizeSkin.cx, m_nItemHei - (m_nItemHei - sizeSkin.cy) / 2);
615 nOffset += sizeSkin.cx;
616 }
617
618 m_nItemOffset = nOffset;
619}
620
622{
624 GETRENDERFACTORY->CreateRenderTarget(&pRT, 0, 0);
625 BeforePaintEx(pRT);
626
627 int nTestDrawMode = GetTextAlign() & ~(DT_CENTER | DT_RIGHT | DT_VCENTER | DT_BOTTOM);
628
629 CRect rcTest;
630 DrawText(pRT, pItem->strText, pItem->strText.GetLength(), rcTest, nTestDrawMode | DT_CALCRECT);
631
632 pItem->nContentWidth = rcTest.Width() + m_nItemOffset + 2 * m_nItemMargin;
633}
634
635int STreeCtrl::CalcMaxItemWidth(HSTREEITEM hItem)
636{
637 int nItemWidth = 0, nChildrenWidth = 0;
638
639 if (hItem != STVI_ROOT)
640 {
641 LPTVITEM pItem = GetItem(hItem);
642 if (pItem->bVisible)
643 nItemWidth = CalcItemWidth(pItem);
644 else
645 return 0;
646 }
647 HSTREEITEM hChild = GetChildItem(hItem);
648 while (hChild)
649 {
650 nChildrenWidth = CalcMaxItemWidth(hChild);
651 if (nChildrenWidth > nItemWidth)
652 nItemWidth = nChildrenWidth;
653
654 hChild = GetNextSiblingItem(hChild);
655 }
656
657 return nItemWidth;
658}
659
664
665int STreeCtrl::GetItemShowIndex(HSTREEITEM hItemObj)
666{
667 int iVisible = -1;
668 HSTREEITEM hItem = GetNextItem(STVI_ROOT);
669 while (hItem)
670 {
671 LPTVITEM pItem = GetItem(hItem);
672 if (pItem->bVisible)
673 iVisible++;
674 if (hItem == hItemObj)
675 {
676 return iVisible;
677 }
678 if (pItem->bCollapsed)
679 { //跳过被折叠的项
680 HSTREEITEM hChild = GetChildItem(hItem, FALSE);
681 while (hChild)
682 {
683 hItem = hChild;
684 hChild = GetChildItem(hItem, FALSE);
685 }
686 }
687 hItem = GetNextItem(hItem);
688 }
689 return -1;
690}
691
692BOOL STreeCtrl::GetItemRect(LPTVITEM pItemObj, CRect &rcItem)
693{
694 if (pItemObj->bVisible == FALSE)
695 return FALSE;
696
697 CRect rcClient;
698 GetClientRect(rcClient);
699 int iFirstVisible = m_siVer.nPos / m_nItemHei;
700 int nPageItems = (rcClient.Height() + m_nItemHei - 1) / m_nItemHei + 1;
701
702 int iVisible = -1;
703 HSTREEITEM hItem = CSTree<LPTVITEM>::GetNextItem(STVI_ROOT);
704 while (hItem)
705 {
706 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
707 if (pItem->bVisible)
708 iVisible++;
709 if (iVisible > iFirstVisible + nPageItems)
710 break;
711 if (iVisible >= iFirstVisible && pItem == pItemObj)
712 {
713 CRect rcRet(m_nIndent * pItemObj->nLevel, 0, rcClient.Width(), m_nItemHei);
714 rcRet.OffsetRect(rcClient.left - m_siHoz.nPos, rcClient.top - m_siVer.nPos + iVisible * m_nItemHei);
715 rcItem = rcRet;
716 return TRUE;
717 }
718 if (pItem->bCollapsed)
719 { //跳过被折叠的项
720 HSTREEITEM hChild = GetChildItem(hItem, FALSE);
721 while (hChild)
722 {
723 hItem = hChild;
724 hChild = GetChildItem(hItem, FALSE);
725 }
726 }
727 hItem = CSTree<LPTVITEM>::GetNextItem(hItem);
728 }
729 return FALSE;
730}
731
732//自动修改pt的位置为相对当前项的偏移量
733HSTREEITEM STreeCtrl::HitTest(CPoint &pt)
734{
735 CRect rcClient;
736 GetClientRect(&rcClient);
737 CPoint pt2 = pt;
738 pt2.y -= rcClient.top - m_siVer.nPos;
739 int iItem = pt2.y / m_nItemHei;
740 if (iItem >= m_nVisibleItems)
741 return 0;
742
743 HSTREEITEM hRet = 0;
744
745 int iVisible = -1;
746 HSTREEITEM hItem = CSTree<LPTVITEM>::GetNextItem(STVI_ROOT);
747 while (hItem)
748 {
749 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
750 if (pItem->bVisible)
751 iVisible++;
752 if (iVisible == iItem)
753 {
754 CRect rcItem(m_nIndent * pItem->nLevel, 0, rcClient.Width(), m_nItemHei);
755 rcItem.OffsetRect(rcClient.left - m_siHoz.nPos, rcClient.top - m_siVer.nPos + iVisible * m_nItemHei);
756 pt -= rcItem.TopLeft();
757 hRet = hItem;
758 break;
759 }
760 if (pItem->bCollapsed)
761 { //跳过被折叠的项
762 HSTREEITEM hChild = GetChildItem(hItem, FALSE);
763 while (hChild)
764 {
765 hItem = hChild;
766 hChild = GetChildItem(hItem, FALSE);
767 }
768 }
769 hItem = CSTree<LPTVITEM>::GetNextItem(hItem);
770 }
771 return hRet;
772}
773
774void STreeCtrl::RedrawItem(HSTREEITEM hItem)
775{
776 if (!IsVisible(TRUE))
777 return;
778 CRect rcClient;
779 GetClientRect(rcClient);
780
781 int iFirstVisible = m_siVer.nPos / m_nItemHei;
782 int nPageItems = (rcClient.Height() + m_nItemHei - 1) / m_nItemHei + 1;
783 int iItem = GetItemShowIndex(hItem);
784 if (iItem != -1 && iItem >= iFirstVisible && iItem < iFirstVisible + nPageItems)
785 {
786 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
787
788 CRect rcItem(0, 0, CalcItemWidth(pItem), m_nItemHei);
789 rcItem.OffsetRect(rcClient.left - m_siHoz.nPos, rcClient.top + m_nItemHei * iItem - m_siVer.nPos);
790 InvalidateRect(&rcItem);
791 }
792}
793
794void STreeCtrl::DrawItem(IRenderTarget *pRT, const CRect &rc, HSTREEITEM hItem)
795{
796 BOOL bTextColorChanged = FALSE;
797 ;
798 COLORREF crOldText = RGBA(0xFF, 0xFF, 0xFF, 0xFF);
799 CRect rcItemBg;
800 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
801
802 pRT->OffsetViewportOrg(rc.left + pItem->nLevel * m_nIndent, rc.top, NULL);
803
804 rcItemBg.SetRect(m_nItemOffset + m_nItemMargin, 0, pItem->nContentWidth, m_nItemHei);
805 if (rcItemBg.right > rc.Width() - pItem->nLevel * m_nIndent)
806 rcItemBg.right = rc.Width() - pItem->nLevel * m_nIndent;
807 //绘制背景
808 if (hItem == m_hSelItem)
809 {
810 if (m_pItemSelSkin != NULL)
811 m_pItemSelSkin->DrawByIndex(pRT, rcItemBg, 0);
812 else if (CR_INVALID != m_crItemSelBg)
813 pRT->FillSolidRect(rcItemBg, m_crItemSelBg);
814
815 if (CR_INVALID != m_crItemSelText)
816 {
817 bTextColorChanged = TRUE;
818 crOldText = pRT->SetTextColor(m_crItemSelText);
819 }
820 }
821 else
822 {
823 if (CR_INVALID != m_crItemText)
824 {
825 bTextColorChanged = TRUE;
826 crOldText = pRT->SetTextColor(m_crItemText);
827 }
828 }
829
830 if (pItem->bHasChildren && STVIMask_Toggle == (m_uItemMask & STVIMask_Toggle) && !m_bHasLines)
831 {
832 int nImage = SState2Index::GetDefIndex(pItem->dwToggleState, false);
833 if (!pItem->bCollapsed)
834 nImage += 3;
835 m_pToggleSkin->DrawByIndex(pRT, m_rcToggle, nImage);
836 }
837
839 {
840 int nImage = SState2Index::GetDefIndex(pItem->dwCheckBoxState, false);
841 if (pItem->nCheckBoxValue == STVICheckBox_Checked)
842 nImage += 3;
843 else if (pItem->nCheckBoxValue == STVICheckBox_PartChecked)
844 nImage += 6;
845 m_pCheckSkin->DrawByIndex(pRT, m_rcCheckBox, nImage);
846 }
847
848 if (STVIMask_Icon == (m_uItemMask & STVIMask_Icon) && (pItem->nSelectedImage != -1 || pItem->nImage != -1))
849 {
850 if (pItem->nSelectedImage != -1 && hItem == m_hSelItem)
851 m_pIconSkin->DrawByIndex(pRT, m_rcIcon, pItem->nSelectedImage);
852 else
853 m_pIconSkin->DrawByIndex(pRT, m_rcIcon, pItem->nImage);
854 }
855
856 UINT align = DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS;
857 rcItemBg.OffsetRect(m_nItemMargin, 0);
858 pRT->DrawText(pItem->strText, -1, rcItemBg, align);
859
860 if (bTextColorChanged)
861 pRT->SetTextColor(crOldText);
862
863 pRT->OffsetViewportOrg(-rc.left - pItem->nLevel * m_nIndent, -rc.top, NULL);
864}
865
866void STreeCtrl::DrawLines(IRenderTarget *pRT, const CRect &rc, HSTREEITEM hItem)
867{
868 if (m_nIndent == 0 || !m_pLineSkin || !m_bHasLines)
869 return;
870 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
871 SList<HSTREEITEM> lstParent;
872 HSTREEITEM hParent = GetParentItem(hItem);
873 while (hParent)
874 {
875 lstParent.AddHead(hParent);
876 hParent = GetParentItem(hParent);
877 }
878 // draw parent flags.
879 enum
880 {
881 plus,
882 plus_join,
883 plus_bottom,
884 minus,
885 minus_join,
886 minus_bottom,
887 line,
888 line_join,
889 line_bottom,
890 line_root,
891 }; // 10 line states
892 CRect rcLine = rc;
893 rcLine.right = rcLine.left + m_nIndent;
894 SPOSITION pos = lstParent.GetHeadPosition();
895 while (pos)
896 {
897 HSTREEITEM hParent = lstParent.GetNext(pos);
898 HSTREEITEM hNextSibling = GetNextSiblingItem(hParent);
899 if (hNextSibling)
900 {
901 m_pLineSkin->DrawByIndex(pRT, rcLine, line);
902 }
903 rcLine.OffsetRect(m_nIndent, 0);
904 }
905 bool hasNextSibling = GetNextSiblingItem(hItem) != 0;
906 bool hasPervSibling = GetPrevSiblingItem(hItem) != 0;
907 bool hasChild = GetChildItem(hItem) != 0;
908 bool hasParent = GetParentItem(hItem) != 0;
909 int iLine = -1;
910 if (hasChild)
911 { // test if is collapsed
912 if (pItem->bCollapsed)
913 {
914 if (!hasParent && !hasPervSibling) // no parent
915 iLine = plus;
916 else if (hasNextSibling)
917 iLine = plus_join;
918 else
919 iLine = plus_bottom;
920 }
921 else
922 {
923 if (!hasParent && !hasPervSibling) // no parent
924 iLine = minus;
925 else if (hasNextSibling)
926 iLine = minus_join;
927 else
928 iLine = minus_bottom;
929 }
930 }
931 else
932 {
933 if (hasNextSibling)
934 {
935 if (!hasParent && !hasPervSibling)
936 iLine = line_root;
937 else
938 iLine = line_join;
939 }
940 else
941 iLine = line_bottom;
942 }
943 m_pLineSkin->DrawByIndex(pRT, rcLine, iLine);
944}
945
946int STreeCtrl::ItemHitTest(HSTREEITEM hItem, CPoint &pt) const
947{
948 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
949 int nHitTestBtn = STVIBtn_None;
950
951 if (STVIMask_Toggle == (m_uItemMask & STVIMask_Toggle) && pItem->bHasChildren && m_rcToggle.PtInRect(pt))
952 nHitTestBtn = STVIBtn_Toggle;
953 else if (STVIMask_CheckBox == (m_uItemMask & STVIMask_CheckBox) && m_rcCheckBox.PtInRect(pt))
954 nHitTestBtn = STVIBtn_CheckBox;
955
956 return nHitTestBtn;
957}
958
959void STreeCtrl::ModifyToggleState(HSTREEITEM hItem, DWORD dwStateAdd, DWORD dwStateRemove)
960{
961 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
962
963 pItem->dwToggleState |= dwStateAdd;
964 pItem->dwToggleState &= ~dwStateRemove;
965
966 CRect rcItem, rcUpdate = m_rcToggle;
967 if (GetItemRect(pItem, rcItem))
968 {
969 rcUpdate.OffsetRect(rcItem.left, rcItem.top);
970 InvalidateRect(rcUpdate);
971 }
972}
973
974void STreeCtrl::ModifyChekcBoxState(HSTREEITEM hItem, DWORD dwStateAdd, DWORD dwStateRemove)
975{
976 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
977
978 pItem->dwCheckBoxState |= dwStateAdd;
979 pItem->dwCheckBoxState &= ~dwStateRemove;
980
981 CRect rcItem, rcUpdate = m_rcCheckBox;
982 if (GetItemRect(pItem, rcItem))
983 {
984 rcUpdate.OffsetRect(rcItem.left, rcItem.top);
985 InvalidateRect(rcUpdate);
986 }
987}
988
989void STreeCtrl::ItemLButtonDown(HSTREEITEM hItem, UINT nFlags, CPoint pt)
990{
991 int nHitTestBtn = ItemHitTest(hItem, pt);
992 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
993
994 //清除原有pushdown按钮
995 if (m_nItemPushDownBtn != nHitTestBtn)
996 {
997 if (m_nItemPushDownBtn == STVIBtn_Toggle && WndState_PushDown == (pItem->dwToggleState & WndState_PushDown))
998 {
1000 }
1001
1002 if (m_nItemPushDownBtn == STVIBtn_CheckBox && WndState_PushDown == (pItem->dwCheckBoxState & WndState_PushDown))
1003 {
1005 }
1006
1007 m_nItemPushDownBtn = nHitTestBtn;
1008 }
1009
1010 //置新pushdown按钮
1012 {
1013 if (m_nItemPushDownBtn == STVIBtn_Toggle && WndState_PushDown != (pItem->dwToggleState & WndState_PushDown))
1014 {
1016 Expand(pItem->hItem, TVE_TOGGLE);
1017 }
1018
1019 if (m_nItemPushDownBtn == STVIBtn_CheckBox && WndState_PushDown != (pItem->dwCheckBoxState & WndState_PushDown))
1020 {
1021 BOOL bCheck = pItem->nCheckBoxValue == STVICheckBox_Checked ? FALSE : TRUE;
1023 SetCheckState(pItem->hItem, bCheck);
1024 }
1025 }
1026}
1027
1028void STreeCtrl::ItemLButtonUp(HSTREEITEM hItem, UINT nFlags, CPoint pt)
1029{
1030 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
1031
1033 {
1034 if (m_nItemPushDownBtn == STVIBtn_Toggle && WndState_PushDown == (pItem->dwToggleState & WndState_PushDown))
1035 {
1037 }
1038
1039 if (m_nItemPushDownBtn == STVIBtn_CheckBox && WndState_PushDown == (pItem->dwCheckBoxState & WndState_PushDown))
1040 {
1042 EventTCCheckState evt(this);
1043 evt.hItem = hItem;
1044 evt.uCheckState = pItem->dwCheckBoxState;
1045 FireEvent(&evt);
1046 }
1047
1049 }
1050}
1051
1052void STreeCtrl::ItemLButtonDbClick(HSTREEITEM hItem, UINT nFlags, CPoint pt)
1053{
1054 if (!hItem)
1055 {
1056 return;
1057 }
1058 int nHitTestBtn = ItemHitTest(hItem, pt);
1059 if (nHitTestBtn == STVIBtn_CheckBox)
1060 ItemLButtonDown(hItem, nFlags, pt);
1061 //产生双击事件 add by zhaosheng
1062 EventTCDbClick dbClick(this);
1063 dbClick.bCancel = FALSE;
1064 dbClick.hItem = hItem;
1065 FireEvent(&dbClick);
1066 if (!dbClick.bCancel)
1067 {
1068 Expand(hItem, TVE_TOGGLE);
1069 }
1070}
1071
1072void STreeCtrl::ItemMouseMove(HSTREEITEM hItem, UINT nFlags, CPoint pt)
1073{
1074 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
1075
1076 int nHitTestBtn = ItemHitTest(hItem, pt);
1077
1078 if (nHitTestBtn != m_nItemHoverBtn)
1079 {
1080 if (m_nItemHoverBtn == STVIBtn_Toggle && WndState_Hover == (pItem->dwToggleState & WndState_Hover))
1081 {
1083 }
1084
1085 if (m_nItemHoverBtn == STVIBtn_CheckBox && WndState_Hover == (pItem->dwCheckBoxState & WndState_Hover))
1086 {
1088 }
1089
1090 m_nItemHoverBtn = nHitTestBtn;
1091 }
1092
1094 {
1095 if (m_nItemHoverBtn == STVIBtn_Toggle && WndState_Hover != (pItem->dwToggleState & WndState_Hover))
1096 {
1098 }
1099
1100 if (m_nItemHoverBtn == STVIBtn_CheckBox && WndState_Hover != (pItem->dwCheckBoxState & WndState_Hover))
1101 {
1103 }
1104 }
1105}
1106
1107void STreeCtrl::ItemMouseLeave(HSTREEITEM hItem)
1108{
1109 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
1110
1112 {
1113 if (m_nItemHoverBtn == STVIBtn_Toggle && WndState_Hover == (pItem->dwToggleState & WndState_Hover))
1114 {
1116 }
1117
1118 if (m_nItemHoverBtn == STVIBtn_CheckBox && WndState_Hover == (pItem->dwCheckBoxState & WndState_Hover))
1119 {
1121 }
1122
1124 }
1125}
1126
1127////////////////////////////////////////////////////////////////////////////////////////////
1128
1130{
1132 __baseCls::OnDestroy();
1133}
1134
1136{
1137 if (IsUpdateLocked())
1138 return;
1139
1140 CRect rcClient;
1141 SPainter painter;
1142 BeforePaint(pRT, painter);
1143
1144 GetClientRect(rcClient);
1145 int iFirstVisible = m_siVer.nPos / m_nItemHei;
1146 int nPageItems = (m_rcClient.Height() + m_nItemHei - 1) / m_nItemHei + 1;
1147
1148 int iVisible = -1;
1149 HSTREEITEM hItem = CSTree<LPTVITEM>::GetNextItem(STVI_ROOT);
1150 while (hItem)
1151 {
1152 LPTVITEM pItem = CSTree<LPTVITEM>::GetItem(hItem);
1153 if (pItem->bVisible)
1154 iVisible++;
1155 if (iVisible > iFirstVisible + nPageItems)
1156 break;
1157 if (iVisible >= iFirstVisible)
1158 {
1159 CRect rcItem(0, 0, CalcItemWidth(pItem), m_nItemHei);
1160 rcItem.OffsetRect(rcClient.left - m_siHoz.nPos, rcClient.top - m_siVer.nPos + iVisible * m_nItemHei);
1161 DrawLines(pRT, rcItem, hItem);
1162 DrawItem(pRT, rcItem, hItem);
1163 }
1164 if (pItem->bCollapsed)
1165 { //跳过被折叠的项
1166 HSTREEITEM hChild = GetChildItem(hItem, FALSE);
1167 while (hChild)
1168 {
1169 hItem = hChild;
1170 hChild = GetChildItem(hItem, FALSE);
1171 }
1172 }
1173 hItem = CSTree<LPTVITEM>::GetNextItem(hItem);
1174 }
1175 AfterPaint(pRT, painter);
1176}
1177
1178void STreeCtrl::OnLButtonDown(UINT nFlags, CPoint pt)
1179{
1180 __baseCls::OnLButtonDown(nFlags, pt);
1181 m_hHoverItem = HitTest(pt);
1182
1184 SelectItem(m_hHoverItem, FALSE);
1185
1186 if (m_hHoverItem)
1187 {
1189 ItemLButtonDown(m_hHoverItem, nFlags, pt);
1190 }
1191}
1192
1193void STreeCtrl::OnRButtonDown(UINT nFlags, CPoint pt)
1194{
1195 CPoint pt2 = pt;
1196 if (!m_bRightClickSel)
1197 {
1198 __baseCls::OnRButtonDown(nFlags, pt2);
1199 return;
1200 }
1201
1202 m_hHoverItem = HitTest(pt);
1203
1205 SelectItem(m_hHoverItem, FALSE);
1206
1207 __baseCls::OnRButtonDown(nFlags, pt2);
1208}
1209
1210void STreeCtrl::OnLButtonUp(UINT nFlags, CPoint pt)
1211{
1212 __baseCls::OnLButtonUp(nFlags, pt);
1213
1214 m_hHoverItem = HitTest(pt);
1215
1216 if (m_hCaptureItem)
1217 {
1218 ItemLButtonUp(m_hCaptureItem, nFlags, pt);
1219 m_hCaptureItem = 0;
1220 return;
1221 }
1222
1223 if (m_hHoverItem)
1224 ItemLButtonUp(m_hHoverItem, nFlags, pt);
1225}
1226
1227void STreeCtrl::OnLButtonDbClick(UINT nFlags, CPoint pt)
1228{
1229 m_hHoverItem = HitTest(pt);
1230 ItemLButtonDbClick(m_hHoverItem, nFlags, pt);
1231}
1232
1233void STreeCtrl::OnMouseMove(UINT nFlags, CPoint pt)
1234{
1235 HSTREEITEM hHitTest = HitTest(pt);
1236
1237 if (hHitTest != m_hHoverItem)
1238 {
1239 if (m_hHoverItem)
1241
1242 m_hHoverItem = hHitTest;
1243 }
1244 if (m_hHoverItem)
1245 ItemMouseMove(m_hHoverItem, nFlags, pt);
1246}
1247
1249{
1250 if (m_hHoverItem)
1251 {
1253 m_hHoverItem = 0;
1254 }
1255}
1256
1257BOOL STreeCtrl::SelectItem(HSTREEITEM hItem, BOOL bEnsureVisible /*=TRUE*/)
1258{
1259 if (!VerifyItem(hItem))
1260 return FALSE;
1261
1262 EventTCSelChanging evt1(this);
1263 evt1.bCancel = FALSE;
1264 evt1.hOldSel = m_hSelItem;
1265 evt1.hNewSel = hItem;
1266
1267 FireEvent(&evt1);
1268 if (evt1.bCancel)
1269 return FALSE;
1270
1271 if (bEnsureVisible)
1272 EnsureVisible(hItem);
1273
1274 EventTCSelChanged evt(this);
1275 evt.hOldSel = m_hSelItem;
1276 evt.hNewSel = hItem;
1277
1278 m_hSelItem = hItem;
1279
1280 FireEvent(&evt);
1281
1282 if (evt.hOldSel)
1283 {
1284 RedrawItem(evt.hOldSel);
1285 }
1286
1287 if (m_hSelItem)
1288 {
1290 }
1291
1292 return TRUE;
1293}
1294
1295int STreeCtrl::CalcItemWidth(const LPTVITEM pItemObj)
1296{
1297 return pItemObj->nContentWidth + pItemObj->nLevel * m_nIndent;
1298}
1299
1300void STreeCtrl::SortChildren(HSTREEITEM hItem, FunTreeSortCallback sortFunc, void *pCtx)
1301{
1302 m_hHoverItem = 0;
1303 m_hCaptureItem = 0;
1304 CSTree<LPTVITEM>::SortChildren(hItem, sortFunc, pCtx);
1305}
1306
1307BOOL STreeCtrl::VerifyItem(HSTREEITEM hItem) const
1308{
1309 if (!hItem)
1310 return FALSE;
1311#ifdef _DEBUG
1312 HSTREEITEM hRoot = CSTree<LPTVITEM>::GetRootItem(hItem);
1314 {
1316 }
1317 return hRoot == GetRootItem();
1318#endif
1319 return TRUE;
1320}
1321
1322void STreeCtrl::OnNodeFree(LPTVITEM &pItemData)
1323{
1324 if (m_pListener)
1325 {
1326 m_pListener->OnDeleteItem(this, pItemData->hItem, pItemData->lParam);
1327 }
1328 delete pItemData;
1329}
1330
1331void STreeCtrl::OnInsertItem(LPTVITEM &pItemData)
1332{
1333 if (m_pListener)
1334 {
1335 m_pListener->OnInsertItem(this, pItemData->hItem);
1336 }
1337}
1338
1340{
1341 m_pListener = pListener;
1342}
1343
1345{
1346 CRect rcClient;
1347 SWindow::GetClientRect(&rcClient);
1348
1349 CSize size = rcClient.Size();
1351
1352 m_wBarVisible = SSB_NULL; //关闭滚动条
1353
1354 if (size.cy < szView.cy || (size.cy < szView.cy + GetSbWidth() && size.cx < szView.cx))
1355 {
1356 //需要纵向滚动条
1357 m_wBarVisible |= SSB_VERT;
1358 m_siVer.nMin = 0;
1359 m_siVer.nMax = szView.cy - 1;
1360 m_siVer.nPage = size.cy;
1361 if (m_siVer.nPos + (int)m_siVer.nPage > m_siVer.nMax)
1362 {
1363 m_siVer.nPos = m_siVer.nMax - m_siVer.nPage;
1364 }
1365 if (size.cx < szView.cx + GetSbWidth())
1366 {
1367 //需要横向滚动条
1368 m_wBarVisible |= SSB_HORZ;
1369 m_siVer.nPage = size.cy - GetSbWidth() > 0 ? size.cy - GetSbWidth() : 0;
1370
1371 m_siHoz.nMin = 0;
1372 m_siHoz.nMax = szView.cx - 1;
1373 m_siHoz.nPage = size.cx - GetSbWidth() > 0 ? size.cx - GetSbWidth() : 0;
1374 if (m_siHoz.nPos + (int)m_siHoz.nPage > m_siHoz.nMax)
1375 {
1376 m_siHoz.nPos = m_siHoz.nMax - m_siHoz.nPage;
1377 }
1378 }
1379 else
1380 {
1381 //不需要横向滚动条
1382 m_siHoz.nPage = size.cx;
1383 m_siHoz.nMin = 0;
1384 m_siHoz.nMax = m_siHoz.nPage - 1;
1385 m_siHoz.nPos = 0;
1386 }
1387 }
1388 else
1389 {
1390 //不需要纵向滚动条
1391 m_siVer.nPage = size.cy;
1392 m_siVer.nMin = 0;
1393 m_siVer.nMax = size.cy - 1;
1394 m_siVer.nPos = 0;
1395
1396 if (size.cx < szView.cx)
1397 {
1398 //需要横向滚动条
1399 m_wBarVisible |= SSB_HORZ;
1400 m_siHoz.nMin = 0;
1401 m_siHoz.nMax = szView.cx - 1;
1402 m_siHoz.nPage = size.cx;
1403 if (m_siHoz.nPos + (int)m_siHoz.nPage > m_siHoz.nMax)
1404 {
1405 m_siHoz.nPos = m_siHoz.nMax - m_siHoz.nPage;
1406 }
1407 }
1408 //不需要横向滚动条
1409 else
1410 {
1411 m_siHoz.nPage = size.cx;
1412 m_siHoz.nMin = 0;
1413 m_siHoz.nMax = m_siHoz.nPage - 1;
1414 m_siHoz.nPos = 0;
1415 }
1416 }
1417
1418 SetScrollPos(TRUE, m_siVer.nPos, TRUE);
1419 SetScrollPos(FALSE, m_siHoz.nPos, TRUE);
1420
1421 SSendMessage(WM_NCCALCSIZE);
1422 Invalidate();
1423}
1424
1425void STreeCtrl::OnSize(UINT nType, CSize size)
1426{
1427 __baseCls::OnSize(nType, size);
1429}
1430
1431HSTREEITEM STreeCtrl::GetNextItem(HSTREEITEM hItem) const
1432{
1433 return CSTree<LPTVITEM>::GetNextItem(hItem);
1434}
1435
1436SNSEND
#define STVI_ROOT
Definition STree.h:43
Definition of the STreeCtrl class.
@ STVICheckBox_PartChecked
Definition STreeCtrl.h:39
@ STVICheckBox_Checked
Definition STreeCtrl.h:38
@ STVICheckBox_UnChecked
Definition STreeCtrl.h:37
@ STVIBtn_None
Definition STreeCtrl.h:48
@ STVIBtn_Toggle
Definition STreeCtrl.h:49
@ STVIBtn_CheckBox
Definition STreeCtrl.h:50
@ STVIMask_Icon
Definition STreeCtrl.h:28
@ STVIMask_Toggle
Definition STreeCtrl.h:26
@ STVIMask_CheckBox
Definition STreeCtrl.h:27
@ WndState_Hover
Definition SWnd.h:76
@ WndState_PushDown
Definition SWnd.h:77
static T GetItem(HSTREEITEM hItem)
Get the item data.
Definition STree.h:307
HSTREEITEM GetChildItem(HSTREEITEM hItem, BOOL bFirst=TRUE) const
Get the child item.
Definition STree.h:212
static HSTREEITEM GetParentItem(HSTREEITEM hItem)
Get the parent item.
Definition STree.h:166
HSTREEITEM GetNextItem(HSTREEITEM hItem) const
Get the next item in the tree.
Definition STree.h:538
virtual void DeleteItem(HSTREEITEM hItem)
Definition STree.h:253
static int GetItemLevel(HSTREEITEM hItem)
Definition STree.h:178
HSTREEITEM InsertItem(const T &data, HSTREEITEM hParent=((HSTREEITEM) 0xFFFF0000), HSTREEITEM hInsertAfter=((HSTREEITEM) 0xFFFF0002))
Insert a new item.
Definition STree.h:348
void DeleteAllItems()
Definition STree.h:127
static HSTREEITEM GetNextSiblingItem(HSTREEITEM hItem)
Get the next sibling item.
Definition STree.h:142
static HSTREEITEM GetPrevSiblingItem(HSTREEITEM hItem)
Get the previous sibling item.
Definition STree.h:154
static HSTREEITEM GetRootItem(HSTREEITEM hItem)
Get the root item of the specified node.
Definition STree.h:196
void SortChildren(HSTREEITEM hItem, int(__cdecl *funSort)(void *, const void *, const void *), void *pCtx)
Sort the children of a node.
Definition STree.h:604
Smart pointer class for managing COM-style reference-counted objects.
Helper class for painting.
Definition SWnd.h:178
virtual CRect GetClientRect() const
Gets the client rectangle.
Definition SPanel.cpp:368
int GetSbWidth() const
Gets the width of the scrollbar.
Definition SPanel.cpp:650
virtual BOOL OnScroll(BOOL bVertical, UINT uCode, int nPos)
Handles scroll events.
Definition SPanel.cpp:517
static int GetDefIndex(DWORD dwState, bool checkAsPushdown=false)
Gets the default index for a given state.
HSTREEITEM HitTest(CPoint &pt)
Performs a hit test on the tree view.
void UpdateScrollBar()
Updates the scroll bars.
COLORREF m_crItemSelBg
Background color of selected items.
Definition STreeCtrl.h:777
BOOL SetItemData(HSTREEITEM hItem, LPARAM lParam) OVERRIDE
Sets the application-defined data of an item.
void ModifyToggleState(HSTREEITEM hItem, DWORD dwStateAdd, DWORD dwStateRemove)
Modifies the toggle state of an item.
BOOL EnsureVisible(HSTREEITEM hItem) OVERRIDE
Ensures an item is visible.
void SortChildren(HSTREEITEM hItem, FunTreeSortCallback sortFunc, void *pCtx) OVERRIDE
Sorts the children of an item.
SAutoRefPtr< ISkinObj > m_pToggleSkin
Skin for the toggle buttons.
Definition STreeCtrl.h:757
BOOL m_bRightClickSel
Flag indicating if right-click selection is enabled.
Definition STreeCtrl.h:732
HSTREEITEM GetRootItem() SCONST OVERRIDE
Gets the root item of the tree.
int m_nVisibleItems
Number of visible items.
Definition STreeCtrl.h:667
virtual void DrawLines(IRenderTarget *pRT, const CRect &rc, HSTREEITEM hItem)
Draws lines for an item.
void ItemLButtonDown(HSTREEITEM hItem, UINT nFlags, CPoint pt)
Handles the left mouse button down event for an item.
virtual void DrawItem(IRenderTarget *pRT, const CRect &rc, HSTREEITEM hItem)
Draws an item.
BOOL RemoveItem(HSTREEITEM hItem) OVERRIDE
Removes an item from the tree.
Definition STreeCtrl.cpp:77
IListener * m_pListener
Listener for tree view events.
Definition STreeCtrl.h:737
SAutoRefPtr< ISkinObj > m_pItemBgSkin
Skin for the background of items.
Definition STreeCtrl.h:742
COLORREF m_crItemBg
Background color of items.
Definition STreeCtrl.h:772
STreeCtrl()
Constructor for STreeCtrl.
Definition STreeCtrl.cpp:12
int m_nItemOffset
Offset for item positioning.
Definition STreeCtrl.h:682
BOOL GetItemRect(LPTVITEM pItem, CRect &rcItem)
Gets the rectangle of an item.
virtual ~STreeCtrl()
Destructor for STreeCtrl.
Definition STreeCtrl.cpp:49
BOOL SetItemText(HSTREEITEM hItem, LPCTSTR lpszItem) OVERRIDE
Sets the text of an item.
int m_nItemHoverBtn
Button currently hovered.
Definition STreeCtrl.h:702
CRect m_rcToggle
Rectangle for the toggle button.
Definition STreeCtrl.h:687
BOOL GetItemImage(HSTREEITEM hItem, int *nImage, int *nSelectedImage) SCONST OVERRIDE
Gets the images of an item.
void PageUp()
Handles the page up action.
void RemoveAllItems() OVERRIDE
Removes all items from the tree.
void ModifyChekcBoxState(HSTREEITEM hItem, DWORD dwStateAdd, DWORD dwStateRemove)
Modifies the checkbox state of an item.
CRect m_rcCheckBox
Rectangle for the checkbox.
Definition STreeCtrl.h:692
virtual int CalcItemWidth(const LPTVITEM pItem)
Calculates the width of an item.
int m_nItemHei
Height of each item.
Definition STreeCtrl.h:712
BOOL CheckChildrenState(HSTREEITEM hItem, BOOL bCheck)
Checks the state of an item's children.
int m_nItemMargin
Margin around each item.
Definition STreeCtrl.h:722
void OnLButtonDown(UINT nFlags, CPoint pt)
Handles the left mouse button down event.
virtual void OnNodeFree(LPTVITEM &pItemData)
Frees the memory associated with an item.
HSTREEITEM GetNextItem(HSTREEITEM hItem) SCONST OVERRIDE
Gets the next item.
BOOL SetItemImage(HSTREEITEM hItem, int nImage, int nSelectedImage) OVERRIDE
Sets the images of an item.
HSTREEITEM GetNextSiblingItem(HSTREEITEM hItem) SCONST OVERRIDE
Gets the next sibling item.
BOOL GetItemText(HSTREEITEM hItem, IStringT *strText) SCONST OVERRIDE
Gets the text of an item.
int ItemHitTest(HSTREEITEM hItem, CPoint &pt) const
Performs a hit test on an item.
CRect m_rcIcon
Rectangle for the icon.
Definition STreeCtrl.h:697
BOOL VerifyItem(HSTREEITEM hItem) const
Verifies if an item is valid.
HSTREEITEM GetParentItem(HSTREEITEM hItem) SCONST OVERRIDE
Gets the parent item.
BOOL m_bCheckBox
Flag indicating if checkboxes are enabled.
Definition STreeCtrl.h:727
void ItemMouseLeave(HSTREEITEM hItem)
Handles the mouse leave event for an item.
void ItemLButtonDbClick(HSTREEITEM hItem, UINT nFlags, CPoint pt)
Handles the left mouse button double-click event for an item.
void RedrawItem(HSTREEITEM hItem)
Redraws an item.
void OnMouseMove(UINT nFlags, CPoint pt)
Handles the mouse move event.
virtual void OnInsertItem(LPTVITEM &pItemData)
Handles the insertion of an item.
void SetChildrenState(HSTREEITEM hItem, int nCheckValue)
Sets the check state of an item's children.
void OnLButtonDbClick(UINT nFlags, CPoint pt)
Handles the left mouse button double-click event.
void ItemMouseMove(HSTREEITEM hItem, UINT nFlags, CPoint pt)
Handles the mouse move event for an item.
int GetItemShowIndex(HSTREEITEM hItemObj)
Gets the index of an item in the visible list.
BOOL IsAncestor(HSTREEITEM hItem1, HSTREEITEM hItem2)
Checks if one item is an ancestor of another.
HSTREEITEM m_hCaptureItem
Handle to the item that has capture.
Definition STreeCtrl.h:662
void PageDown()
Handles the page down action.
int m_nContentWidth
Total content width of the tree.
Definition STreeCtrl.h:672
SAutoRefPtr< ISkinObj > m_pItemSelSkin
Skin for the selected background of items.
Definition STreeCtrl.h:747
BOOL ItemHasChildren(HSTREEITEM hItem) SCONST OVERRIDE
Checks if an item has children.
void OnPaint(IRenderTarget *pRT)
Handles the paint event.
int GetCheckState(HSTREEITEM hItem) SCONST OVERRIDE
Gets the check state of an item.
void OnDestroy()
Handles the destruction of the tree control.
virtual void CalcItemContentWidth(LPTVITEM pItem)
Calculates the content width of an item.
BOOL SelectItem(HSTREEITEM hItem, BOOL bEnsureVisible=TRUE) OVERRIDE
Selects an item.
HSTREEITEM m_hHoverItem
Handle to the item under the hover state.
Definition STreeCtrl.h:657
virtual void LoadItemAttribute(SXmlNode xmlNode, LPTVITEM pItem)
Loads attributes for an item from an XML node.
HSTREEITEM GetChildItem(HSTREEITEM hItem, BOOL bFirst=TRUE) SCONST OVERRIDE
Gets a child item.
int m_nItemPushDownBtn
Button currently pushed down.
Definition STreeCtrl.h:707
UINT m_uItemMask
Mask for item attributes.
Definition STreeCtrl.h:677
void OnMouseLeave()
Handles the mouse leave event.
HSTREEITEM m_hSelItem
Handle to the selected item.
Definition STreeCtrl.h:652
COLORREF m_crItemText
Text color of items.
Definition STreeCtrl.h:782
SAutoRefPtr< ISkinObj > m_pCheckSkin
Skin for the checkboxes.
Definition STreeCtrl.h:762
BOOL m_bHasLines
Flag indicating if lines are drawn between items.
Definition STreeCtrl.h:792
SAutoRefPtr< ISkinObj > m_pLineSkin
Skin for the lines.
Definition STreeCtrl.h:767
void OnLButtonUp(UINT nFlags, CPoint pt)
Handles the left mouse button up event.
virtual void LoadBranch(HSTREEITEM hParent, SXmlNode xmlNode)
Loads a branch of items from an XML node.
virtual BOOL CreateChildren(SXmlNode xmlNode)
Creates child windows from an XML node.
virtual void ItemLayout()
Performs layout calculations for items.
HSTREEITEM GetSelectedItem() SCONST OVERRIDE
Gets the selected item.
void ItemLButtonUp(HSTREEITEM hItem, UINT nFlags, CPoint pt)
Handles the left mouse button up event for an item.
HSTREEITEM InsertItem(LPCTSTR lpszItem, int nImage, int nSelectedImage, LPARAM lParam, HSTREEITEM hParent=STVI_ROOT, HSTREEITEM hInsertAfter=STVI_LAST) OVERRIDE
Inserts a new item into the tree.
Definition STreeCtrl.cpp:65
int m_nIndent
Indentation between levels.
Definition STreeCtrl.h:717
void SetChildrenVisible(HSTREEITEM hItem, BOOL bVisible)
Sets the visibility of an item's children.
virtual int CalcMaxItemWidth(HSTREEITEM hItem)
Calculates the maximum width of an item and its children.
BOOL Expand(HSTREEITEM hItem, UINT nCode=TVE_EXPAND) OVERRIDE
Expands or collapses an item.
void OnRButtonDown(UINT nFlags, CPoint pt)
Handles the right mouse button down event.
void OnSize(UINT nType, CSize size)
Handles the size event.
LPARAM GetItemData(HSTREEITEM hItem) SCONST OVERRIDE
Gets the application-defined data of an item.
SAutoRefPtr< ISkinObj > m_pIconSkin
Skin for the icons.
Definition STreeCtrl.h:752
void CheckState(HSTREEITEM hItem)
Updates the check state of an item.
virtual void UpdateContentWidth()
Updates the content width of the tree.
HSTREEITEM GetPrevSiblingItem(HSTREEITEM hItem) SCONST OVERRIDE
Gets the previous sibling item.
void SetListener(IListener *pListener)
Sets the listener for tree view events.
COLORREF m_crItemSelText
Text color of selected items.
Definition STreeCtrl.h:787
BOOL SetCheckState(HSTREEITEM hItem, BOOL bCheck) OVERRIDE
Sets the check state of an item.
BOOL FireEvent(IEvtArgs *evt) OVERRIDE
Fires an event.
Definition Swnd.cpp:1540
UINT GetTextAlign() const
Retrieves the text alignment of the window.
Definition Swnd.cpp:218
BOOL IsVisible(BOOL bCheckParent=FALSE) SCONST OVERRIDE
Checks if the window is visible.
Definition Swnd.cpp:646
virtual CRect GetClientRect() const
Retrieves the client rectangle of the window.
Definition Swnd.cpp:243
LRESULT SSendMessage(UINT uMsg, WPARAM wParam=0, LPARAM lParam=0, BOOL *pbMsgHandled=NULL) OVERRIDE
Sends a message to the window.
Definition Swnd.cpp:364
virtual void BeforePaint(IRenderTarget *pRT, SPainter &painter)
Prepare rendering environment.
Definition Swnd.cpp:1755
void InvalidateRect(LPCRECT lprect) OVERRIDE
Invalidates a specific rectangle area of the window.
Definition Swnd.cpp:1444
BOOL m_bFocusable
Definition SWnd.h:2609
BOOL IsUpdateLocked(BOOL bCheckParent=FALSE) SCONST OVERRIDE
Checks if updates to the window are locked.
Definition Swnd.cpp:1503
virtual void AfterPaint(IRenderTarget *pRT, SPainter &painter)
Restore rendering environment.
Definition Swnd.cpp:1776
virtual void DrawText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)
Draw text content.
Definition Swnd.cpp:1968
void Invalidate() OVERRIDE
Invalidates the entire window.
Definition Swnd.cpp:1437
SEventSet m_evtSet
Definition SWnd.h:2581
void BeforePaintEx(IRenderTarget *pRT)
Prepares the drawing environment for the current window's RenderTarget, starting from the top-level w...
Definition Swnd.cpp:1767
BOOL m_bClipClient
Definition SWnd.h:2607
Class representing an XML attribute.
Definition SXml.h:20
bool as_bool(bool def=false) const
Converts the attribute value to a boolean.
Definition SXml.cpp:120
Class representing an XML node.
Definition SXml.h:352
SXmlNode next_sibling() const
Gets the next sibling node in the children list of the parent node.
Definition SXml.cpp:393
SXmlAttr first_attribute() const
Gets the first attribute of the node.
Definition SXml.cpp:373
SXmlAttr attribute(const wchar_t *name, bool bCaseSensitive=false) const
Gets the attribute with the specified name.
Definition SXml.cpp:428
SXmlNode child(const wchar_t *name, bool bCaseSensitive=false) const
Gets the child node, attribute, or next/previous sibling with the specified name.
Definition SXml.cpp:423
Interface for rendering target objects.
Definition SRender-i.h:1440
HRESULT DrawText(LPCTSTR pszText, int cchLen, LPRECT pRc, UINT uFormat) PURE
Draw text within a rectangle.
HRESULT FillSolidRect(LPCRECT pRect, COLORREF cr) PURE
Fill a rectangle with a solid color.
HRESULT OffsetViewportOrg(int xOff, int yOff, LPPOINT lpPoint=NULL) PURE
Offset the viewport origin.
COLORREF SetTextColor(COLORREF color) PURE
Sets the current text color.
Listener interface for tree view events.
Definition STreeCtrl.h:113
Bitfield structure for font style attributes.