TreePropSheet.cpp

00001 /********************************************************************
00002 *
00003 * Copyright (c) 2002 Sven Wiegand <[email protected]>
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

Generated on Tue Dec 13 14:47:58 2005 for guliverkli by  doxygen 1.4.5