TreePropSheet.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:23k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /********************************************************************
  2. *
  3. * Copyright (c) 2002 Sven Wiegand <mail@sven-wiegand.de>
  4. *
  5. * You can use this and modify this in any way you want,
  6. * BUT LEAVE THIS HEADER INTACT.
  7. *
  8. * Redistribution is appreciated.
  9. *
  10. * $Workfile:$
  11. * $Revision: 1.2 $
  12. * $Modtime:$
  13. * $Author: gabest $
  14. *
  15. * Revision History:
  16. * $History:$
  17. *
  18. *********************************************************************/
  19. #include "stdafx.h"
  20. #include "TreePropSheet.h"
  21. #include "PropPageFrameDefault.h"
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. namespace TreePropSheet
  28. {
  29. //-------------------------------------------------------------------
  30. // class CTreePropSheet
  31. //-------------------------------------------------------------------
  32. BEGIN_MESSAGE_MAP(CTreePropSheet, CPropertySheet)
  33. //{{AFX_MSG_MAP(CTreePropSheet)
  34. ON_WM_DESTROY()
  35. //}}AFX_MSG_MAP
  36. ON_MESSAGE(PSM_ADDPAGE, OnAddPage)
  37. ON_MESSAGE(PSM_REMOVEPAGE, OnRemovePage)
  38. ON_MESSAGE(PSM_SETCURSEL, OnSetCurSel)
  39. ON_MESSAGE(PSM_SETCURSELID, OnSetCurSelId)
  40. ON_MESSAGE(PSM_ISDIALOGMESSAGE, OnIsDialogMessage)
  41. ON_NOTIFY(TVN_SELCHANGINGA, s_unPageTreeId, OnPageTreeSelChanging)
  42. ON_NOTIFY(TVN_SELCHANGINGW, s_unPageTreeId, OnPageTreeSelChanging)
  43. ON_NOTIFY(TVN_SELCHANGEDA, s_unPageTreeId, OnPageTreeSelChanged)
  44. ON_NOTIFY(TVN_SELCHANGEDW, s_unPageTreeId, OnPageTreeSelChanged)
  45. END_MESSAGE_MAP()
  46. IMPLEMENT_DYNAMIC(CTreePropSheet, CPropertySheet)
  47. const UINT CTreePropSheet::s_unPageTreeId = 0x7EEE;
  48. CTreePropSheet::CTreePropSheet()
  49. : m_bPageTreeSelChangedActive(FALSE),
  50. m_bTreeViewMode(TRUE),
  51. m_bPageCaption(FALSE),
  52. m_bTreeImages(FALSE),
  53. m_nPageTreeWidth(150),
  54. m_pwndPageTree(NULL),
  55. m_pFrame(NULL)
  56. {}
  57. CTreePropSheet::CTreePropSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
  58. : CPropertySheet(nIDCaption, pParentWnd, iSelectPage),
  59. m_bPageTreeSelChangedActive(FALSE),
  60. m_bTreeViewMode(TRUE),
  61. m_bPageCaption(FALSE),
  62. m_bTreeImages(FALSE),
  63. m_nPageTreeWidth(150),
  64. m_pwndPageTree(NULL),
  65. m_pFrame(NULL)
  66. {
  67. }
  68. CTreePropSheet::CTreePropSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
  69. : CPropertySheet(pszCaption, pParentWnd, iSelectPage),
  70. m_bPageTreeSelChangedActive(FALSE),
  71. m_bTreeViewMode(TRUE),
  72. m_bPageCaption(FALSE),
  73. m_bTreeImages(FALSE),
  74. m_nPageTreeWidth(150),
  75. m_pwndPageTree(NULL),
  76. m_pFrame(NULL)
  77. {
  78. }
  79. CTreePropSheet::~CTreePropSheet()
  80. {
  81. if(m_Images.GetSafeHandle()) m_Images.DeleteImageList();
  82. delete m_pwndPageTree, m_pwndPageTree = NULL;
  83. delete m_pFrame, m_pFrame = NULL;
  84. }
  85. /////////////////////////////////////////////////////////////////////
  86. // Operationen
  87. BOOL CTreePropSheet::SetTreeViewMode(BOOL bTreeViewMode /* = TRUE */, BOOL bPageCaption /* = FALSE */, BOOL bTreeImages /* = FALSE */)
  88. {
  89. if (IsWindow(m_hWnd))
  90. {
  91. // needs to becalled, before the window has been created
  92. ASSERT(FALSE);
  93. return FALSE;
  94. }
  95. m_bTreeViewMode = bTreeViewMode;
  96. if (m_bTreeViewMode)
  97. {
  98. m_bPageCaption = bPageCaption;
  99. m_bTreeImages = bTreeImages;
  100. }
  101. return TRUE;
  102. }
  103. BOOL CTreePropSheet::SetTreeWidth(int nWidth)
  104. {
  105. if (IsWindow(m_hWnd))
  106. {
  107. // needs to be called, before the window is created.
  108. ASSERT(FALSE);
  109. return FALSE;
  110. }
  111. m_nPageTreeWidth = nWidth;
  112. return TRUE;
  113. }
  114. void CTreePropSheet::SetEmptyPageText(LPCTSTR lpszEmptyPageText)
  115. {
  116. m_strEmptyPageMessage = lpszEmptyPageText;
  117. }
  118. DWORD CTreePropSheet::SetEmptyPageTextFormat(DWORD dwFormat)
  119. {
  120. DWORD dwPrevFormat = m_pFrame->GetMsgFormat();
  121. m_pFrame->SetMsgFormat(dwFormat);
  122. return dwPrevFormat;
  123. }
  124. BOOL CTreePropSheet::SetTreeDefaultImages(CImageList *pImages)
  125. {
  126. if (pImages->GetImageCount() != 2)
  127. {
  128. ASSERT(FALSE);
  129. return FALSE;
  130. }
  131. if (m_DefaultImages.GetSafeHandle())
  132. m_DefaultImages.DeleteImageList();
  133. m_DefaultImages.Create(pImages);
  134. // update, if necessary
  135. if (IsWindow(m_hWnd))
  136. RefillPageTree();
  137. return TRUE;
  138. }
  139. BOOL CTreePropSheet::SetTreeDefaultImages(UINT unBitmapID, int cx, COLORREF crMask)
  140. {
  141. if (m_DefaultImages.GetSafeHandle())
  142. m_DefaultImages.DeleteImageList();
  143. if (!m_DefaultImages.Create(unBitmapID, cx, 0, crMask))
  144. return FALSE;
  145. if (m_DefaultImages.GetImageCount() != 2)
  146. {
  147. m_DefaultImages.DeleteImageList();
  148. return FALSE;
  149. }
  150. return TRUE;
  151. }
  152. CTreeCtrl* CTreePropSheet::GetPageTreeControl()
  153. {
  154. return m_pwndPageTree;
  155. }
  156. /////////////////////////////////////////////////////////////////////
  157. // public helpers
  158. BOOL CTreePropSheet::SetPageIcon(CPropertyPage *pPage, HICON hIcon)
  159. {
  160. pPage->m_psp.dwFlags|= PSP_USEHICON;
  161. pPage->m_psp.hIcon = hIcon;
  162. return TRUE;
  163. }
  164. BOOL CTreePropSheet::SetPageIcon(CPropertyPage *pPage, UINT unIconId)
  165. {
  166. HICON hIcon = AfxGetApp()->LoadIcon(unIconId);
  167. if (!hIcon)
  168. return FALSE;
  169. return SetPageIcon(pPage, hIcon);
  170. }
  171. BOOL CTreePropSheet::SetPageIcon(CPropertyPage *pPage, CImageList &Images, int nImage)
  172. {
  173. HICON hIcon = Images.ExtractIcon(nImage);
  174. if (!hIcon)
  175. return FALSE;
  176. return SetPageIcon(pPage, hIcon);
  177. }
  178. BOOL CTreePropSheet::DestroyPageIcon(CPropertyPage *pPage)
  179. {
  180. if (!pPage || !(pPage->m_psp.dwFlags&PSP_USEHICON) || !pPage->m_psp.hIcon)
  181. return FALSE;
  182. DestroyIcon(pPage->m_psp.hIcon);
  183. pPage->m_psp.dwFlags&= ~PSP_USEHICON;
  184. pPage->m_psp.hIcon = NULL;
  185. return TRUE;
  186. }
  187. /////////////////////////////////////////////////////////////////////
  188. // Overridable implementation helpers
  189. CString CTreePropSheet::GenerateEmptyPageMessage(LPCTSTR lpszEmptyPageMessage, LPCTSTR lpszCaption)
  190. {
  191. CString strMsg;
  192. strMsg.Format(lpszEmptyPageMessage, lpszCaption);
  193. return strMsg;
  194. }
  195. CTreeCtrl* CTreePropSheet::CreatePageTreeObject()
  196. {
  197. return new CTreeCtrl;
  198. }
  199. CPropPageFrame* CTreePropSheet::CreatePageFrame()
  200. {
  201. return new CPropPageFrameDefault;
  202. }
  203. /////////////////////////////////////////////////////////////////////
  204. // Implementation helpers
  205. void CTreePropSheet::MoveChildWindows(int nDx, int nDy)
  206. {
  207. CWnd *pWnd = GetWindow(GW_CHILD);
  208. while (pWnd)
  209. {
  210. CRect rect;
  211. pWnd->GetWindowRect(rect);
  212. rect.OffsetRect(nDx, nDy);
  213. ScreenToClient(rect);
  214. pWnd->MoveWindow(rect);
  215. pWnd = pWnd->GetNextWindow();
  216. }
  217. }
  218. void CTreePropSheet::RefillPageTree()
  219. {
  220. if (!IsWindow(m_hWnd))
  221. return;
  222. m_pwndPageTree->DeleteAllItems();
  223. CTabCtrl *pTabCtrl = GetTabControl();
  224. if (!IsWindow(pTabCtrl->GetSafeHwnd()))
  225. {
  226. ASSERT(FALSE);
  227. return;
  228. }
  229. const int nPageCount = pTabCtrl->GetItemCount();
  230. // rebuild image list
  231. if (m_bTreeImages)
  232. {
  233. for (int i = m_Images.GetImageCount()-1; i >= 0; --i)
  234. m_Images.Remove(i);
  235. // add page images
  236. CImageList *pPageImages = pTabCtrl->GetImageList();
  237. if (pPageImages)
  238. {
  239. for (int nImage = 0; nImage < pPageImages->GetImageCount(); ++nImage)
  240. {
  241. HICON hIcon = pPageImages->ExtractIcon(nImage);
  242. m_Images.Add(hIcon);
  243. DestroyIcon(hIcon);
  244. }
  245. }
  246. // add default images
  247. if (m_DefaultImages.GetSafeHandle())
  248. {
  249. HICON hIcon;
  250. // add default images
  251. hIcon = m_DefaultImages.ExtractIcon(0);
  252. if (hIcon)
  253. {
  254. m_Images.Add(hIcon);
  255. DestroyIcon(hIcon);
  256. }
  257. hIcon = m_DefaultImages.ExtractIcon(1);
  258. {
  259. m_Images.Add(hIcon);
  260. DestroyIcon(hIcon);
  261. }
  262. }
  263. }
  264. // insert tree items
  265. for (int nPage = 0; nPage < nPageCount; ++nPage)
  266. {
  267. // Get title and image of the page
  268. CString strPagePath;
  269. TCITEM ti;
  270. ZeroMemory(&ti, sizeof(ti));
  271. ti.mask = TCIF_TEXT|TCIF_IMAGE;
  272. ti.cchTextMax = MAX_PATH;
  273. ti.pszText = strPagePath.GetBuffer(ti.cchTextMax);
  274. ASSERT(ti.pszText);
  275. if (!ti.pszText)
  276. return;
  277. pTabCtrl->GetItem(nPage, &ti);
  278. strPagePath.ReleaseBuffer();
  279. // Create an item in the tree for the page
  280. HTREEITEM hItem = CreatePageTreeItem(ti.pszText);
  281. ASSERT(hItem);
  282. if (hItem)
  283. {
  284. m_pwndPageTree->SetItemData(hItem, nPage);
  285. // set image
  286. if (m_bTreeImages)
  287. {
  288. int nImage = ti.iImage;
  289. if (nImage < 0 || nImage >= m_Images.GetImageCount())
  290. nImage = m_DefaultImages.GetSafeHandle()? m_Images.GetImageCount()-1 : -1;
  291. m_pwndPageTree->SetItemImage(hItem, nImage, nImage);
  292. }
  293. }
  294. }
  295. }
  296. HTREEITEM CTreePropSheet::CreatePageTreeItem(LPCTSTR lpszPath, HTREEITEM hParent /* = TVI_ROOT */)
  297. {
  298. CString strPath(lpszPath);
  299. CString strTopMostItem(SplitPageTreePath(strPath));
  300. // Check if an item with the given text does already exist
  301. HTREEITEM hItem = NULL;
  302. HTREEITEM hChild = m_pwndPageTree->GetChildItem(hParent);
  303. while (hChild)
  304. {
  305. if (m_pwndPageTree->GetItemText(hChild) == strTopMostItem)
  306. {
  307. hItem = hChild;
  308. break;
  309. }
  310. hChild = m_pwndPageTree->GetNextItem(hChild, TVGN_NEXT);
  311. }
  312. // If item with that text does not already exist, create a new one
  313. if (!hItem)
  314. {
  315. hItem = m_pwndPageTree->InsertItem(strTopMostItem, hParent);
  316. m_pwndPageTree->SetItemData(hItem, -1);
  317. if (!strPath.IsEmpty() && m_bTreeImages && m_DefaultImages.GetSafeHandle())
  318. // set folder image
  319. m_pwndPageTree->SetItemImage(hItem, m_Images.GetImageCount()-2, m_Images.GetImageCount()-2);
  320. }
  321. if (!hItem)
  322. {
  323. ASSERT(FALSE);
  324. return NULL;
  325. }
  326. if (strPath.IsEmpty())
  327. return hItem;
  328. else
  329. return CreatePageTreeItem(strPath, hItem);
  330. }
  331. CString CTreePropSheet::SplitPageTreePath(CString &strRest)
  332. {
  333. int nSeperatorPos = 0;
  334. while (TRUE)
  335. {
  336. nSeperatorPos = strRest.Find(_T("::"), nSeperatorPos);
  337. if (nSeperatorPos == -1)
  338. {
  339. CString strItem(strRest);
  340. strRest.Empty();
  341. return strItem;
  342. }
  343. else if (nSeperatorPos>0)
  344. {
  345. // if there is an odd number of backslashes infront of the
  346. // seperator, than do not interpret it as separator
  347. int nBackslashCount = 0;
  348. for (int nPos = nSeperatorPos-1; nPos >= 0 && strRest[nPos]==_T('\'); --nPos, ++nBackslashCount);
  349. if (nBackslashCount%2 == 0)
  350. break;
  351. else
  352. ++nSeperatorPos;
  353. }
  354. }
  355. CString strItem(strRest.Left(nSeperatorPos));
  356. strItem.Replace(_T("\::"), _T("::"));
  357. strItem.Replace(_T("\\"), _T("\"));
  358. strRest = strRest.Mid(nSeperatorPos+2);
  359. return strItem;
  360. }
  361. BOOL CTreePropSheet::KillActiveCurrentPage()
  362. {
  363. HWND hCurrentPage = PropSheet_GetCurrentPageHwnd(m_hWnd);
  364. if (!IsWindow(hCurrentPage))
  365. {
  366. ASSERT(FALSE);
  367. return TRUE;
  368. }
  369. // Check if the current page is really active (if page is invisible
  370. // an virtual empty page is the active one.
  371. if (!::IsWindowVisible(hCurrentPage))
  372. return TRUE;
  373. // Try to deactivate current page
  374. PSHNOTIFY pshn;
  375. pshn.hdr.code = PSN_KILLACTIVE;
  376. pshn.hdr.hwndFrom = m_hWnd;
  377. pshn.hdr.idFrom = GetDlgCtrlID();
  378. pshn.lParam = 0;
  379. if (::SendMessage(hCurrentPage, WM_NOTIFY, pshn.hdr.idFrom, (LPARAM)&pshn))
  380. // current page does not allow page change
  381. return FALSE;
  382. // Hide the page
  383. ::ShowWindow(hCurrentPage, SW_HIDE);
  384. return TRUE;
  385. }
  386. HTREEITEM CTreePropSheet::GetPageTreeItem(int nPage, HTREEITEM hRoot /* = TVI_ROOT */)
  387. {
  388. // Special handling for root case
  389. if (hRoot == TVI_ROOT)
  390. hRoot = m_pwndPageTree->GetNextItem(NULL, TVGN_ROOT);
  391. // Check parameters
  392. if (nPage < 0 || nPage >= GetPageCount())
  393. {
  394. ASSERT(FALSE);
  395. return NULL;
  396. }
  397. if (hRoot == NULL)
  398. {
  399. ASSERT(FALSE);
  400. return NULL;
  401. }
  402. // we are performing a simple linear search here, because we are
  403. // expecting only little data
  404. HTREEITEM hItem = hRoot;
  405. while (hItem)
  406. {
  407. if ((signed)m_pwndPageTree->GetItemData(hItem) == nPage)
  408. return hItem;
  409. if (m_pwndPageTree->ItemHasChildren(hItem))
  410. {
  411. HTREEITEM hResult = GetPageTreeItem(nPage, m_pwndPageTree->GetNextItem(hItem, TVGN_CHILD));
  412. if (hResult)
  413. return hResult;
  414. }
  415. hItem = m_pwndPageTree->GetNextItem(hItem, TVGN_NEXT);
  416. }
  417. // we've found nothing, if we arrive here
  418. return hItem;
  419. }
  420. BOOL CTreePropSheet::SelectPageTreeItem(int nPage)
  421. {
  422. HTREEITEM hItem = GetPageTreeItem(nPage);
  423. if (!hItem)
  424. return FALSE;
  425. return m_pwndPageTree->SelectItem(hItem);
  426. }
  427. BOOL CTreePropSheet::SelectCurrentPageTreeItem()
  428. {
  429. CTabCtrl *pTab = GetTabControl();
  430. if (!IsWindow(pTab->GetSafeHwnd()))
  431. return FALSE;
  432. return SelectPageTreeItem(pTab->GetCurSel());
  433. }
  434. void CTreePropSheet::UpdateCaption()
  435. {
  436. HWND hPage = PropSheet_GetCurrentPageHwnd(GetSafeHwnd());
  437. BOOL bRealPage = IsWindow(hPage) && ::IsWindowVisible(hPage);
  438. HTREEITEM hItem = m_pwndPageTree->GetSelectedItem();
  439. if (!hItem)
  440. return;
  441. CString strCaption = m_pwndPageTree->GetItemText(hItem);
  442. // if empty page, then update empty page message
  443. if (!bRealPage)
  444. m_pFrame->SetMsgText(GenerateEmptyPageMessage(m_strEmptyPageMessage, strCaption));
  445. // if no captions are displayed, cancel here
  446. if (!m_pFrame->GetShowCaption())
  447. return;
  448. // get tab control, to the the images from
  449. CTabCtrl *pTabCtrl = GetTabControl();
  450. if (!IsWindow(pTabCtrl->GetSafeHwnd()))
  451. {
  452. ASSERT(FALSE);
  453. return;
  454. }
  455. if (m_bTreeImages)
  456. {
  457. // get image from tree
  458. int nImage;
  459. m_pwndPageTree->GetItemImage(hItem, nImage, nImage);
  460. HICON hIcon = m_Images.ExtractIcon(nImage);
  461. m_pFrame->SetCaption(strCaption, hIcon);
  462. if (hIcon)
  463. DestroyIcon(hIcon);
  464. }
  465. else if (bRealPage)
  466. {
  467. // get image from hidden (original) tab provided by the original
  468. // implementation
  469. CImageList *pImages = pTabCtrl->GetImageList();
  470. if (pImages)
  471. {
  472. TCITEM ti;
  473. ZeroMemory(&ti, sizeof(ti));
  474. ti.mask = TCIF_IMAGE;
  475. HICON hIcon = NULL;
  476. if (pTabCtrl->GetItem((int)m_pwndPageTree->GetItemData(hItem), &ti))
  477. hIcon = pImages->ExtractIcon(ti.iImage);
  478. m_pFrame->SetCaption(strCaption, hIcon);
  479. if (hIcon)
  480. DestroyIcon(hIcon);
  481. }
  482. else
  483. m_pFrame->SetCaption(strCaption);
  484. }
  485. else
  486. m_pFrame->SetCaption(strCaption);
  487. }
  488. void CTreePropSheet::ActivatePreviousPage()
  489. {
  490. if (!IsWindow(m_hWnd))
  491. return;
  492. if (!IsWindow(m_pwndPageTree->GetSafeHwnd()))
  493. {
  494. // normal tab property sheet. Simply use page index
  495. int nPageIndex = GetActiveIndex();
  496. if (nPageIndex<0 || nPageIndex>=GetPageCount())
  497. return;
  498. int nPrevIndex = (nPageIndex==0)? GetPageCount()-1 : nPageIndex-1;
  499. SetActivePage(nPrevIndex);
  500. }
  501. else
  502. {
  503. // property sheet with page tree.
  504. // we need a more sophisticated handling here, than simply using
  505. // the page index, because we won't skip empty pages.
  506. // so we have to walk the page tree
  507. HTREEITEM hItem = m_pwndPageTree->GetSelectedItem();
  508. ASSERT(hItem);
  509. if (!hItem)
  510. return;
  511. HTREEITEM hPrevItem = NULL;
  512. if (hPrevItem=m_pwndPageTree->GetPrevSiblingItem(hItem))
  513. {
  514. while (m_pwndPageTree->ItemHasChildren(hPrevItem))
  515. {
  516. hPrevItem = m_pwndPageTree->GetChildItem(hPrevItem);
  517. while (m_pwndPageTree->GetNextSiblingItem(hPrevItem))
  518. hPrevItem = m_pwndPageTree->GetNextSiblingItem(hPrevItem);
  519. }
  520. }
  521. else 
  522. hPrevItem=m_pwndPageTree->GetParentItem(hItem);
  523. if (!hPrevItem)
  524. {
  525. // no prev item, so cycle to the last item
  526. hPrevItem = m_pwndPageTree->GetRootItem();
  527. while (TRUE)
  528. {
  529. while (m_pwndPageTree->GetNextSiblingItem(hPrevItem))
  530. hPrevItem = m_pwndPageTree->GetNextSiblingItem(hPrevItem);
  531. if (m_pwndPageTree->ItemHasChildren(hPrevItem))
  532. hPrevItem = m_pwndPageTree->GetChildItem(hPrevItem);
  533. else
  534. break;
  535. }
  536. }
  537. if (hPrevItem)
  538. m_pwndPageTree->SelectItem(hPrevItem);
  539. }
  540. }
  541. void CTreePropSheet::ActivateNextPage()
  542. {
  543. if (!IsWindow(m_hWnd))
  544. return;
  545. if (!IsWindow(m_pwndPageTree->GetSafeHwnd()))
  546. {
  547. // normal tab property sheet. Simply use page index
  548. int nPageIndex = GetActiveIndex();
  549. if (nPageIndex<0 || nPageIndex>=GetPageCount())
  550. return;
  551. int nNextIndex = (nPageIndex==GetPageCount()-1)? 0 : nPageIndex+1;
  552. SetActivePage(nNextIndex);
  553. }
  554. else
  555. {
  556. // property sheet with page tree.
  557. // we need a more sophisticated handling here, than simply using
  558. // the page index, because we won't skip empty pages.
  559. // so we have to walk the page tree
  560. HTREEITEM hItem = m_pwndPageTree->GetSelectedItem();
  561. ASSERT(hItem);
  562. if (!hItem)
  563. return;
  564. HTREEITEM hNextItem = NULL;
  565. if (hNextItem=m_pwndPageTree->GetChildItem(hItem))
  566. ;
  567. else if (hNextItem=m_pwndPageTree->GetNextSiblingItem(hItem))
  568. ;
  569. else if (m_pwndPageTree->GetParentItem(hItem))
  570. {
  571. while (!hNextItem)
  572. {
  573. hItem = m_pwndPageTree->GetParentItem(hItem);
  574. if (!hItem)
  575. break;
  576. hNextItem = m_pwndPageTree->GetNextSiblingItem(hItem);
  577. }
  578. }
  579. if (!hNextItem)
  580. // no next item -- so cycle to the first item
  581. hNextItem = m_pwndPageTree->GetRootItem();
  582. if (hNextItem)
  583. m_pwndPageTree->SelectItem(hNextItem);
  584. }
  585. }
  586. /////////////////////////////////////////////////////////////////////
  587. // Overridings
  588. BOOL CTreePropSheet::OnInitDialog() 
  589. {
  590. if (m_bTreeViewMode)
  591. {
  592. // be sure, there are no stacked tabs, because otherwise the
  593. // page caption will be to large in tree view mode
  594. EnableStackedTabs(FALSE);
  595. // Initialize image list.
  596. if (m_DefaultImages.GetSafeHandle())
  597. {
  598. IMAGEINFO ii;
  599. m_DefaultImages.GetImageInfo(0, &ii);
  600. if (ii.hbmImage) DeleteObject(ii.hbmImage);
  601. if (ii.hbmMask) DeleteObject(ii.hbmMask);
  602. m_Images.Create(ii.rcImage.right-ii.rcImage.left, ii.rcImage.bottom-ii.rcImage.top, ILC_COLOR32|ILC_MASK, 0, 1);
  603. }
  604. else
  605. m_Images.Create(16, 16, ILC_COLOR32|ILC_MASK, 0, 1);
  606. }
  607. // perform default implementation
  608. BOOL bResult = __super::OnInitDialog();
  609. if (!m_bTreeViewMode)
  610. // stop here, if we would like to use tabs
  611. return bResult;
  612. // Get tab control...
  613. CTabCtrl *pTab = GetTabControl();
  614. if (!IsWindow(pTab->GetSafeHwnd()))
  615. {
  616. ASSERT(FALSE);
  617. return bResult;
  618. }
  619. // ... and hide it
  620. pTab->ShowWindow(SW_HIDE);
  621. pTab->EnableWindow(FALSE);
  622. // Place another (empty) tab ctrl, to get a frame instead
  623. CRect rectFrame;
  624. pTab->GetWindowRect(rectFrame);
  625. ScreenToClient(rectFrame);
  626. m_pFrame = CreatePageFrame();
  627. if (!m_pFrame)
  628. {
  629. ASSERT(FALSE);
  630. AfxThrowMemoryException();
  631. }
  632. m_pFrame->Create(WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS, rectFrame, this, 0xFFFF);
  633. m_pFrame->ShowCaption(m_bPageCaption);
  634. // Lets make place for the tree ctrl
  635. const int nTreeWidth = m_nPageTreeWidth;
  636. const int nTreeSpace = 5;
  637. CRect rectSheet;
  638. GetWindowRect(rectSheet);
  639. rectSheet.right+= nTreeWidth;
  640. SetWindowPos(NULL, -1, -1, rectSheet.Width(), rectSheet.Height(), SWP_NOZORDER|SWP_NOMOVE);
  641. CenterWindow();
  642. MoveChildWindows(nTreeWidth, 0);
  643. // Lets calculate the rectangle for the tree ctrl
  644. CRect rectTree(rectFrame);
  645. rectTree.right = rectTree.left + nTreeWidth - nTreeSpace;
  646. // calculate caption height
  647. CTabCtrl wndTabCtrl;
  648. wndTabCtrl.Create(WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS, rectFrame, this, 0x1234);
  649. wndTabCtrl.InsertItem(0, _T(""));
  650. CRect rectFrameCaption;
  651. wndTabCtrl.GetItemRect(0, rectFrameCaption);
  652. wndTabCtrl.DestroyWindow();
  653. m_pFrame->SetCaptionHeight(rectFrameCaption.Height());
  654. // if no caption should be displayed, make the window smaller in
  655. // height
  656. if (!m_bPageCaption)
  657. {
  658. // make frame smaller
  659. m_pFrame->GetWnd()->GetWindowRect(rectFrame);
  660. ScreenToClient(rectFrame);
  661. rectFrame.top+= rectFrameCaption.Height();
  662. m_pFrame->GetWnd()->MoveWindow(rectFrame);
  663. // move all child windows up
  664. MoveChildWindows(0, -rectFrameCaption.Height());
  665. // modify rectangle for the tree ctrl
  666. rectTree.bottom-= rectFrameCaption.Height();
  667. // make us smaller
  668. CRect rect;
  669. GetWindowRect(rect);
  670. rect.top+= rectFrameCaption.Height()/2;
  671. rect.bottom-= rectFrameCaption.Height()-rectFrameCaption.Height()/2;
  672. // if (GetParent())
  673. // GetParent()->ScreenToClient(rect);
  674. MoveWindow(rect);
  675. }
  676. // finally create tht tree control
  677. const DWORD dwTreeStyle = TVS_SHOWSELALWAYS|TVS_TRACKSELECT|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS;
  678. m_pwndPageTree = CreatePageTreeObject();
  679. if (!m_pwndPageTree)
  680. {
  681. ASSERT(FALSE);
  682. AfxThrowMemoryException();
  683. }
  684. // MFC7-support here (Thanks to Rainer Wollgarten)
  685. #if _MFC_VER >= 0x0700
  686. {
  687. m_pwndPageTree->CreateEx(
  688. WS_EX_CLIENTEDGE|WS_EX_NOPARENTNOTIFY, 
  689. WS_TABSTOP|WS_CHILD|WS_VISIBLE|dwTreeStyle, 
  690. rectTree, this, s_unPageTreeId);
  691. }
  692. #else
  693. {
  694. m_pwndPageTree->CreateEx(
  695. WS_EX_CLIENTEDGE|WS_EX_NOPARENTNOTIFY, 
  696. _T("SysTreeView32"), _T("PageTree"), 
  697. WS_TABSTOP|WS_CHILD|WS_VISIBLE|dwTreeStyle, 
  698. rectTree, this, s_unPageTreeId);
  699. }
  700. #endif
  701. if (m_bTreeImages)
  702. {
  703. m_pwndPageTree->SetImageList(&m_Images, TVSIL_NORMAL);
  704. m_pwndPageTree->SetImageList(&m_Images, TVSIL_STATE);
  705. }
  706. // Fill the tree ctrl
  707. RefillPageTree();
  708. // Select item for the current page
  709. if (pTab->GetCurSel() > -1)
  710. SelectPageTreeItem(pTab->GetCurSel());
  711. return bResult;
  712. }
  713. void CTreePropSheet::OnDestroy() 
  714. {
  715. __super::OnDestroy();
  716. if(m_pwndPageTree && m_pwndPageTree->m_hWnd)
  717. m_pwndPageTree->DestroyWindow();
  718. if(m_pFrame && m_pFrame->GetWnd()->m_hWnd)
  719. m_pFrame->GetWnd()->DestroyWindow();
  720. }
  721. LRESULT CTreePropSheet::OnAddPage(WPARAM wParam, LPARAM lParam)
  722. {
  723. LRESULT lResult = DefWindowProc(PSM_ADDPAGE, wParam, lParam);
  724. if (!m_bTreeViewMode)
  725. return lResult;
  726. RefillPageTree();
  727. SelectCurrentPageTreeItem();
  728. return lResult;
  729. }
  730. LRESULT CTreePropSheet::OnRemovePage(WPARAM wParam, LPARAM lParam)
  731. {
  732. LRESULT lResult = DefWindowProc(PSM_REMOVEPAGE, wParam, lParam);
  733. if (!m_bTreeViewMode)
  734. return lResult;
  735. RefillPageTree();
  736. SelectCurrentPageTreeItem();
  737. return lResult;
  738. }
  739. LRESULT CTreePropSheet::OnSetCurSel(WPARAM wParam, LPARAM lParam)
  740. {
  741. LRESULT lResult = DefWindowProc(PSM_SETCURSEL, wParam, lParam);
  742. if (!m_bTreeViewMode)
  743. return lResult;
  744. SelectCurrentPageTreeItem();
  745. UpdateCaption();
  746. return lResult;
  747. }
  748. LRESULT CTreePropSheet::OnSetCurSelId(WPARAM wParam, LPARAM lParam)
  749. {
  750. LRESULT lResult = DefWindowProc(PSM_SETCURSEL, wParam, lParam);
  751. if (!m_bTreeViewMode)
  752. return lResult;
  753. SelectCurrentPageTreeItem();
  754. UpdateCaption();
  755. return lResult;
  756. }
  757. void CTreePropSheet::OnPageTreeSelChanging(NMHDR *pNotifyStruct, LRESULT *plResult)
  758. {
  759. *plResult = 0;
  760. if (m_bPageTreeSelChangedActive)
  761. return;
  762. else
  763. m_bPageTreeSelChangedActive = TRUE;
  764. NMTREEVIEW *pTvn = reinterpret_cast<NMTREEVIEW*>(pNotifyStruct);
  765. int nPage = m_pwndPageTree->GetItemData(pTvn->itemNew.hItem);
  766. BOOL bResult;
  767. if (nPage<0 || (unsigned)nPage>=m_pwndPageTree->GetCount())
  768. bResult = KillActiveCurrentPage();
  769. else
  770. bResult = SetActivePage(nPage);
  771. if (!bResult)
  772. // prevent selection to change
  773. *plResult = TRUE;
  774. // Set focus to tree ctrl (I guess that's what the user expects)
  775. m_pwndPageTree->SetFocus();
  776. m_bPageTreeSelChangedActive = FALSE;
  777. return;
  778. }
  779. void CTreePropSheet::OnPageTreeSelChanged(NMHDR *pNotifyStruct, LRESULT *plResult)
  780. {
  781. *plResult = 0;
  782. UpdateCaption();
  783. return;
  784. }
  785. LRESULT CTreePropSheet::OnIsDialogMessage(WPARAM wParam, LPARAM lParam)
  786. {
  787. MSG *pMsg = reinterpret_cast<MSG*>(lParam);
  788. if (pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_TAB && GetKeyState(VK_CONTROL)&0x8000)
  789. {
  790. if (GetKeyState(VK_SHIFT)&0x8000)
  791. ActivatePreviousPage();
  792. else
  793. ActivateNextPage();
  794. return TRUE;
  795. }
  796. return __super::DefWindowProc(PSM_ISDIALOGMESSAGE, wParam, lParam);
  797. }
  798. } //namespace TreePropSheet