- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# TreePropSheet.cpp

    00001 /********************************************************************
    00002 *
    00003 * Copyright (c) 2002 Sven Wiegand <mail@sven-wiegand.de>
    00004 *
    00005 * You can use this and modify this in any way you want,
    00006 * BUT LEAVE THIS HEADER INTACT.
    00007 *
    00008 * Redistribution is appreciated.
    00009 *
    00010 * $Workfile:$
    00011 * $Revision: 1.2 $
    00012 * $Modtime:$
    00013 * $Author: gabest $
    00014 *
    00015 * Revision History:
    00016 *       $History:$
    00017 *
    00018 *********************************************************************/
    00019
    00020
    00021 #include "stdafx.h"
    00022 #include "TreePropSheet.h"
    00023 #include "PropPageFrameDefault.h"
    00024
    00025 #ifdef _DEBUG
    00026 #define new DEBUG_NEW
    00027 #undef THIS_FILE
    00028 static char THIS_FILE[] = __FILE__;
    00029 #endif
    00030
    00031
    00032
    00033 namespace TreePropSheet
    00034 {
    00035
    00036 //-------------------------------------------------------------------
    00037 // class CTreePropSheet
    00038 //-------------------------------------------------------------------
    00039
    00040 BEGIN_MESSAGE_MAP(CTreePropSheet, CPropertySheet)
    00041         //{{AFX_MSG_MAP(CTreePropSheet)
    00042         ON_WM_DESTROY()
    00043         //}}AFX_MSG_MAP
    00044         ON_MESSAGE(PSM_ADDPAGE, OnAddPage)
    00045         ON_MESSAGE(PSM_REMOVEPAGE, OnRemovePage)
    00046         ON_MESSAGE(PSM_SETCURSEL, OnSetCurSel)
    00047         ON_MESSAGE(PSM_SETCURSELID, OnSetCurSelId)
    00048         ON_MESSAGE(PSM_ISDIALOGMESSAGE, OnIsDialogMessage)
    00049
    00050         ON_NOTIFY(TVN_SELCHANGINGA, s_unPageTreeId, OnPageTreeSelChanging)
    00051         ON_NOTIFY(TVN_SELCHANGINGW, s_unPageTreeId, OnPageTreeSelChanging)
    00052         ON_NOTIFY(TVN_SELCHANGEDA, s_unPageTreeId, OnPageTreeSelChanged)
    00053         ON_NOTIFY(TVN_SELCHANGEDW, s_unPageTreeId, OnPageTreeSelChanged)
    00054 END_MESSAGE_MAP()
    00055
    00056 IMPLEMENT_DYNAMIC(CTreePropSheet, CPropertySheet)
    00057
    00058 const UINT CTreePropSheet::s_unPageTreeId = 0x7EEE;
    00059
    00060 CTreePropSheet::CTreePropSheet()
    00061 :       m_bPageTreeSelChangedActive(FALSE),
    00062         m_bTreeViewMode(TRUE),
    00063         m_bPageCaption(FALSE),
    00064         m_bTreeImages(FALSE),
    00065         m_nPageTreeWidth(150),
    00066         m_pwndPageTree(NULL),
    00067         m_pFrame(NULL)
    00068 {}
    00069
    00070
    00071 CTreePropSheet::CTreePropSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
    00072 :       CPropertySheet(nIDCaption, pParentWnd, iSelectPage),
    00073         m_bPageTreeSelChangedActive(FALSE),
    00074         m_bTreeViewMode(TRUE),
    00075         m_bPageCaption(FALSE),
    00076         m_bTreeImages(FALSE),
    00077         m_nPageTreeWidth(150),
    00078         m_pwndPageTree(NULL),
    00079         m_pFrame(NULL)
    00080 {
    00081 }
    00082
    00083
    00084 CTreePropSheet::CTreePropSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
    00085 :       CPropertySheet(pszCaption, pParentWnd, iSelectPage),
    00086         m_bPageTreeSelChangedActive(FALSE),
    00087         m_bTreeViewMode(TRUE),
    00088         m_bPageCaption(FALSE),
    00089         m_bTreeImages(FALSE),
    00090         m_nPageTreeWidth(150),
    00091         m_pwndPageTree(NULL),
    00092         m_pFrame(NULL)
    00093 {
    00094 }
    00095
    00096
    00097 CTreePropSheet::~CTreePropSheet()
    00098 {
    00099         if(m_Images.GetSafeHandle()) m_Images.DeleteImageList();
    00100         delete m_pwndPageTree, m_pwndPageTree = NULL;
    00101         delete m_pFrame, m_pFrame = NULL;
    00102 }
    00103
    00105 // Operationen
    00106
    00107 BOOL CTreePropSheet::SetTreeViewMode(BOOL bTreeViewMode /* = TRUE */, BOOL bPageCaption /* = FALSE */, BOOL bTreeImages /* = FALSE */)
    00108 {
    00109         if (IsWindow(m_hWnd))
    00110         {
    00111                 // needs to becalled, before the window has been created
    00112                 ASSERT(FALSE);
    00113                 return FALSE;
    00114         }
    00115
    00116         m_bTreeViewMode = bTreeViewMode;
    00117         if (m_bTreeViewMode)
    00118         {
    00119                 m_bPageCaption = bPageCaption;
    00120                 m_bTreeImages = bTreeImages;
    00121         }
    00122
    00123         return TRUE;
    00124 }
    00125
    00126
    00127 BOOL CTreePropSheet::SetTreeWidth(int nWidth)
    00128 {
    00129         if (IsWindow(m_hWnd))
    00130         {
    00131                 // needs to be called, before the window is created.
    00132                 ASSERT(FALSE);
    00133                 return FALSE;
    00134         }
    00135
    00136         m_nPageTreeWidth = nWidth;
    00137
    00138         return TRUE;
    00139 }
    00140
    00141
    00142 void CTreePropSheet::SetEmptyPageText(LPCTSTR lpszEmptyPageText)
    00143 {
    00144         m_strEmptyPageMessage = lpszEmptyPageText;
    00145 }
    00146
    00147
    00148 DWORD   CTreePropSheet::SetEmptyPageTextFormat(DWORD dwFormat)
    00149 {
    00150         DWORD   dwPrevFormat = m_pFrame->GetMsgFormat();
    00151         m_pFrame->SetMsgFormat(dwFormat);
    00152         return dwPrevFormat;
    00153 }
    00154
    00155
    00156 BOOL CTreePropSheet::SetTreeDefaultImages(CImageList *pImages)
    00157 {
    00158         if (pImages->GetImageCount() != 2)
    00159         {
    00160                 ASSERT(FALSE);
    00161                 return FALSE;
    00162         }
    00163
    00164         if (m_DefaultImages.GetSafeHandle())
    00165                 m_DefaultImages.DeleteImageList();
    00166         m_DefaultImages.Create(pImages);
    00167
    00168         // update, if necessary
    00169         if (IsWindow(m_hWnd))
    00170                 RefillPageTree();
    00171
    00172         return TRUE;
    00173 }
    00174
    00175
    00176 BOOL CTreePropSheet::SetTreeDefaultImages(UINT unBitmapID, int cx, COLORREF crMask)
    00177 {
    00178         if (m_DefaultImages.GetSafeHandle())
    00179                 m_DefaultImages.DeleteImageList();
    00180         if (!m_DefaultImages.Create(unBitmapID, cx, 0, crMask))
    00181                 return FALSE;
    00182
    00183         if (m_DefaultImages.GetImageCount() != 2)
    00184         {
    00185                 m_DefaultImages.DeleteImageList();
    00186                 return FALSE;
    00187         }
    00188
    00189         return TRUE;
    00190 }
    00191
    00192
    00193 CTreeCtrl* CTreePropSheet::GetPageTreeControl()
    00194 {
    00195         return m_pwndPageTree;
    00196 }
    00197
    00198
    00200 // public helpers
    00201
    00202 BOOL CTreePropSheet::SetPageIcon(CPropertyPage *pPage, HICON hIcon)
    00203 {
    00204         pPage->m_psp.dwFlags|= PSP_USEHICON;
    00205         pPage->m_psp.hIcon = hIcon;
    00206         return TRUE;
    00207 }
    00208
    00209
    00210 BOOL CTreePropSheet::SetPageIcon(CPropertyPage *pPage, UINT unIconId)
    00211 {
    00212         HICON   hIcon = AfxGetApp()->LoadIcon(unIconId);
    00213         if (!hIcon)
    00214                 return FALSE;
    00215
    00216         return SetPageIcon(pPage, hIcon);
    00217 }
    00218
    00219
    00220 BOOL CTreePropSheet::SetPageIcon(CPropertyPage *pPage, CImageList &Images, int nImage)
    00221 {
    00222         HICON   hIcon = Images.ExtractIcon(nImage);
    00223         if (!hIcon)
    00224                 return FALSE;
    00225
    00226         return SetPageIcon(pPage, hIcon);
    00227 }
    00228
    00229
    00230 BOOL CTreePropSheet::DestroyPageIcon(CPropertyPage *pPage)
    00231 {
    00232         if (!pPage || !(pPage->m_psp.dwFlags&PSP_USEHICON) || !pPage->m_psp.hIcon)
    00233                 return FALSE;
    00234
    00235         DestroyIcon(pPage->m_psp.hIcon);
    00236         pPage->m_psp.dwFlags&= ~PSP_USEHICON;
    00237         pPage->m_psp.hIcon = NULL;
    00238
    00239         return TRUE;
    00240 }
    00241
    00242
    00244 // Overridable implementation helpers
    00245
    00246 CString CTreePropSheet::GenerateEmptyPageMessage(LPCTSTR lpszEmptyPageMessage, LPCTSTR lpszCaption)
    00247 {
    00248         CString strMsg;
    00249         strMsg.Format(lpszEmptyPageMessage, lpszCaption);
    00250         return strMsg;
    00251 }
    00252
    00253
    00254 CTreeCtrl* CTreePropSheet::CreatePageTreeObject()
    00255 {
    00256         return new CTreeCtrl;
    00257 }
    00258
    00259
    00260 CPropPageFrame* CTreePropSheet::CreatePageFrame()
    00261 {
    00262         return new CPropPageFrameDefault;
    00263 }
    00264
    00265
    00267 // Implementation helpers
    00268
    00269 void CTreePropSheet::MoveChildWindows(int nDx, int nDy)
    00270 {
    00271         CWnd    *pWnd = GetWindow(GW_CHILD);
    00272         while (pWnd)
    00273         {
    00274                 CRect   rect;
    00275                 pWnd->GetWindowRect(rect);
    00276                 rect.OffsetRect(nDx, nDy);
    00277                 ScreenToClient(rect);
    00278                 pWnd->MoveWindow(rect);
    00279
    00280                 pWnd = pWnd->GetNextWindow();
    00281         }
    00282 }
    00283
    00284
    00285 void CTreePropSheet::RefillPageTree()
    00286 {
    00287         if (!IsWindow(m_hWnd))
    00288                 return;
    00289
    00290         m_pwndPageTree->DeleteAllItems();
    00291
    00292         CTabCtrl        *pTabCtrl = GetTabControl();
    00293         if (!IsWindow(pTabCtrl->GetSafeHwnd()))
    00294         {
    00295                 ASSERT(FALSE);
    00296                 return;
    00297         }
    00298
    00299         const int       nPageCount = pTabCtrl->GetItemCount();
    00300
    00301         // rebuild image list
    00302         if (m_bTreeImages)
    00303         {
    00304                 for (int i = m_Images.GetImageCount()-1; i >= 0; --i)
    00305                         m_Images.Remove(i);
    00306
    00307                 // add page images
    00308                 CImageList      *pPageImages = pTabCtrl->GetImageList();
    00309                 if (pPageImages)
    00310                 {
    00311                         for (int nImage = 0; nImage < pPageImages->GetImageCount(); ++nImage)
    00312                         {
    00313                                 HICON   hIcon = pPageImages->ExtractIcon(nImage);
    00314                                 m_Images.Add(hIcon);
    00315                                 DestroyIcon(hIcon);
    00316                         }
    00317                 }
    00318
    00319                 // add default images
    00320                 if (m_DefaultImages.GetSafeHandle())
    00321                 {
    00322                         HICON   hIcon;
    00323
    00324                         // add default images
    00325                         hIcon = m_DefaultImages.ExtractIcon(0);
    00326                         if (hIcon)
    00327                         {
    00328                                 m_Images.Add(hIcon);
    00329                                 DestroyIcon(hIcon);
    00330                         }
    00331                         hIcon = m_DefaultImages.ExtractIcon(1);
    00332                         {
    00333                                 m_Images.Add(hIcon);
    00334                                 DestroyIcon(hIcon);
    00335                         }
    00336                 }
    00337         }
    00338
    00339         // insert tree items
    00340         for (int nPage = 0; nPage < nPageCount; ++nPage)
    00341         {
    00342                 // Get title and image of the page
    00343                 CString strPagePath;
    00344
    00345                 TCITEM  ti;
    00346                 ZeroMemory(&ti, sizeof(ti));
    00347                 ti.mask = TCIF_TEXT|TCIF_IMAGE;
    00348                 ti.cchTextMax = MAX_PATH;
    00349                 ti.pszText = strPagePath.GetBuffer(ti.cchTextMax);
    00350                 ASSERT(ti.pszText);
    00351                 if (!ti.pszText)
    00352                         return;
    00353
    00354                 pTabCtrl->GetItem(nPage, &ti);
    00355                 strPagePath.ReleaseBuffer();
    00356
    00357                 // Create an item in the tree for the page
    00358                 HTREEITEM       hItem = CreatePageTreeItem(ti.pszText);
    00359                 ASSERT(hItem);
    00360                 if (hItem)
    00361                 {
    00362                         m_pwndPageTree->SetItemData(hItem, nPage);
    00363
    00364                         // set image
    00365                         if (m_bTreeImages)
    00366                         {
    00367                                 int     nImage = ti.iImage;
    00368                                 if (nImage < 0 || nImage >= m_Images.GetImageCount())
    00369                                         nImage = m_DefaultImages.GetSafeHandle()? m_Images.GetImageCount()-1 : -1;
    00370
    00371                                 m_pwndPageTree->SetItemImage(hItem, nImage, nImage);
    00372                         }
    00373                 }
    00374         }
    00375 }
    00376
    00377
    00378 HTREEITEM CTreePropSheet::CreatePageTreeItem(LPCTSTR lpszPath, HTREEITEM hParent /* = TVI_ROOT */)
    00379 {
    00380         CString         strPath(lpszPath);
    00381         CString         strTopMostItem(SplitPageTreePath(strPath));
    00382
    00383         // Check if an item with the given text does already exist
    00384         HTREEITEM       hItem = NULL;
    00385         HTREEITEM       hChild = m_pwndPageTree->GetChildItem(hParent);
    00386         while (hChild)
    00387         {
    00388                 if (m_pwndPageTree->GetItemText(hChild) == strTopMostItem)
    00389                 {
    00390                         hItem = hChild;
    00391                         break;
    00392                 }
    00393                 hChild = m_pwndPageTree->GetNextItem(hChild, TVGN_NEXT);
    00394         }
    00395
    00396         // If item with that text does not already exist, create a new one
    00397         if (!hItem)
    00398         {
    00399                 hItem = m_pwndPageTree->InsertItem(strTopMostItem, hParent);
    00400                 m_pwndPageTree->SetItemData(hItem, -1);
    00401                 if (!strPath.IsEmpty() && m_bTreeImages && m_DefaultImages.GetSafeHandle())
    00402                         // set folder image
    00403                         m_pwndPageTree->SetItemImage(hItem, m_Images.GetImageCount()-2, m_Images.GetImageCount()-2);
    00404         }
    00405         if (!hItem)
    00406         {
    00407                 ASSERT(FALSE);
    00408                 return NULL;
    00409         }
    00410
    00411         if (strPath.IsEmpty())
    00412                 return hItem;
    00413         else
    00414                 return CreatePageTreeItem(strPath, hItem);
    00415 }
    00416
    00417
    00418 CString CTreePropSheet::SplitPageTreePath(CString &strRest)
    00419 {
    00420         int     nSeperatorPos = 0;
    00421         while (TRUE)
    00422         {
    00423                 nSeperatorPos = strRest.Find(_T("::"), nSeperatorPos);
    00424                 if (nSeperatorPos == -1)
    00425                 {
    00426                         CString strItem(strRest);
    00427                         strRest.Empty();
    00428                         return strItem;
    00429                 }
    00430                 else if (nSeperatorPos>0)
    00431                 {
    00432                         // if there is an odd number of backslashes infront of the
    00433                         // seperator, than do not interpret it as separator
    00434                         int     nBackslashCount = 0;
    00435                         for (int nPos = nSeperatorPos-1; nPos >= 0 && strRest[nPos]==_T('\\'); --nPos, ++nBackslashCount);
    00436                         if (nBackslashCount%2 == 0)
    00437                                 break;
    00438                         else
    00439                                 ++nSeperatorPos;
    00440                 }
    00441         }
    00442
    00443         CString strItem(strRest.Left(nSeperatorPos));
    00444         strItem.Replace(_T("\\::"), _T("::"));
    00445         strItem.Replace(_T("\\\\"), _T("\\"));
    00446         strRest = strRest.Mid(nSeperatorPos+2);
    00447         return strItem;
    00448 }
    00449
    00450
    00451 BOOL CTreePropSheet::KillActiveCurrentPage()
    00452 {
    00453         HWND    hCurrentPage = PropSheet_GetCurrentPageHwnd(m_hWnd);
    00454         if (!IsWindow(hCurrentPage))
    00455         {
    00456                 ASSERT(FALSE);
    00457                 return TRUE;
    00458         }
    00459
    00460         // Check if the current page is really active (if page is invisible
    00461         // an virtual empty page is the active one.
    00462         if (!::IsWindowVisible(hCurrentPage))
    00463                 return TRUE;
    00464
    00465         // Try to deactivate current page
    00466         PSHNOTIFY       pshn;
    00467         pshn.hdr.code = PSN_KILLACTIVE;
    00468         pshn.hdr.hwndFrom = m_hWnd;
    00469         pshn.hdr.idFrom = GetDlgCtrlID();
    00470         pshn.lParam = 0;
    00471         if (::SendMessage(hCurrentPage, WM_NOTIFY, pshn.hdr.idFrom, (LPARAM)&pshn))
    00472                 // current page does not allow page change
    00473                 return FALSE;
    00474
    00475         // Hide the page
    00476         ::ShowWindow(hCurrentPage, SW_HIDE);
    00477
    00478         return TRUE;
    00479 }
    00480
    00481
    00482 HTREEITEM CTreePropSheet::GetPageTreeItem(int nPage, HTREEITEM hRoot /* = TVI_ROOT */)
    00483 {
    00484         // Special handling for root case
    00485         if (hRoot == TVI_ROOT)
    00486                 hRoot = m_pwndPageTree->GetNextItem(NULL, TVGN_ROOT);
    00487
    00488         // Check parameters
    00489         if (nPage < 0 || nPage >= GetPageCount())
    00490         {
    00491                 ASSERT(FALSE);
    00492                 return NULL;
    00493         }
    00494
    00495         if (hRoot == NULL)
    00496         {
    00497                 ASSERT(FALSE);
    00498                 return NULL;
    00499         }
    00500
    00501         // we are performing a simple linear search here, because we are
    00502         // expecting only little data
    00503         HTREEITEM       hItem = hRoot;
    00504         while (hItem)
    00505         {
    00506                 if ((signed)m_pwndPageTree->GetItemData(hItem) == nPage)
    00507                         return hItem;
    00508                 if (m_pwndPageTree->ItemHasChildren(hItem))
    00509                 {
    00510                         HTREEITEM       hResult = GetPageTreeItem(nPage, m_pwndPageTree->GetNextItem(hItem, TVGN_CHILD));
    00511                         if (hResult)
    00512                                 return hResult;
    00513                 }
    00514
    00515                 hItem = m_pwndPageTree->GetNextItem(hItem, TVGN_NEXT);
    00516         }
    00517
    00518         // we've found nothing, if we arrive here
    00519         return hItem;
    00520 }
    00521
    00522
    00523 BOOL CTreePropSheet::SelectPageTreeItem(int nPage)
    00524 {
    00525         HTREEITEM       hItem = GetPageTreeItem(nPage);
    00526         if (!hItem)
    00527                 return FALSE;
    00528
    00529         return m_pwndPageTree->SelectItem(hItem);
    00530 }
    00531
    00532
    00533 BOOL CTreePropSheet::SelectCurrentPageTreeItem()
    00534 {
    00535         CTabCtrl        *pTab = GetTabControl();
    00536         if (!IsWindow(pTab->GetSafeHwnd()))
    00537                 return FALSE;
    00538
    00539         return SelectPageTreeItem(pTab->GetCurSel());
    00540 }
    00541
    00542
    00543 void CTreePropSheet::UpdateCaption()
    00544 {
    00545         HWND                    hPage = PropSheet_GetCurrentPageHwnd(GetSafeHwnd());
    00546         BOOL                    bRealPage = IsWindow(hPage) && ::IsWindowVisible(hPage);
    00547         HTREEITEM       hItem = m_pwndPageTree->GetSelectedItem();
    00548         if (!hItem)
    00549                 return;
    00550         CString         strCaption = m_pwndPageTree->GetItemText(hItem);
    00551
    00552         // if empty page, then update empty page message
    00553         if (!bRealPage)
    00554                 m_pFrame->SetMsgText(GenerateEmptyPageMessage(m_strEmptyPageMessage, strCaption));
    00555
    00556         // if no captions are displayed, cancel here
    00557         if (!m_pFrame->GetShowCaption())
    00558                 return;
    00559
    00560         // get tab control, to the the images from
    00561         CTabCtrl        *pTabCtrl = GetTabControl();
    00562         if (!IsWindow(pTabCtrl->GetSafeHwnd()))
    00563         {
    00564                 ASSERT(FALSE);
    00565                 return;
    00566         }
    00567
    00568         if (m_bTreeImages)
    00569         {
    00570                 // get image from tree
    00571                 int     nImage;
    00572                 m_pwndPageTree->GetItemImage(hItem, nImage, nImage);
    00573                 HICON   hIcon = m_Images.ExtractIcon(nImage);
    00574                 m_pFrame->SetCaption(strCaption, hIcon);
    00575                 if (hIcon)
    00576                         DestroyIcon(hIcon);
    00577         }
    00578         else if (bRealPage)
    00579         {
    00580                 // get image from hidden (original) tab provided by the original
    00581                 // implementation
    00582                 CImageList      *pImages = pTabCtrl->GetImageList();
    00583                 if (pImages)
    00584                 {
    00585                         TCITEM  ti;
    00586                         ZeroMemory(&ti, sizeof(ti));
    00587                         ti.mask = TCIF_IMAGE;
    00588
    00589                         HICON   hIcon = NULL;
    00590                         if (pTabCtrl->GetItem((int)m_pwndPageTree->GetItemData(hItem), &ti))
    00591                                 hIcon = pImages->ExtractIcon(ti.iImage);
    00592
    00593                         m_pFrame->SetCaption(strCaption, hIcon);
    00594                         if (hIcon)
    00595                                 DestroyIcon(hIcon);
    00596                 }
    00597                 else
    00598                         m_pFrame->SetCaption(strCaption);
    00599         }
    00600         else
    00601                 m_pFrame->SetCaption(strCaption);
    00602 }
    00603
    00604
    00605 void CTreePropSheet::ActivatePreviousPage()
    00606 {
    00607         if (!IsWindow(m_hWnd))
    00608                 return;
    00609
    00610         if (!IsWindow(m_pwndPageTree->GetSafeHwnd()))
    00611         {
    00612                 // normal tab property sheet. Simply use page index
    00613                 int     nPageIndex = GetActiveIndex();
    00614                 if (nPageIndex<0 || nPageIndex>=GetPageCount())
    00615                         return;
    00616
    00617                 int     nPrevIndex = (nPageIndex==0)? GetPageCount()-1 : nPageIndex-1;
    00618                 SetActivePage(nPrevIndex);
    00619         }
    00620         else
    00621         {
    00622                 // property sheet with page tree.
    00623                 // we need a more sophisticated handling here, than simply using
    00624                 // the page index, because we won't skip empty pages.
    00625                 // so we have to walk the page tree
    00626                 HTREEITEM       hItem = m_pwndPageTree->GetSelectedItem();
    00627                 ASSERT(hItem);
    00628                 if (!hItem)
    00629                         return;
    00630
    00631                 HTREEITEM       hPrevItem = NULL;
    00632                 if (hPrevItem=m_pwndPageTree->GetPrevSiblingItem(hItem))
    00633                 {
    00634                         while (m_pwndPageTree->ItemHasChildren(hPrevItem))
    00635                         {
    00636                                 hPrevItem = m_pwndPageTree->GetChildItem(hPrevItem);
    00637                                 while (m_pwndPageTree->GetNextSiblingItem(hPrevItem))
    00638                                         hPrevItem = m_pwndPageTree->GetNextSiblingItem(hPrevItem);
    00639                         }
    00640                 }
    00641                 else
    00642                         hPrevItem=m_pwndPageTree->GetParentItem(hItem);
    00643
    00644                 if (!hPrevItem)
    00645                 {
    00646                         // no prev item, so cycle to the last item
    00647                         hPrevItem = m_pwndPageTree->GetRootItem();
    00648
    00649                         while (TRUE)
    00650                         {
    00651                                 while (m_pwndPageTree->GetNextSiblingItem(hPrevItem))
    00652                                         hPrevItem = m_pwndPageTree->GetNextSiblingItem(hPrevItem);
    00653
    00654                                 if (m_pwndPageTree->ItemHasChildren(hPrevItem))
    00655                                         hPrevItem = m_pwndPageTree->GetChildItem(hPrevItem);
    00656                                 else
    00657                                         break;
    00658                         }
    00659                 }
    00660
    00661                 if (hPrevItem)
    00662                         m_pwndPageTree->SelectItem(hPrevItem);
    00663         }
    00664 }
    00665
    00666
    00667 void CTreePropSheet::ActivateNextPage()
    00668 {
    00669         if (!IsWindow(m_hWnd))
    00670                 return;
    00671
    00672         if (!IsWindow(m_pwndPageTree->GetSafeHwnd()))
    00673         {
    00674                 // normal tab property sheet. Simply use page index
    00675                 int     nPageIndex = GetActiveIndex();
    00676                 if (nPageIndex<0 || nPageIndex>=GetPageCount())
    00677                         return;
    00678
    00679                 int     nNextIndex = (nPageIndex==GetPageCount()-1)? 0 : nPageIndex+1;
    00680                 SetActivePage(nNextIndex);
    00681         }
    00682         else
    00683         {
    00684                 // property sheet with page tree.
    00685                 // we need a more sophisticated handling here, than simply using
    00686                 // the page index, because we won't skip empty pages.
    00687                 // so we have to walk the page tree
    00688                 HTREEITEM       hItem = m_pwndPageTree->GetSelectedItem();
    00689                 ASSERT(hItem);
    00690                 if (!hItem)
    00691                         return;
    00692
    00693                 HTREEITEM       hNextItem = NULL;
    00694                 if (hNextItem=m_pwndPageTree->GetChildItem(hItem))
    00695                         ;
    00696                 else if (hNextItem=m_pwndPageTree->GetNextSiblingItem(hItem))
    00697                         ;
    00698                 else if (m_pwndPageTree->GetParentItem(hItem))
    00699                 {
    00700                         while (!hNextItem)
    00701                         {
    00702                                 hItem = m_pwndPageTree->GetParentItem(hItem);
    00703                                 if (!hItem)
    00704                                         break;
    00705
    00706                                 hNextItem       = m_pwndPageTree->GetNextSiblingItem(hItem);
    00707                         }
    00708                 }
    00709
    00710                 if (!hNextItem)
    00711                         // no next item -- so cycle to the first item
    00712                         hNextItem = m_pwndPageTree->GetRootItem();
    00713
    00714                 if (hNextItem)
    00715                         m_pwndPageTree->SelectItem(hNextItem);
    00716         }
    00717 }
    00718
    00719
    00721 // Overridings
    00722
    00723 BOOL CTreePropSheet::OnInitDialog()
    00724 {
    00725         if (m_bTreeViewMode)
    00726         {
    00727                 // be sure, there are no stacked tabs, because otherwise the
    00728                 // page caption will be to large in tree view mode
    00729                 EnableStackedTabs(FALSE);
    00730
    00731                 // Initialize image list.
    00732                 if (m_DefaultImages.GetSafeHandle())
    00733                 {
    00734                         IMAGEINFO       ii;
    00735                         m_DefaultImages.GetImageInfo(0, &ii);
    00736                         if (ii.hbmImage) DeleteObject(ii.hbmImage);
    00737                         if (ii.hbmMask) DeleteObject(ii.hbmMask);
    00738                         m_Images.Create(ii.rcImage.right-ii.rcImage.left, ii.rcImage.bottom-ii.rcImage.top, ILC_COLOR32|ILC_MASK, 0, 1);
    00739                 }
    00740                 else
    00741                         m_Images.Create(16, 16, ILC_COLOR32|ILC_MASK, 0, 1);
    00742         }
    00743
    00744         // perform default implementation
    00745         BOOL bResult = __super::OnInitDialog();
    00746
    00747         if (!m_bTreeViewMode)
    00748                 // stop here, if we would like to use tabs
    00749                 return bResult;
    00750
    00751         // Get tab control...
    00752         CTabCtrl        *pTab = GetTabControl();
    00753         if (!IsWindow(pTab->GetSafeHwnd()))
    00754         {
    00755                 ASSERT(FALSE);
    00756                 return bResult;
    00757         }
    00758
    00759         // ... and hide it
    00760         pTab->ShowWindow(SW_HIDE);
    00761         pTab->EnableWindow(FALSE);
    00762
    00763         // Place another (empty) tab ctrl, to get a frame instead
    00764         CRect   rectFrame;
    00765         pTab->GetWindowRect(rectFrame);
    00766         ScreenToClient(rectFrame);
    00767
    00768         m_pFrame = CreatePageFrame();
    00769         if (!m_pFrame)
    00770         {
    00771                 ASSERT(FALSE);
    00772                 AfxThrowMemoryException();
    00773         }
    00774         m_pFrame->Create(WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS, rectFrame, this, 0xFFFF);
    00775         m_pFrame->ShowCaption(m_bPageCaption);
    00776
    00777         // Lets make place for the tree ctrl
    00778         const int       nTreeWidth = m_nPageTreeWidth;
    00779         const int       nTreeSpace = 5;
    00780
    00781         CRect   rectSheet;
    00782         GetWindowRect(rectSheet);
    00783         rectSheet.right+= nTreeWidth;
    00784         SetWindowPos(NULL, -1, -1, rectSheet.Width(), rectSheet.Height(), SWP_NOZORDER|SWP_NOMOVE);
    00785         CenterWindow();
    00786
    00787         MoveChildWindows(nTreeWidth, 0);
    00788
    00789         // Lets calculate the rectangle for the tree ctrl
    00790         CRect   rectTree(rectFrame);
    00791         rectTree.right = rectTree.left + nTreeWidth - nTreeSpace;
    00792
    00793         // calculate caption height
    00794         CTabCtrl        wndTabCtrl;
    00795         wndTabCtrl.Create(WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS, rectFrame, this, 0x1234);
    00796         wndTabCtrl.InsertItem(0, _T(""));
    00797         CRect   rectFrameCaption;
    00798         wndTabCtrl.GetItemRect(0, rectFrameCaption);
    00799         wndTabCtrl.DestroyWindow();
    00800         m_pFrame->SetCaptionHeight(rectFrameCaption.Height());
    00801
    00802         // if no caption should be displayed, make the window smaller in
    00803         // height
    00804         if (!m_bPageCaption)
    00805         {
    00806                 // make frame smaller
    00807                 m_pFrame->GetWnd()->GetWindowRect(rectFrame);
    00808                 ScreenToClient(rectFrame);
    00809                 rectFrame.top+= rectFrameCaption.Height();
    00810                 m_pFrame->GetWnd()->MoveWindow(rectFrame);
    00811
    00812                 // move all child windows up
    00813                 MoveChildWindows(0, -rectFrameCaption.Height());
    00814
    00815                 // modify rectangle for the tree ctrl
    00816                 rectTree.bottom-= rectFrameCaption.Height();
    00817
    00818                 // make us smaller
    00819                 CRect   rect;
    00820                 GetWindowRect(rect);
    00821                 rect.top+= rectFrameCaption.Height()/2;
    00822                 rect.bottom-= rectFrameCaption.Height()-rectFrameCaption.Height()/2;
    00823 //              if (GetParent())
    00824 //                      GetParent()->ScreenToClient(rect);
    00825                 MoveWindow(rect);
    00826         }
    00827
    00828         // finally create tht tree control
    00829         const DWORD     dwTreeStyle = TVS_SHOWSELALWAYS|TVS_TRACKSELECT|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS;
    00830         m_pwndPageTree = CreatePageTreeObject();
    00831         if (!m_pwndPageTree)
    00832         {
    00833                 ASSERT(FALSE);
    00834                 AfxThrowMemoryException();
    00835         }
    00836
    00837         // MFC7-support here (Thanks to Rainer Wollgarten)
    00838         #if _MFC_VER >= 0x0700
    00839         {
    00840                 m_pwndPageTree->CreateEx(
    00841                         WS_EX_CLIENTEDGE|WS_EX_NOPARENTNOTIFY,
    00842                         WS_TABSTOP|WS_CHILD|WS_VISIBLE|dwTreeStyle,
    00843                         rectTree, this, s_unPageTreeId);
    00844         }
    00845         #else
    00846         {
    00847                 m_pwndPageTree->CreateEx(
    00848                         WS_EX_CLIENTEDGE|WS_EX_NOPARENTNOTIFY,
    00849                         _T("SysTreeView32"), _T("PageTree"),
    00850                         WS_TABSTOP|WS_CHILD|WS_VISIBLE|dwTreeStyle,
    00851                         rectTree, this, s_unPageTreeId);
    00852         }
    00853         #endif
    00854
    00855         if (m_bTreeImages)
    00856         {
    00857                 m_pwndPageTree->SetImageList(&m_Images, TVSIL_NORMAL);
    00858                 m_pwndPageTree->SetImageList(&m_Images, TVSIL_STATE);
    00859         }
    00860
    00861         // Fill the tree ctrl
    00862         RefillPageTree();
    00863
    00864         // Select item for the current page
    00865         if (pTab->GetCurSel() > -1)
    00866                 SelectPageTreeItem(pTab->GetCurSel());
    00867
    00868         return bResult;
    00869 }
    00870
    00871
    00872 void CTreePropSheet::OnDestroy()
    00873 {
    00874         __super::OnDestroy();
    00875
    00876         if(m_pwndPageTree && m_pwndPageTree->m_hWnd)
    00877                 m_pwndPageTree->DestroyWindow();
    00878
    00879         if(m_pFrame && m_pFrame->GetWnd()->m_hWnd)
    00880                 m_pFrame->GetWnd()->DestroyWindow();
    00881 }
    00882
    00883
    00884 LRESULT CTreePropSheet::OnAddPage(WPARAM wParam, LPARAM lParam)
    00885 {
    00886         LRESULT lResult = DefWindowProc(PSM_ADDPAGE, wParam, lParam);
    00887         if (!m_bTreeViewMode)
    00888                 return lResult;
    00889
    00890         RefillPageTree();
    00891         SelectCurrentPageTreeItem();
    00892
    00893         return lResult;
    00894 }
    00895
    00896
    00897 LRESULT CTreePropSheet::OnRemovePage(WPARAM wParam, LPARAM lParam)
    00898 {
    00899         LRESULT lResult = DefWindowProc(PSM_REMOVEPAGE, wParam, lParam);
    00900         if (!m_bTreeViewMode)
    00901                 return lResult;
    00902
    00903         RefillPageTree();
    00904         SelectCurrentPageTreeItem();
    00905
    00906         return lResult;
    00907 }
    00908
    00909
    00910 LRESULT CTreePropSheet::OnSetCurSel(WPARAM wParam, LPARAM lParam)
    00911 {
    00912         LRESULT lResult = DefWindowProc(PSM_SETCURSEL, wParam, lParam);
    00913         if (!m_bTreeViewMode)
    00914                 return lResult;
    00915
    00916         SelectCurrentPageTreeItem();
    00917         UpdateCaption();
    00918         return lResult;
    00919 }
    00920
    00921
    00922 LRESULT CTreePropSheet::OnSetCurSelId(WPARAM wParam, LPARAM lParam)
    00923 {
    00924         LRESULT lResult = DefWindowProc(PSM_SETCURSEL, wParam, lParam);
    00925         if (!m_bTreeViewMode)
    00926                 return lResult;
    00927
    00928         SelectCurrentPageTreeItem();
    00929         UpdateCaption();
    00930         return lResult;
    00931 }
    00932
    00933
    00934 void CTreePropSheet::OnPageTreeSelChanging(NMHDR *pNotifyStruct, LRESULT *plResult)
    00935 {
    00936         *plResult = 0;
    00937         if (m_bPageTreeSelChangedActive)
    00938                 return;
    00939         else
    00940                 m_bPageTreeSelChangedActive = TRUE;
    00941
    00942         NMTREEVIEW      *pTvn = reinterpret_cast<NMTREEVIEW*>(pNotifyStruct);
    00943         int                                     nPage = m_pwndPageTree->GetItemData(pTvn->itemNew.hItem);
    00944         BOOL                            bResult;
    00945         if (nPage<0 || (unsigned)nPage>=m_pwndPageTree->GetCount())
    00946                 bResult = KillActiveCurrentPage();
    00947         else
    00948                 bResult = SetActivePage(nPage);
    00949
    00950         if (!bResult)
    00951                 // prevent selection to change
    00952                 *plResult = TRUE;
    00953
    00954         // Set focus to tree ctrl (I guess that's what the user expects)
    00955         m_pwndPageTree->SetFocus();
    00956
    00957         m_bPageTreeSelChangedActive = FALSE;
    00958
    00959         return;
    00960 }
    00961
    00962
    00963 void CTreePropSheet::OnPageTreeSelChanged(NMHDR *pNotifyStruct, LRESULT *plResult)
    00964 {
    00965         *plResult = 0;
    00966
    00967         UpdateCaption();
    00968
    00969         return;
    00970 }
    00971
    00972
    00973 LRESULT CTreePropSheet::OnIsDialogMessage(WPARAM wParam, LPARAM lParam)
    00974 {
    00975         MSG     *pMsg = reinterpret_cast<MSG*>(lParam);
    00976         if (pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_TAB && GetKeyState(VK_CONTROL)&0x8000)
    00977         {
    00978                 if (GetKeyState(VK_SHIFT)&0x8000)
    00979                         ActivatePreviousPage();
    00980                 else
    00981                         ActivateNextPage();
    00982                 return TRUE;
    00983         }
    00984
    00985
    00986         return __super::DefWindowProc(PSM_ISDIALOGMESSAGE, wParam, lParam);
    00987 }
    00988
    00989 } //namespace TreePropSheet