Fixed issue #1737: Make a button to rename remote
[TortoiseGit.git] / src / Utils / TreePropSheet / TreePropSheet.cpp
blob9015f0d275eccba4ca54aaba97c82d6da28ee014
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.
10 * $Workfile:$
11 * $Revision:$
12 * $Modtime:$
13 * $Author:$
15 * Revision History:
16 * $History:$
18 *********************************************************************/
21 #include "stdafx.h"
22 #include "TreePropSheet.h"
23 #include "PropPageFrameDefault.h"
24 #include "HighColorTab.hpp"
26 #ifdef _DEBUG
27 #define new DEBUG_NEW
28 #undef THIS_FILE
29 static char THIS_FILE[] = __FILE__;
30 #endif
34 namespace TreePropSheet
37 //-------------------------------------------------------------------
38 // class CTreePropSheet
39 //-------------------------------------------------------------------
41 BEGIN_MESSAGE_MAP(CTreePropSheet, CPropertySheet)
42 //{{AFX_MSG_MAP(CTreePropSheet)
43 ON_WM_DESTROY()
44 //}}AFX_MSG_MAP
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)
55 END_MESSAGE_MAP()
57 IMPLEMENT_DYNAMIC(CTreePropSheet, CPropertySheet)
59 const UINT CTreePropSheet::s_unPageTreeId = 0x7EEE;
61 CTreePropSheet::CTreePropSheet()
62 : CPropertySheet(),
63 m_bPageTreeSelChangedActive(FALSE),
64 m_bTreeViewMode(TRUE),
65 m_bPageCaption(FALSE),
66 m_bTreeImages(FALSE),
67 m_nPageTreeWidth(150),
68 m_pwndPageTree(NULL),
69 m_pFrame(NULL)
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),
78 m_bTreeImages(FALSE),
79 m_nPageTreeWidth(150),
80 m_pwndPageTree(NULL),
81 m_pFrame(NULL)
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),
91 m_bTreeImages(FALSE),
92 m_nPageTreeWidth(150),
93 m_pwndPageTree(NULL),
94 m_pFrame(NULL)
99 CTreePropSheet::~CTreePropSheet()
104 /////////////////////////////////////////////////////////////////////
105 // Operationen
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
112 ASSERT(FALSE);
113 return FALSE;
116 m_bTreeViewMode = bTreeViewMode;
117 if (m_bTreeViewMode)
119 m_bPageCaption = bPageCaption;
120 m_bTreeImages = bTreeImages;
123 return TRUE;
127 BOOL CTreePropSheet::SetTreeWidth(int nWidth)
129 if (IsWindow(m_hWnd))
131 // needs to be called, before the window is created.
132 ASSERT(FALSE);
133 return FALSE;
136 m_nPageTreeWidth = nWidth;
138 return TRUE;
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);
152 return dwPrevFormat;
156 BOOL CTreePropSheet::SetTreeDefaultImages(CImageList *pImages)
158 if (pImages->GetImageCount() != 2)
160 ASSERT(FALSE);
161 return FALSE;
164 if (m_DefaultImages.GetSafeHandle())
165 m_DefaultImages.DeleteImageList();
166 m_DefaultImages.Create(pImages);
168 // update, if necessary
169 if (IsWindow(m_hWnd))
170 RefillPageTree();
172 return TRUE;
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))
181 return FALSE;
183 if (m_DefaultImages.GetImageCount() != 2)
185 m_DefaultImages.DeleteImageList();
186 return FALSE;
189 return TRUE;
193 CTreeCtrl* CTreePropSheet::GetPageTreeControl()
195 return m_pwndPageTree;
199 /////////////////////////////////////////////////////////////////////
200 // public helpers
202 BOOL CTreePropSheet::SetPageIcon(CPropertyPage *pPage, HICON hIcon)
204 pPage->m_psp.dwFlags|= PSP_USEHICON;
205 pPage->m_psp.hIcon = hIcon;
206 return TRUE;
210 BOOL CTreePropSheet::SetPageIcon(CPropertyPage *pPage, UINT unIconId)
212 HICON hIcon = AfxGetApp()->LoadIcon(unIconId);
213 if (!hIcon)
214 return FALSE;
216 return SetPageIcon(pPage, hIcon);
220 BOOL CTreePropSheet::SetPageIcon(CPropertyPage *pPage, CImageList &Images, int nImage)
222 HICON hIcon = Images.ExtractIcon(nImage);
223 if (!hIcon)
224 return FALSE;
226 return SetPageIcon(pPage, hIcon);
230 BOOL CTreePropSheet::DestroyPageIcon(CPropertyPage *pPage)
232 if (!pPage || !(pPage->m_psp.dwFlags&PSP_USEHICON) || !pPage->m_psp.hIcon)
233 return FALSE;
235 DestroyIcon(pPage->m_psp.hIcon);
236 pPage->m_psp.dwFlags&= ~PSP_USEHICON;
237 pPage->m_psp.hIcon = NULL;
239 return TRUE;
243 /////////////////////////////////////////////////////////////////////
244 // Overridable implementation helpers
246 CString CTreePropSheet::GenerateEmptyPageMessage(LPCTSTR lpszEmptyPageMessage, LPCTSTR lpszCaption)
248 CString strMsg;
249 strMsg.Format(lpszEmptyPageMessage, lpszCaption);
250 return strMsg;
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);
272 while (pWnd)
274 CRect rect;
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))
288 return;
290 m_pwndPageTree->DeleteAllItems();
292 CTabCtrl *pTabCtrl = GetTabControl();
293 if (!IsWindow(pTabCtrl->GetSafeHwnd()))
295 ASSERT(FALSE);
296 return;
299 const int nPageCount = pTabCtrl->GetItemCount();
301 // rebuild image list
302 if (m_bTreeImages)
304 for (int i = m_Images.GetImageCount()-1; i >= 0; --i)
305 m_Images.Remove(i);
307 // add page images
308 CImageList *pPageImages = pTabCtrl->GetImageList();
309 if (pPageImages)
311 for (int nImage = 0; nImage < pPageImages->GetImageCount(); ++nImage)
313 HICON hIcon = pPageImages->ExtractIcon(nImage);
314 m_Images.Add(hIcon);
315 DestroyIcon(hIcon);
319 // add default images
320 if (m_DefaultImages.GetSafeHandle())
322 HICON hIcon;
324 // add default images
325 hIcon = m_DefaultImages.ExtractIcon(0);
326 if (hIcon)
328 m_Images.Add(hIcon);
329 DestroyIcon(hIcon);
331 hIcon = m_DefaultImages.ExtractIcon(1);
333 m_Images.Add(hIcon);
334 DestroyIcon(hIcon);
339 // insert tree items
340 for (int nPage = 0; nPage < nPageCount; ++nPage)
342 // Get title and image of the page
343 CString strPagePath;
345 TCITEM ti;
346 SecureZeroMemory(&ti, sizeof(ti));
347 ti.mask = TCIF_TEXT|TCIF_IMAGE;
348 ti.cchTextMax = MAX_PATH;
349 ti.pszText = strPagePath.GetBuffer(ti.cchTextMax);
350 ASSERT(ti.pszText);
351 if (!ti.pszText)
352 return;
354 pTabCtrl->GetItem(nPage, &ti);
355 strPagePath.ReleaseBuffer();
357 // Create an item in the tree for the page
358 HTREEITEM hItem = CreatePageTreeItem(ti.pszText);
359 ASSERT(hItem);
360 if (hItem)
362 m_pwndPageTree->SetItemData(hItem, nPage);
364 // set image
365 if (m_bTreeImages)
367 int nImage = ti.iImage;
368 if (nImage < 0 || nImage >= m_Images.GetImageCount())
369 nImage = m_DefaultImages.GetSafeHandle()? m_Images.GetImageCount()-1 : -1;
371 m_pwndPageTree->SetItemImage(hItem, nImage, nImage);
373 m_pwndPageTree->Expand(m_pwndPageTree->GetParentItem(hItem), TVE_EXPAND);
379 HTREEITEM CTreePropSheet::CreatePageTreeItem(LPCTSTR lpszPath, HTREEITEM hParent /* = TVI_ROOT */)
381 CString strPath(lpszPath);
382 CString strTopMostItem(SplitPageTreePath(strPath));
384 // Check if an item with the given text does already exist
385 HTREEITEM hItem = NULL;
386 HTREEITEM hChild = m_pwndPageTree->GetChildItem(hParent);
387 while (hChild)
389 if (m_pwndPageTree->GetItemText(hChild) == strTopMostItem)
391 hItem = hChild;
392 break;
394 hChild = m_pwndPageTree->GetNextItem(hChild, TVGN_NEXT);
397 // If item with that text does not already exist, create a new one
398 if (!hItem)
400 hItem = m_pwndPageTree->InsertItem(strTopMostItem, hParent);
401 m_pwndPageTree->SetItemData(hItem, (DWORD_PTR)-1);
402 if (!strPath.IsEmpty() && m_bTreeImages && m_DefaultImages.GetSafeHandle())
403 // set folder image
404 m_pwndPageTree->SetItemImage(hItem, m_Images.GetImageCount()-2, m_Images.GetImageCount()-2);
406 if (!hItem)
408 ASSERT(FALSE);
409 return NULL;
412 if (strPath.IsEmpty())
413 return hItem;
414 else
415 return CreatePageTreeItem(strPath, hItem);
419 CString CTreePropSheet::SplitPageTreePath(CString &strRest)
421 int nSeperatorPos = 0;
422 #pragma warning(push)
423 #pragma warning(disable: 4127) // conditional expression constant
424 while (TRUE)
426 nSeperatorPos = strRest.Find(_T("::"), nSeperatorPos);
427 if (nSeperatorPos == -1)
429 CString strItem(strRest);
430 strRest.Empty();
431 return strItem;
433 else if (nSeperatorPos>0)
435 // if there is an odd number of backslashes infront of the
436 // seperator, than do not interpret it as separator
437 int nBackslashCount = 0;
438 for (int nPos = nSeperatorPos-1; nPos >= 0 && strRest[nPos]==_T('\\'); --nPos, ++nBackslashCount);
439 if (nBackslashCount%2 == 0)
440 break;
441 else
442 ++nSeperatorPos;
445 #pragma warning(pop)
447 CString strItem(strRest.Left(nSeperatorPos));
448 strItem.Replace(_T("\\::"), _T("::"));
449 strItem.Replace(_T("\\\\"), _T("\\"));
450 strRest = strRest.Mid(nSeperatorPos+2);
451 return strItem;
455 BOOL CTreePropSheet::KillActiveCurrentPage()
457 HWND hCurrentPage = PropSheet_GetCurrentPageHwnd(m_hWnd);
458 if (!IsWindow(hCurrentPage))
460 ASSERT(FALSE);
461 return TRUE;
464 // Check if the current page is really active (if page is invisible
465 // an virtual empty page is the active one.
466 if (!::IsWindowVisible(hCurrentPage))
467 return TRUE;
469 // Try to deactivate current page
470 PSHNOTIFY pshn;
471 pshn.hdr.code = PSN_KILLACTIVE;
472 pshn.hdr.hwndFrom = m_hWnd;
473 pshn.hdr.idFrom = GetDlgCtrlID();
474 pshn.lParam = 0;
475 if (::SendMessage(hCurrentPage, WM_NOTIFY, pshn.hdr.idFrom, (LPARAM)&pshn))
476 // current page does not allow page change
477 return FALSE;
479 // Hide the page
480 ::ShowWindow(hCurrentPage, SW_HIDE);
482 return TRUE;
486 HTREEITEM CTreePropSheet::GetPageTreeItem(int nPage, HTREEITEM hRoot /* = TVI_ROOT */)
488 // Special handling for root case
489 if (hRoot == TVI_ROOT)
490 hRoot = m_pwndPageTree->GetNextItem(NULL, TVGN_ROOT);
492 // Check parameters
493 if (nPage < 0 || nPage >= GetPageCount())
495 ASSERT(FALSE);
496 return NULL;
499 if (hRoot == NULL)
501 ASSERT(FALSE);
502 return NULL;
505 // we are performing a simple linear search here, because we are
506 // expecting only little data
507 HTREEITEM hItem = hRoot;
508 while (hItem)
510 if ((signed)m_pwndPageTree->GetItemData(hItem) == nPage)
511 return hItem;
512 if (m_pwndPageTree->ItemHasChildren(hItem))
514 HTREEITEM hResult = GetPageTreeItem(nPage, m_pwndPageTree->GetNextItem(hItem, TVGN_CHILD));
515 if (hResult)
516 return hResult;
519 hItem = m_pwndPageTree->GetNextItem(hItem, TVGN_NEXT);
522 // we've found nothing, if we arrive here
523 return hItem;
527 BOOL CTreePropSheet::SelectPageTreeItem(int nPage)
529 HTREEITEM hItem = GetPageTreeItem(nPage);
530 if (!hItem)
531 return FALSE;
533 return m_pwndPageTree->SelectItem(hItem);
537 BOOL CTreePropSheet::SelectCurrentPageTreeItem()
539 CTabCtrl *pTab = GetTabControl();
540 if (!IsWindow(pTab->GetSafeHwnd()))
541 return FALSE;
543 return SelectPageTreeItem(pTab->GetCurSel());
547 void CTreePropSheet::UpdateCaption()
549 HWND hPage = PropSheet_GetCurrentPageHwnd(GetSafeHwnd());
550 BOOL bRealPage = IsWindow(hPage) && ::IsWindowVisible(hPage);
551 HTREEITEM hItem = m_pwndPageTree->GetSelectedItem();
552 if (!hItem)
553 return;
555 CString strCaption = m_pwndPageTree->GetItemText(hItem);
557 // if empty page, then update empty page message
558 if (!bRealPage)
559 m_pFrame->SetMsgText(GenerateEmptyPageMessage(m_strEmptyPageMessage, strCaption));
561 // if no captions are displayed, cancel here
562 if (!m_pFrame->GetShowCaption())
563 return;
565 // get tab control, to the the images from
566 CTabCtrl *pTabCtrl = GetTabControl();
567 if (!IsWindow(pTabCtrl->GetSafeHwnd()))
569 ASSERT(FALSE);
570 return;
573 if (m_bTreeImages)
575 // get image from tree
576 int nImage;
577 m_pwndPageTree->GetItemImage(hItem, nImage, nImage);
578 HICON hIcon = m_Images.ExtractIcon(nImage);
579 m_pFrame->SetCaption(strCaption, hIcon);
580 if (hIcon)
581 DestroyIcon(hIcon);
583 else if (bRealPage)
585 // get image from hidden (original) tab provided by the original
586 // implementation
587 CImageList *pImages = pTabCtrl->GetImageList();
588 if (pImages)
590 TCITEM ti;
591 SecureZeroMemory(&ti, sizeof(ti));
592 ti.mask = TCIF_IMAGE;
594 HICON hIcon = NULL;
595 if (pTabCtrl->GetItem((int)m_pwndPageTree->GetItemData(hItem), &ti))
596 hIcon = pImages->ExtractIcon(ti.iImage);
598 m_pFrame->SetCaption(strCaption, hIcon);
599 if (hIcon)
600 DestroyIcon(hIcon);
602 else
603 m_pFrame->SetCaption(strCaption);
605 else
606 m_pFrame->SetCaption(strCaption);
610 void CTreePropSheet::ActivatePreviousPage()
612 if (!IsWindow(m_hWnd))
613 return;
615 if (!IsWindow(m_pwndPageTree->GetSafeHwnd()))
617 // normal tab property sheet. Simply use page index
618 int nPageIndex = GetActiveIndex();
619 if (nPageIndex<0 || nPageIndex>=GetPageCount())
620 return;
622 int nPrevIndex = (nPageIndex==0)? GetPageCount()-1 : nPageIndex-1;
623 SetActivePage(nPrevIndex);
625 else
627 // property sheet with page tree.
628 // we need a more sophisticated handling here, than simply using
629 // the page index, because we won't skip empty pages.
630 // so we have to walk the page tree
631 HTREEITEM hItem = m_pwndPageTree->GetSelectedItem();
632 ASSERT(hItem);
633 if (!hItem)
634 return;
636 HTREEITEM hPrevItem = NULL;
637 if ((hPrevItem=m_pwndPageTree->GetPrevSiblingItem(hItem))!=0)
639 while (m_pwndPageTree->ItemHasChildren(hPrevItem))
641 hPrevItem = m_pwndPageTree->GetChildItem(hPrevItem);
642 while (m_pwndPageTree->GetNextSiblingItem(hPrevItem))
643 hPrevItem = m_pwndPageTree->GetNextSiblingItem(hPrevItem);
646 else
647 hPrevItem=m_pwndPageTree->GetParentItem(hItem);
649 if (!hPrevItem)
651 // no prev item, so cycle to the last item
652 hPrevItem = m_pwndPageTree->GetRootItem();
654 #pragma warning(push)
655 #pragma warning(disable: 4127) // conditional expression constant
656 while (TRUE)
658 while (m_pwndPageTree->GetNextSiblingItem(hPrevItem))
659 hPrevItem = m_pwndPageTree->GetNextSiblingItem(hPrevItem);
661 if (m_pwndPageTree->ItemHasChildren(hPrevItem))
662 hPrevItem = m_pwndPageTree->GetChildItem(hPrevItem);
663 else
664 break;
666 #pragma warning(pop)
669 if (hPrevItem)
670 m_pwndPageTree->SelectItem(hPrevItem);
675 void CTreePropSheet::ActivateNextPage()
677 if (!IsWindow(m_hWnd))
678 return;
680 if (!IsWindow(m_pwndPageTree->GetSafeHwnd()))
682 // normal tab property sheet. Simply use page index
683 int nPageIndex = GetActiveIndex();
684 if (nPageIndex<0 || nPageIndex>=GetPageCount())
685 return;
687 int nNextIndex = (nPageIndex==GetPageCount()-1)? 0 : nPageIndex+1;
688 SetActivePage(nNextIndex);
690 else
692 // property sheet with page tree.
693 // we need a more sophisticated handling here, than simply using
694 // the page index, because we won't skip empty pages.
695 // so we have to walk the page tree
696 HTREEITEM hItem = m_pwndPageTree->GetSelectedItem();
697 ASSERT(hItem);
698 if (!hItem)
699 return;
701 HTREEITEM hNextItem = NULL;
702 if ((hNextItem=m_pwndPageTree->GetChildItem(hItem))!=0)
704 else if ((hNextItem=m_pwndPageTree->GetNextSiblingItem(hItem))!=0)
706 else if (m_pwndPageTree->GetParentItem(hItem))
708 while (!hNextItem)
710 hItem = m_pwndPageTree->GetParentItem(hItem);
711 if (!hItem)
712 break;
714 hNextItem = m_pwndPageTree->GetNextSiblingItem(hItem);
718 if (!hNextItem)
719 // no next item -- so cycle to the first item
720 hNextItem = m_pwndPageTree->GetRootItem();
722 if (hNextItem)
723 m_pwndPageTree->SelectItem(hNextItem);
728 /////////////////////////////////////////////////////////////////////
729 // Overridings
731 BOOL CTreePropSheet::OnInitDialog()
733 if (m_bTreeViewMode)
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())
742 IMAGEINFO ii;
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);
748 else
749 m_Images.Create(16, 16, ILC_COLOR32|ILC_MASK, 0, 1);
752 // perform default implementation
753 BOOL bResult = CPropertySheet::OnInitDialog();
754 HighColorTab::UpdateImageList(*this);
756 if (!m_bTreeViewMode)
757 // stop here, if we would like to use tabs
758 return bResult;
760 // Get tab control...
761 CTabCtrl *pTab = GetTabControl();
762 if (!IsWindow(pTab->GetSafeHwnd()))
764 ASSERT(FALSE);
765 return bResult;
768 // ... and hide it
769 pTab->ShowWindow(SW_HIDE);
770 pTab->EnableWindow(FALSE);
772 // Place another (empty) tab ctrl, to get a frame instead
773 CRect rectFrame;
774 pTab->GetWindowRect(rectFrame);
775 ScreenToClient(rectFrame);
777 m_pFrame = CreatePageFrame();
778 if (!m_pFrame)
780 ASSERT(FALSE);
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 const int nTreeWidth = m_nPageTreeWidth;
788 const int nTreeSpace = 5;
790 CRect rectSheet;
791 GetWindowRect(rectSheet);
792 rectSheet.right+= nTreeWidth;
793 SetWindowPos(NULL, -1, -1, rectSheet.Width(), rectSheet.Height(), SWP_NOZORDER|SWP_NOMOVE);
794 CenterWindow();
796 MoveChildWindows(nTreeWidth, 0);
798 // Lets calculate the rectangle for the tree ctrl
799 CRect rectTree(rectFrame);
800 rectTree.right = rectTree.left + nTreeWidth - nTreeSpace;
802 // calculate caption height
803 CTabCtrl wndTabCtrl;
804 wndTabCtrl.Create(WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS, rectFrame, this, 0x1234);
805 wndTabCtrl.InsertItem(0, _T(""));
806 CRect rectFrameCaption;
807 wndTabCtrl.GetItemRect(0, rectFrameCaption);
808 wndTabCtrl.DestroyWindow();
809 m_pFrame->SetCaptionHeight(rectFrameCaption.Height());
811 // if no caption should be displayed, make the window smaller in
812 // height
813 if (!m_bPageCaption)
815 // make frame smaller
816 m_pFrame->GetWnd()->GetWindowRect(rectFrame);
817 ScreenToClient(rectFrame);
818 rectFrame.top+= rectFrameCaption.Height();
819 m_pFrame->GetWnd()->MoveWindow(rectFrame);
821 // move all child windows up
822 MoveChildWindows(0, -rectFrameCaption.Height());
824 // modify rectangle for the tree ctrl
825 rectTree.bottom-= rectFrameCaption.Height();
827 // make us smaller
828 CRect rect;
829 GetWindowRect(rect);
830 rect.top+= rectFrameCaption.Height()/2;
831 rect.bottom-= rectFrameCaption.Height()-rectFrameCaption.Height()/2;
832 if (GetParent())
833 GetParent()->ScreenToClient(rect);
834 MoveWindow(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();
840 if (!m_pwndPageTree)
842 ASSERT(FALSE);
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 _T("SysTreeView32"), _T("PageTree"),
851 WS_TABSTOP|WS_CHILD|WS_VISIBLE|dwTreeStyle,
852 rectTree, this, s_unPageTreeId);
854 if (m_bTreeImages)
856 m_pwndPageTree->SetImageList(&m_Images, TVSIL_NORMAL);
857 m_pwndPageTree->SetImageList(&m_Images, TVSIL_STATE);
859 SetWindowTheme(m_pwndPageTree->GetSafeHwnd(), L"Explorer", NULL);
861 // Fill the tree ctrl
862 RefillPageTree();
864 // Select item for the current page
865 if (pTab->GetCurSel() > -1)
866 SelectPageTreeItem(pTab->GetCurSel());
868 return bResult;
872 void CTreePropSheet::OnDestroy()
874 CPropertySheet::OnDestroy();
876 if (m_Images.GetSafeHandle())
877 m_Images.DeleteImageList();
879 delete m_pwndPageTree;
880 m_pwndPageTree = NULL;
882 delete m_pFrame;
883 m_pFrame = NULL;
887 LRESULT CTreePropSheet::OnAddPage(WPARAM wParam, LPARAM lParam)
889 LRESULT lResult = DefWindowProc(PSM_ADDPAGE, wParam, lParam);
890 if (!m_bTreeViewMode)
891 return lResult;
893 RefillPageTree();
894 SelectCurrentPageTreeItem();
896 return lResult;
900 LRESULT CTreePropSheet::OnRemovePage(WPARAM wParam, LPARAM lParam)
902 LRESULT lResult = DefWindowProc(PSM_REMOVEPAGE, wParam, lParam);
903 if (!m_bTreeViewMode)
904 return lResult;
906 RefillPageTree();
907 SelectCurrentPageTreeItem();
909 return lResult;
913 LRESULT CTreePropSheet::OnSetCurSel(WPARAM wParam, LPARAM lParam)
915 LRESULT lResult = DefWindowProc(PSM_SETCURSEL, wParam, lParam);
916 if (!m_bTreeViewMode)
917 return lResult;
919 SelectCurrentPageTreeItem();
920 UpdateCaption();
921 return lResult;
924 LRESULT CTreePropSheet::OnSetCurSelId(WPARAM wParam, LPARAM lParam)
926 return OnSetCurSel(wParam, lParam);
930 void CTreePropSheet::OnPageTreeSelChanging(NMHDR *pNotifyStruct, LRESULT *plResult)
932 *plResult = 0;
933 if (m_bPageTreeSelChangedActive)
934 return;
935 else
936 m_bPageTreeSelChangedActive = TRUE;
938 NMTREEVIEW *pTvn = reinterpret_cast<NMTREEVIEW*>(pNotifyStruct);
939 int nPage = (int)m_pwndPageTree->GetItemData(pTvn->itemNew.hItem);
940 if (nPage < 0)
942 HTREEITEM nextItem = m_pwndPageTree->GetChildItem(pTvn->itemNew.hItem);
943 nPage = (int)m_pwndPageTree->GetItemData(nextItem);
945 BOOL bResult;
946 if (nPage >= (int)m_pwndPageTree->GetCount())
947 bResult = KillActiveCurrentPage();
948 else
949 bResult = SetActivePage((int)nPage);
951 if (!bResult)
952 // prevent selection to change
953 *plResult = TRUE;
955 // Set focus to tree ctrl (I guess that's what the user expects)
956 m_pwndPageTree->SetFocus();
958 m_bPageTreeSelChangedActive = FALSE;
960 return;
964 void CTreePropSheet::OnPageTreeSelChanged(NMHDR * /*pNotifyStruct*/, LRESULT *plResult)
966 *plResult = 0;
968 UpdateCaption();
970 return;
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();
981 else
982 ActivateNextPage();
983 return TRUE;
987 return CPropertySheet::DefWindowProc(PSM_ISDIALOGMESSAGE, wParam, lParam);
990 } //namespace TreePropSheet