1 /********************************************************************
3 * Copyright (c) 2002 Sven Wiegand <mail@sven-wiegand.de>
5 * You can use this and modify this in any way you want,
6 * BUT LEAVE THIS HEADER INTACT.
8 * Redistribution is appreciated.
18 *********************************************************************/
22 #include "TreePropSheet.h"
23 #include "PropPageFrameDefault.h"
24 #include "HighColorTab.hpp"
29 static char THIS_FILE
[] = __FILE__
;
34 namespace TreePropSheet
37 //-------------------------------------------------------------------
38 // class CTreePropSheet
39 //-------------------------------------------------------------------
41 BEGIN_MESSAGE_MAP(CTreePropSheet
, CPropertySheet
)
42 //{{AFX_MSG_MAP(CTreePropSheet)
45 ON_MESSAGE(PSM_ADDPAGE
, OnAddPage
)
46 ON_MESSAGE(PSM_REMOVEPAGE
, OnRemovePage
)
47 ON_MESSAGE(PSM_SETCURSEL
, OnSetCurSel
)
48 ON_MESSAGE(PSM_SETCURSELID
, OnSetCurSelId
)
49 ON_MESSAGE(PSM_ISDIALOGMESSAGE
, OnIsDialogMessage
)
51 ON_NOTIFY(TVN_SELCHANGINGA
, s_unPageTreeId
, OnPageTreeSelChanging
)
52 ON_NOTIFY(TVN_SELCHANGINGW
, s_unPageTreeId
, OnPageTreeSelChanging
)
53 ON_NOTIFY(TVN_SELCHANGEDA
, s_unPageTreeId
, OnPageTreeSelChanged
)
54 ON_NOTIFY(TVN_SELCHANGEDW
, s_unPageTreeId
, OnPageTreeSelChanged
)
57 IMPLEMENT_DYNAMIC(CTreePropSheet
, CPropertySheet
)
59 const UINT
CTreePropSheet::s_unPageTreeId
= 0x7EEE;
61 CTreePropSheet::CTreePropSheet()
63 m_bPageTreeSelChangedActive(FALSE
),
64 m_bTreeViewMode(TRUE
),
65 m_bPageCaption(FALSE
),
67 m_nPageTreeWidth(150),
68 m_pwndPageTree(nullptr),
73 CTreePropSheet::CTreePropSheet(UINT nIDCaption
, CWnd
* pParentWnd
, UINT iSelectPage
)
74 : CPropertySheet(nIDCaption
, pParentWnd
, iSelectPage
),
75 m_bPageTreeSelChangedActive(FALSE
),
76 m_bTreeViewMode(TRUE
),
77 m_bPageCaption(FALSE
),
79 m_nPageTreeWidth(150),
80 m_pwndPageTree(nullptr),
86 CTreePropSheet::CTreePropSheet(LPCTSTR pszCaption
, CWnd
* pParentWnd
, UINT iSelectPage
)
87 : CPropertySheet(pszCaption
, pParentWnd
, iSelectPage
),
88 m_bPageTreeSelChangedActive(FALSE
),
89 m_bTreeViewMode(TRUE
),
90 m_bPageCaption(FALSE
),
92 m_nPageTreeWidth(150),
93 m_pwndPageTree(nullptr),
99 CTreePropSheet::~CTreePropSheet()
104 /////////////////////////////////////////////////////////////////////
107 BOOL
CTreePropSheet::SetTreeViewMode(BOOL bTreeViewMode
/* = TRUE */, BOOL bPageCaption
/* = FALSE */, BOOL bTreeImages
/* = FALSE */)
109 if (IsWindow(m_hWnd
))
111 // needs to becalled, before the window has been created
116 m_bTreeViewMode
= bTreeViewMode
;
119 m_bPageCaption
= bPageCaption
;
120 m_bTreeImages
= bTreeImages
;
127 BOOL
CTreePropSheet::SetTreeWidth(int nWidth
)
129 if (IsWindow(m_hWnd
))
131 // needs to be called, before the window is created.
136 m_nPageTreeWidth
= nWidth
;
142 void CTreePropSheet::SetEmptyPageText(LPCTSTR lpszEmptyPageText
)
144 m_strEmptyPageMessage
= lpszEmptyPageText
;
148 DWORD
CTreePropSheet::SetEmptyPageTextFormat(DWORD dwFormat
)
150 DWORD dwPrevFormat
= m_pFrame
->GetMsgFormat();
151 m_pFrame
->SetMsgFormat(dwFormat
);
156 BOOL
CTreePropSheet::SetTreeDefaultImages(CImageList
*pImages
)
158 if (pImages
->GetImageCount() != 2)
164 if (m_DefaultImages
.GetSafeHandle())
165 m_DefaultImages
.DeleteImageList();
166 m_DefaultImages
.Create(pImages
);
168 // update, if necessary
169 if (IsWindow(m_hWnd
))
176 BOOL
CTreePropSheet::SetTreeDefaultImages(UINT unBitmapID
, int cx
, COLORREF crMask
)
178 if (m_DefaultImages
.GetSafeHandle())
179 m_DefaultImages
.DeleteImageList();
180 if (!m_DefaultImages
.Create(unBitmapID
, cx
, 0, crMask
))
183 if (m_DefaultImages
.GetImageCount() != 2)
185 m_DefaultImages
.DeleteImageList();
193 CTreeCtrl
* CTreePropSheet::GetPageTreeControl()
195 return m_pwndPageTree
;
199 /////////////////////////////////////////////////////////////////////
202 BOOL
CTreePropSheet::SetPageIcon(CPropertyPage
*pPage
, HICON hIcon
)
204 pPage
->m_psp
.dwFlags
|= PSP_USEHICON
;
205 pPage
->m_psp
.hIcon
= hIcon
;
210 BOOL
CTreePropSheet::SetPageIcon(CPropertyPage
*pPage
, UINT unIconId
)
212 HICON hIcon
= AfxGetApp()->LoadIcon(unIconId
);
216 return SetPageIcon(pPage
, hIcon
);
220 BOOL
CTreePropSheet::SetPageIcon(CPropertyPage
*pPage
, CImageList
&Images
, int nImage
)
222 HICON hIcon
= Images
.ExtractIcon(nImage
);
226 return SetPageIcon(pPage
, hIcon
);
230 BOOL
CTreePropSheet::DestroyPageIcon(CPropertyPage
*pPage
)
232 if (!pPage
|| !(pPage
->m_psp
.dwFlags
&PSP_USEHICON
) || !pPage
->m_psp
.hIcon
)
235 DestroyIcon(pPage
->m_psp
.hIcon
);
236 pPage
->m_psp
.dwFlags
&= ~PSP_USEHICON
;
237 pPage
->m_psp
.hIcon
= nullptr;
243 /////////////////////////////////////////////////////////////////////
244 // Overridable implementation helpers
246 CString
CTreePropSheet::GenerateEmptyPageMessage(LPCTSTR lpszEmptyPageMessage
, LPCTSTR lpszCaption
)
249 strMsg
.Format(lpszEmptyPageMessage
, lpszCaption
);
254 CTreeCtrl
* CTreePropSheet::CreatePageTreeObject()
256 return new CTreeCtrl
;
260 CPropPageFrame
* CTreePropSheet::CreatePageFrame()
262 return new CPropPageFrameDefault
;
266 /////////////////////////////////////////////////////////////////////
267 // Implementation helpers
269 void CTreePropSheet::MoveChildWindows(int nDx
, int nDy
)
271 CWnd
*pWnd
= GetWindow(GW_CHILD
);
275 pWnd
->GetWindowRect(rect
);
276 rect
.OffsetRect(nDx
, nDy
);
277 ScreenToClient(rect
);
278 pWnd
->MoveWindow(rect
);
280 pWnd
= pWnd
->GetNextWindow();
285 void CTreePropSheet::RefillPageTree()
287 if (!IsWindow(m_hWnd
))
290 m_pwndPageTree
->DeleteAllItems();
292 CTabCtrl
*pTabCtrl
= GetTabControl();
293 if (!IsWindow(pTabCtrl
->GetSafeHwnd()))
299 const int nPageCount
= pTabCtrl
->GetItemCount();
301 // rebuild image list
304 for (int i
= m_Images
.GetImageCount()-1; i
>= 0; --i
)
308 CImageList
*pPageImages
= pTabCtrl
->GetImageList();
311 for (int nImage
= 0; nImage
< pPageImages
->GetImageCount(); ++nImage
)
313 HICON hIcon
= pPageImages
->ExtractIcon(nImage
);
319 // add default images
320 if (m_DefaultImages
.GetSafeHandle())
324 // add default images
325 hIcon
= m_DefaultImages
.ExtractIcon(0);
331 hIcon
= m_DefaultImages
.ExtractIcon(1);
340 for (int nPage
= 0; nPage
< nPageCount
; ++nPage
)
342 // Get title and image of the page
346 ti
.mask
= TCIF_TEXT
|TCIF_IMAGE
;
347 ti
.cchTextMax
= MAX_PATH
;
348 ti
.pszText
= strPagePath
.GetBuffer(ti
.cchTextMax
+ 1);
353 pTabCtrl
->GetItem(nPage
, &ti
);
354 strPagePath
.ReleaseBuffer();
356 // Create an item in the tree for the page
357 HTREEITEM hItem
= CreatePageTreeItem(ti
.pszText
);
361 m_pwndPageTree
->SetItemData(hItem
, nPage
);
366 int nImage
= ti
.iImage
;
367 if (nImage
< 0 || nImage
>= m_Images
.GetImageCount())
368 nImage
= m_DefaultImages
.GetSafeHandle()? m_Images
.GetImageCount()-1 : -1;
370 m_pwndPageTree
->SetItemImage(hItem
, nImage
, nImage
);
372 m_pwndPageTree
->Expand(m_pwndPageTree
->GetParentItem(hItem
), TVE_EXPAND
);
378 HTREEITEM
CTreePropSheet::CreatePageTreeItem(LPCTSTR lpszPath
, HTREEITEM hParent
/* = TVI_ROOT */)
380 CString
strPath(lpszPath
);
381 CString
strTopMostItem(SplitPageTreePath(strPath
));
383 // Check if an item with the given text does already exist
384 HTREEITEM hItem
= nullptr;
385 HTREEITEM hChild
= m_pwndPageTree
->GetChildItem(hParent
);
388 if (m_pwndPageTree
->GetItemText(hChild
) == strTopMostItem
)
393 hChild
= m_pwndPageTree
->GetNextItem(hChild
, TVGN_NEXT
);
396 // If item with that text does not already exist, create a new one
399 hItem
= m_pwndPageTree
->InsertItem(strTopMostItem
, hParent
);
400 m_pwndPageTree
->SetItemData(hItem
, (DWORD_PTR
)-1);
401 if (!strPath
.IsEmpty() && m_bTreeImages
&& m_DefaultImages
.GetSafeHandle())
403 m_pwndPageTree
->SetItemImage(hItem
, m_Images
.GetImageCount()-2, m_Images
.GetImageCount()-2);
411 if (strPath
.IsEmpty())
414 return CreatePageTreeItem(strPath
, hItem
);
418 CString
CTreePropSheet::SplitPageTreePath(CString
&strRest
)
420 int nSeparatorPos
= 0;
421 #pragma warning(push)
422 #pragma warning(disable: 4127) // conditional expression constant
425 nSeparatorPos
= strRest
.Find(L
"::", nSeparatorPos
);
426 if (nSeparatorPos
== -1)
428 CString
strItem(strRest
);
432 else if (nSeparatorPos
>0)
434 // if there is an odd number of backslashes infront of the
435 // separator, than do not interpret it as separator
436 int nBackslashCount
= 0;
437 for (int nPos
= nSeparatorPos
-1; nPos
>= 0 && strRest
[nPos
] == L
'\\'; --nPos
, ++nBackslashCount
);
438 if (nBackslashCount
%2 == 0)
446 CString
strItem(strRest
.Left(nSeparatorPos
));
447 strItem
.Replace(L
"\\::", L
"::");
448 strItem
.Replace(L
"\\\\", L
"\\");
449 strRest
= strRest
.Mid(nSeparatorPos
+2);
454 BOOL
CTreePropSheet::KillActiveCurrentPage()
456 HWND hCurrentPage
= PropSheet_GetCurrentPageHwnd(m_hWnd
);
457 if (!IsWindow(hCurrentPage
))
463 // Check if the current page is really active (if page is invisible
464 // an virtual empty page is the active one.
465 if (!::IsWindowVisible(hCurrentPage
))
468 // Try to deactivate current page
470 pshn
.hdr
.code
= PSN_KILLACTIVE
;
471 pshn
.hdr
.hwndFrom
= m_hWnd
;
472 pshn
.hdr
.idFrom
= GetDlgCtrlID();
474 if (::SendMessage(hCurrentPage
, WM_NOTIFY
, pshn
.hdr
.idFrom
, (LPARAM
)&pshn
))
475 // current page does not allow page change
479 ::ShowWindow(hCurrentPage
, SW_HIDE
);
485 HTREEITEM
CTreePropSheet::GetPageTreeItem(int nPage
, HTREEITEM hRoot
/* = TVI_ROOT */)
487 // Special handling for root case
488 if (hRoot
== TVI_ROOT
)
489 hRoot
= m_pwndPageTree
->GetNextItem(TVI_ROOT
, TVGN_ROOT
);
492 if (nPage
< 0 || nPage
>= GetPageCount())
504 // we are performing a simple linear search here, because we are
505 // expecting only little data
506 HTREEITEM hItem
= hRoot
;
509 if ((signed)m_pwndPageTree
->GetItemData(hItem
) == nPage
)
511 if (m_pwndPageTree
->ItemHasChildren(hItem
))
513 HTREEITEM hResult
= GetPageTreeItem(nPage
, m_pwndPageTree
->GetNextItem(hItem
, TVGN_CHILD
));
518 hItem
= m_pwndPageTree
->GetNextItem(hItem
, TVGN_NEXT
);
521 // we've found nothing, if we arrive here
526 BOOL
CTreePropSheet::SelectPageTreeItem(int nPage
)
528 HTREEITEM hItem
= GetPageTreeItem(nPage
);
532 return m_pwndPageTree
->SelectItem(hItem
);
536 BOOL
CTreePropSheet::SelectCurrentPageTreeItem()
538 CTabCtrl
*pTab
= GetTabControl();
539 if (!IsWindow(pTab
->GetSafeHwnd()))
542 return SelectPageTreeItem(pTab
->GetCurSel());
546 void CTreePropSheet::UpdateCaption()
548 HWND hPage
= PropSheet_GetCurrentPageHwnd(GetSafeHwnd());
549 BOOL bRealPage
= IsWindow(hPage
) && ::IsWindowVisible(hPage
);
550 HTREEITEM hItem
= m_pwndPageTree
->GetSelectedItem();
554 CString strCaption
= m_pwndPageTree
->GetItemText(hItem
);
556 // if empty page, then update empty page message
558 m_pFrame
->SetMsgText(GenerateEmptyPageMessage(m_strEmptyPageMessage
, strCaption
));
560 // if no captions are displayed, cancel here
561 if (!m_pFrame
->GetShowCaption())
564 // get tab control, to the the images from
565 CTabCtrl
*pTabCtrl
= GetTabControl();
566 if (!IsWindow(pTabCtrl
->GetSafeHwnd()))
574 // get image from tree
576 m_pwndPageTree
->GetItemImage(hItem
, nImage
, nImage
);
577 HICON hIcon
= m_Images
.ExtractIcon(nImage
);
578 m_pFrame
->SetCaption(strCaption
, hIcon
);
584 // get image from hidden (original) tab provided by the original
586 CImageList
*pImages
= pTabCtrl
->GetImageList();
590 ti
.mask
= TCIF_IMAGE
;
592 HICON hIcon
= nullptr;
593 if (pTabCtrl
->GetItem((int)m_pwndPageTree
->GetItemData(hItem
), &ti
))
594 hIcon
= pImages
->ExtractIcon(ti
.iImage
);
596 m_pFrame
->SetCaption(strCaption
, hIcon
);
601 m_pFrame
->SetCaption(strCaption
);
604 m_pFrame
->SetCaption(strCaption
);
608 void CTreePropSheet::ActivatePreviousPage()
610 if (!IsWindow(m_hWnd
))
613 if (!IsWindow(m_pwndPageTree
->GetSafeHwnd()))
615 // normal tab property sheet. Simply use page index
616 int nPageIndex
= GetActiveIndex();
617 if (nPageIndex
<0 || nPageIndex
>=GetPageCount())
620 int nPrevIndex
= (nPageIndex
==0)? GetPageCount()-1 : nPageIndex
-1;
621 SetActivePage(nPrevIndex
);
625 // property sheet with page tree.
626 // we need a more sophisticated handling here, than simply using
627 // the page index, because we won't skip empty pages.
628 // so we have to walk the page tree
629 HTREEITEM hItem
= m_pwndPageTree
->GetSelectedItem();
634 HTREEITEM hPrevItem
= nullptr;
635 if ((hPrevItem
=m_pwndPageTree
->GetPrevSiblingItem(hItem
))!=0)
637 while (m_pwndPageTree
->ItemHasChildren(hPrevItem
))
639 hPrevItem
= m_pwndPageTree
->GetChildItem(hPrevItem
);
640 while (m_pwndPageTree
->GetNextSiblingItem(hPrevItem
))
641 hPrevItem
= m_pwndPageTree
->GetNextSiblingItem(hPrevItem
);
645 hPrevItem
=m_pwndPageTree
->GetParentItem(hItem
);
649 // no prev item, so cycle to the last item
650 hPrevItem
= m_pwndPageTree
->GetRootItem();
652 #pragma warning(push)
653 #pragma warning(disable: 4127) // conditional expression constant
656 while (m_pwndPageTree
->GetNextSiblingItem(hPrevItem
))
657 hPrevItem
= m_pwndPageTree
->GetNextSiblingItem(hPrevItem
);
659 if (m_pwndPageTree
->ItemHasChildren(hPrevItem
))
660 hPrevItem
= m_pwndPageTree
->GetChildItem(hPrevItem
);
668 m_pwndPageTree
->SelectItem(hPrevItem
);
673 void CTreePropSheet::ActivateNextPage()
675 if (!IsWindow(m_hWnd
))
678 if (!IsWindow(m_pwndPageTree
->GetSafeHwnd()))
680 // normal tab property sheet. Simply use page index
681 int nPageIndex
= GetActiveIndex();
682 if (nPageIndex
<0 || nPageIndex
>=GetPageCount())
685 int nNextIndex
= (nPageIndex
==GetPageCount()-1)? 0 : nPageIndex
+1;
686 SetActivePage(nNextIndex
);
690 // property sheet with page tree.
691 // we need a more sophisticated handling here, than simply using
692 // the page index, because we won't skip empty pages.
693 // so we have to walk the page tree
694 HTREEITEM hItem
= m_pwndPageTree
->GetSelectedItem();
699 HTREEITEM hNextItem
= nullptr;
700 if ((hNextItem
=m_pwndPageTree
->GetChildItem(hItem
))!=0)
702 else if ((hNextItem
=m_pwndPageTree
->GetNextSiblingItem(hItem
))!=0)
704 else if (m_pwndPageTree
->GetParentItem(hItem
))
708 hItem
= m_pwndPageTree
->GetParentItem(hItem
);
712 hNextItem
= m_pwndPageTree
->GetNextSiblingItem(hItem
);
717 // no next item -- so cycle to the first item
718 hNextItem
= m_pwndPageTree
->GetRootItem();
721 m_pwndPageTree
->SelectItem(hNextItem
);
726 /////////////////////////////////////////////////////////////////////
729 BOOL
CTreePropSheet::OnInitDialog()
731 int iconWidth
= GetSystemMetrics(SM_CXSMICON
);
732 int iconHeight
= GetSystemMetrics(SM_CYSMICON
);
735 // be sure, there are no stacked tabs, because otherwise the
736 // page caption will be to large in tree view mode
737 EnableStackedTabs(FALSE
);
739 // Initialize image list.
740 if (m_DefaultImages
.GetSafeHandle())
743 m_DefaultImages
.GetImageInfo(0, &ii
);
744 if (ii
.hbmImage
) DeleteObject(ii
.hbmImage
);
745 if (ii
.hbmMask
) DeleteObject(ii
.hbmMask
);
746 m_Images
.Create(ii
.rcImage
.right
-ii
.rcImage
.left
, ii
.rcImage
.bottom
-ii
.rcImage
.top
, ILC_COLOR32
|ILC_MASK
, 0, 1);
749 m_Images
.Create(iconWidth
, iconHeight
, ILC_COLOR32
| ILC_MASK
, 0, 1);
752 // perform default implementation
753 BOOL bResult
= CPropertySheet::OnInitDialog();
754 HighColorTab::UpdateImageList(*this, iconWidth
, iconHeight
);
756 if (!m_bTreeViewMode
)
757 // stop here, if we would like to use tabs
760 // Get tab control...
761 CTabCtrl
*pTab
= GetTabControl();
762 if (!IsWindow(pTab
->GetSafeHwnd()))
769 pTab
->ShowWindow(SW_HIDE
);
770 pTab
->EnableWindow(FALSE
);
772 // Place another (empty) tab ctrl, to get a frame instead
774 pTab
->GetWindowRect(rectFrame
);
775 ScreenToClient(rectFrame
);
777 m_pFrame
= CreatePageFrame();
781 AfxThrowMemoryException();
783 m_pFrame
->Create(WS_CHILD
|WS_VISIBLE
|WS_CLIPSIBLINGS
, rectFrame
, this, 0xFFFF);
784 m_pFrame
->ShowCaption(m_bPageCaption
);
786 // Lets make place for the tree ctrl
787 HDC hdc
= ::GetDC(nullptr);
788 int dpiX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
789 ::ReleaseDC(nullptr, hdc
);
790 const int nTreeWidth
= m_nPageTreeWidth
* dpiX
/ 96;
791 const int nTreeSpace
= 5;
794 GetWindowRect(rectSheet
);
795 rectSheet
.right
+= nTreeWidth
;
796 SetWindowPos(nullptr, -1, -1, rectSheet
.Width(), rectSheet
.Height(), SWP_NOZORDER
| SWP_NOMOVE
);
799 MoveChildWindows(nTreeWidth
, 0);
801 // Lets calculate the rectangle for the tree ctrl
802 CRect
rectTree(rectFrame
);
803 rectTree
.right
= rectTree
.left
+ nTreeWidth
- nTreeSpace
;
805 // calculate caption height
806 NONCLIENTMETRICS metrics
= { 0 };
807 metrics
.cbSize
= sizeof(NONCLIENTMETRICS
);
808 SystemParametersInfo(SPI_GETNONCLIENTMETRICS
, 0, &metrics
, FALSE
);
809 m_pFrame
->SetCaptionHeight(metrics
.iCaptionHeight
);
811 // if no caption should be displayed, make the window smaller in
815 // make frame smaller
816 m_pFrame
->GetWnd()->GetWindowRect(rectFrame
);
817 ScreenToClient(rectFrame
);
818 rectFrame
.top
+= metrics
.iCaptionHeight
;
819 m_pFrame
->GetWnd()->MoveWindow(rectFrame
);
821 // move all child windows up
822 MoveChildWindows(0, -metrics
.iCaptionHeight
);
824 // modify rectangle for the tree ctrl
825 rectTree
.bottom
-= metrics
.iCaptionHeight
;
830 rect
.top
+= metrics
.iCaptionHeight
/ 2;
831 rect
.bottom
-= metrics
.iCaptionHeight
- metrics
.iCaptionHeight
/ 2;
833 GetParent()->ScreenToClient(rect
);
837 // finally create the tree control
838 const DWORD dwTreeStyle
= TVS_SHOWSELALWAYS
|TVS_TRACKSELECT
|TVS_HASLINES
|TVS_LINESATROOT
|TVS_HASBUTTONS
;
839 m_pwndPageTree
= CreatePageTreeObject();
843 AfxThrowMemoryException();
846 // MFC7-support here (Thanks to Rainer Wollgarten)
847 // YT: Cast tree control to CWnd and calls CWnd::CreateEx in all cases (VC 6 and7).
848 ((CWnd
*)m_pwndPageTree
)->CreateEx(
849 WS_EX_CLIENTEDGE
|WS_EX_NOPARENTNOTIFY
|TVS_EX_DOUBLEBUFFER
,
850 L
"SysTreeView32", L
"PageTree",
851 WS_TABSTOP
|WS_CHILD
|WS_VISIBLE
|dwTreeStyle
,
852 rectTree
, this, s_unPageTreeId
);
856 m_pwndPageTree
->SetImageList(&m_Images
, TVSIL_NORMAL
);
857 m_pwndPageTree
->SetImageList(&m_Images
, TVSIL_STATE
);
859 SetWindowTheme(m_pwndPageTree
->GetSafeHwnd(), L
"Explorer", nullptr);
861 // Fill the tree ctrl
864 // Select item for the current page
865 if (pTab
->GetCurSel() > -1)
866 SelectPageTreeItem(pTab
->GetCurSel());
872 void CTreePropSheet::OnDestroy()
874 CPropertySheet::OnDestroy();
876 if (m_Images
.GetSafeHandle())
877 m_Images
.DeleteImageList();
879 delete m_pwndPageTree
;
880 m_pwndPageTree
= nullptr;
887 LRESULT
CTreePropSheet::OnAddPage(WPARAM wParam
, LPARAM lParam
)
889 LRESULT lResult
= DefWindowProc(PSM_ADDPAGE
, wParam
, lParam
);
890 if (!m_bTreeViewMode
)
894 SelectCurrentPageTreeItem();
900 LRESULT
CTreePropSheet::OnRemovePage(WPARAM wParam
, LPARAM lParam
)
902 LRESULT lResult
= DefWindowProc(PSM_REMOVEPAGE
, wParam
, lParam
);
903 if (!m_bTreeViewMode
)
907 SelectCurrentPageTreeItem();
913 LRESULT
CTreePropSheet::OnSetCurSel(WPARAM wParam
, LPARAM lParam
)
915 LRESULT lResult
= DefWindowProc(PSM_SETCURSEL
, wParam
, lParam
);
916 if (!m_bTreeViewMode
)
919 SelectCurrentPageTreeItem();
924 LRESULT
CTreePropSheet::OnSetCurSelId(WPARAM wParam
, LPARAM lParam
)
926 return OnSetCurSel(wParam
, lParam
);
930 void CTreePropSheet::OnPageTreeSelChanging(NMHDR
*pNotifyStruct
, LRESULT
*plResult
)
933 if (m_bPageTreeSelChangedActive
)
936 m_bPageTreeSelChangedActive
= TRUE
;
938 NMTREEVIEW
*pTvn
= reinterpret_cast<NMTREEVIEW
*>(pNotifyStruct
);
939 int nPage
= (int)m_pwndPageTree
->GetItemData(pTvn
->itemNew
.hItem
);
942 HTREEITEM nextItem
= m_pwndPageTree
->GetChildItem(pTvn
->itemNew
.hItem
);
943 nPage
= (int)m_pwndPageTree
->GetItemData(nextItem
);
946 if (nPage
>= (int)m_pwndPageTree
->GetCount())
947 bResult
= KillActiveCurrentPage();
949 bResult
= SetActivePage((int)nPage
);
952 // prevent selection to change
955 // Set focus to tree ctrl (I guess that's what the user expects)
956 m_pwndPageTree
->SetFocus();
958 m_bPageTreeSelChangedActive
= FALSE
;
964 void CTreePropSheet::OnPageTreeSelChanged(NMHDR
* /*pNotifyStruct*/, LRESULT
*plResult
)
974 LRESULT
CTreePropSheet::OnIsDialogMessage(WPARAM wParam
, LPARAM lParam
)
976 MSG
*pMsg
= reinterpret_cast<MSG
*>(lParam
);
977 if (pMsg
->message
==WM_KEYDOWN
&& pMsg
->wParam
==VK_TAB
&& GetKeyState(VK_CONTROL
)&0x8000)
979 if (GetKeyState(VK_SHIFT
)&0x8000)
980 ActivatePreviousPage();
986 if (pMsg
->message
== WM_KEYDOWN
&& GetKeyState(VK_CONTROL
) & 0x8000 && ((pMsg
->wParam
== VK_PRIOR
) || pMsg
->wParam
== VK_NEXT
))
988 if (pMsg
->wParam
== VK_PRIOR
)
989 ActivatePreviousPage();
995 return CPropertySheet::DefWindowProc(PSM_ISDIALOGMESSAGE
, wParam
, lParam
);
998 } //namespace TreePropSheet