Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1516 lines
30 KiB

  1. /*++
  2. Copyright (c) 1994-95 Microsoft Corporation
  3. Module Name:
  4. utils.cpp
  5. Abstract:
  6. Utilities.
  7. Author:
  8. Don Ryan (donryan) 04-Jan-1995
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. Jeff Parham (jeffparh) 16-Jan-1996
  13. o Removed multitudinous SetRedraw()'s and made a fix to TvGetDomain()
  14. so that LLSMGR no longer AVs when it performs refreshes wherein the
  15. overall number of domains diminishes and one of the now superfluous
  16. entries was expanded before the refresh.
  17. --*/
  18. #include "stdafx.h"
  19. #include "llsmgr.h"
  20. //
  21. // List view utilities
  22. //
  23. void LvInitColumns(CListCtrl* pListCtrl, PLV_COLUMN_INFO plvColumnInfo)
  24. /*++
  25. Routine Description:
  26. Initializes list view columns.
  27. Arguments:
  28. pListCtrl - list control.
  29. plvColumnInfo - column information.
  30. Return Values:
  31. None.
  32. --*/
  33. {
  34. ASSERT(plvColumnInfo);
  35. VALIDATE_OBJECT(pListCtrl, CListCtrl);
  36. int nStringId;
  37. CString strText;
  38. LV_COLUMN lvColumn;
  39. int nColumns = plvColumnInfo->nColumns;
  40. PLV_COLUMN_ENTRY plvColumnEntry = plvColumnInfo->lvColumnEntry;
  41. lvColumn.mask = LVCF_FMT|
  42. LVCF_TEXT|
  43. LVCF_SUBITEM;
  44. lvColumn.fmt = LVCFMT_LEFT;
  45. pListCtrl->SetRedraw(FALSE); // turn off drawing...
  46. while (nColumns--)
  47. {
  48. lvColumn.iSubItem = plvColumnEntry->iSubItem;
  49. if (nStringId = plvColumnEntry->nStringId)
  50. {
  51. strText.LoadString(nStringId);
  52. lvColumn.pszText = MKSTR(strText);
  53. }
  54. else
  55. lvColumn.pszText = _T("");
  56. pListCtrl->InsertColumn(lvColumn.iSubItem, &lvColumn);
  57. plvColumnEntry++;
  58. }
  59. pListCtrl->SetImageList(&theApp.m_smallImages, LVSIL_SMALL);
  60. pListCtrl->SetImageList(&theApp.m_largeImages, LVSIL_NORMAL);
  61. SetDefaultFont(pListCtrl);
  62. LvResizeColumns(pListCtrl, plvColumnInfo);
  63. pListCtrl->SetRedraw(TRUE); // turn on drawing...
  64. }
  65. void LvResizeColumns(CListCtrl* pListCtrl, PLV_COLUMN_INFO plvColumnInfo)
  66. /*++
  67. Routine Description:
  68. Resizes list view columns.
  69. Arguments:
  70. pListCtrl - list control.
  71. plvColumnInfo - column information.
  72. Return Values:
  73. None.
  74. --*/
  75. {
  76. ASSERT(plvColumnInfo);
  77. VALIDATE_OBJECT(pListCtrl, CListCtrl);
  78. int nColumnWidth;
  79. int nRelativeWidth;
  80. int nEntireWidthSoFar = 0;
  81. int nColumns = plvColumnInfo->nColumns;
  82. PLV_COLUMN_ENTRY plvColumnEntry = plvColumnInfo->lvColumnEntry;
  83. CRect clientRect;
  84. pListCtrl->GetClientRect(clientRect);
  85. pListCtrl->SetRedraw(FALSE); // turn off drawing...
  86. while ((nRelativeWidth = plvColumnEntry->nRelativeWidth) != -1)
  87. {
  88. nColumnWidth = (nRelativeWidth * clientRect.Width()) / 100;
  89. pListCtrl->SetColumnWidth(plvColumnEntry->iSubItem, nColumnWidth);
  90. nEntireWidthSoFar += nColumnWidth;
  91. plvColumnEntry++;
  92. }
  93. nColumnWidth = clientRect.Width() - nEntireWidthSoFar;
  94. pListCtrl->SetColumnWidth(plvColumnEntry->iSubItem, nColumnWidth);
  95. pListCtrl->SetRedraw(TRUE); // turn on drawing...
  96. }
  97. void LvChangeFormat(CListCtrl* pListCtrl, UINT nFormatId)
  98. /*++
  99. Routine Description:
  100. Changes window style of list view.
  101. Arguments:
  102. pListCtrl - list control.
  103. nFormatId - format specification.
  104. Return Values:
  105. None.
  106. --*/
  107. {
  108. VALIDATE_OBJECT(pListCtrl, CListCtrl);
  109. DWORD dwStyle = ::GetWindowLong(pListCtrl->GetSafeHwnd(), GWL_STYLE);
  110. pListCtrl->BeginWaitCursor();
  111. pListCtrl->SetRedraw(FALSE); // turn off drawing...
  112. if ((dwStyle & LVS_TYPEMASK) != nFormatId)
  113. {
  114. ::SetWindowLong(
  115. pListCtrl->GetSafeHwnd(),
  116. GWL_STYLE,
  117. (dwStyle & ~LVS_TYPEMASK) | nFormatId
  118. );
  119. }
  120. pListCtrl->SetRedraw(TRUE); // turn on drawing...
  121. pListCtrl->EndWaitCursor();
  122. }
  123. LPVOID LvGetSelObj(CListCtrl* pListCtrl)
  124. /*++
  125. Routine Description:
  126. Retrieves the object selected (assumes one) from list view.
  127. Arguments:
  128. pListCtrl - list control.
  129. Return Values:
  130. Same as LvGetNextObj.
  131. --*/
  132. {
  133. int iItem = -1;
  134. return LvGetNextObj(pListCtrl, &iItem);
  135. }
  136. LPVOID LvGetNextObj(CListCtrl* pListCtrl, LPINT piItem, int nType)
  137. /*++
  138. Routine Description:
  139. Retrieves the next object selected from list view.
  140. Arguments:
  141. pListCtrl - list control.
  142. piItem - starting index (updated).
  143. nType - specifies search criteria.
  144. Return Values:
  145. Returns object pointer or null.
  146. --*/
  147. {
  148. ASSERT(piItem);
  149. VALIDATE_OBJECT(pListCtrl, CListCtrl);
  150. LV_ITEM lvItem;
  151. if ((lvItem.iItem = pListCtrl->GetNextItem(*piItem, nType)) != -1)
  152. {
  153. lvItem.mask = LVIF_PARAM;
  154. lvItem.iSubItem = 0;
  155. if (pListCtrl->GetItem(&lvItem))
  156. {
  157. *piItem = lvItem.iItem;
  158. return (LPVOID)lvItem.lParam;
  159. }
  160. }
  161. return NULL;
  162. }
  163. BOOL LvInsertObArray(CListCtrl* pListCtrl, PLV_COLUMN_INFO plvColumnInfo, CObArray* pObArray)
  164. /*++
  165. Routine Description:
  166. Insert object array into list view.
  167. Note list view must be unsorted and support LVN_GETDISPINFO.
  168. Arguments:
  169. pListCtrl - list control.
  170. plvColumnInfo - column info.
  171. pObArray - object array.
  172. Return Values:
  173. VT_BOOL.
  174. --*/
  175. {
  176. VALIDATE_OBJECT(pObArray, CObArray);
  177. VALIDATE_OBJECT(pListCtrl, CListCtrl);
  178. ASSERT(plvColumnInfo);
  179. ASSERT(pListCtrl->GetItemCount() == 0);
  180. BOOL bItemsInserted = FALSE;
  181. LV_ITEM lvItem;
  182. lvItem.mask = LVIF_TEXT|
  183. LVIF_PARAM|
  184. LVIF_IMAGE;
  185. lvItem.pszText = LPSTR_TEXTCALLBACK;
  186. lvItem.cchTextMax = LPSTR_TEXTCALLBACK_MAX;
  187. lvItem.iImage = I_IMAGECALLBACK;
  188. lvItem.iSubItem = 0;
  189. int iItem;
  190. int iSubItem;
  191. int nItems = (int)pObArray->GetSize();
  192. ASSERT(nItems != -1); // iItem is -1 if error...
  193. pListCtrl->SetRedraw(FALSE); // turn off drawing...
  194. pListCtrl->SetItemCount(nItems);
  195. CCmdTarget* pObject = NULL;
  196. for (iItem = 0; (iItem < nItems) && (pObject = (CCmdTarget*)pObArray->GetAt(iItem)); iItem++)
  197. {
  198. VALIDATE_OBJECT(pObject, CCmdTarget);
  199. lvItem.iItem = iItem;
  200. lvItem.lParam = (LPARAM)(LPVOID)pObject;
  201. pObject->InternalAddRef(); // add ref...
  202. iItem = pListCtrl->InsertItem(&lvItem);
  203. ASSERT((iItem == lvItem.iItem) || (iItem == -1));
  204. for (iSubItem = 1; iSubItem < plvColumnInfo->nColumns; iSubItem++)
  205. {
  206. pListCtrl->SetItemText(iItem, iSubItem, LPSTR_TEXTCALLBACK);
  207. }
  208. }
  209. if (iItem == nItems)
  210. {
  211. bItemsInserted = TRUE;
  212. VERIFY(pListCtrl->SetItemState(
  213. 0,
  214. LVIS_FOCUSED|
  215. LVIS_SELECTED,
  216. LVIS_FOCUSED|
  217. LVIS_SELECTED
  218. ));
  219. }
  220. else
  221. {
  222. LlsSetLastStatus(STATUS_NO_MEMORY);
  223. VERIFY(pListCtrl->DeleteAllItems());
  224. }
  225. LvResizeColumns(pListCtrl, plvColumnInfo);
  226. pListCtrl->Invalidate(TRUE);
  227. pListCtrl->SetRedraw(TRUE); // turn on drawing...
  228. return bItemsInserted;
  229. }
  230. BOOL
  231. LvRefreshObArray(
  232. CListCtrl* pListCtrl,
  233. PLV_COLUMN_INFO plvColumnInfo,
  234. CObArray* pObArray
  235. )
  236. /*++
  237. Routine Description:
  238. Refresh object array in list view.
  239. Arguments:
  240. pListCtrl - list control.
  241. plvColumnInfo - column info.
  242. pObArray - object array.
  243. Return Values:
  244. VT_BOOL.
  245. --*/
  246. {
  247. ASSERT(plvColumnInfo);
  248. VALIDATE_OBJECT(pObArray, CObArray);
  249. VALIDATE_OBJECT(pListCtrl, CListCtrl);
  250. LONG_PTR nObjects = pObArray->GetSize();
  251. long nObjectsInList = pListCtrl->GetItemCount();
  252. if (!nObjects)
  253. {
  254. LvReleaseObArray(pListCtrl);
  255. return TRUE;
  256. }
  257. else if (!nObjectsInList)
  258. {
  259. return LvInsertObArray(
  260. pListCtrl,
  261. plvColumnInfo,
  262. pObArray
  263. );
  264. }
  265. CCmdTarget* pObject;
  266. int iObject = 0;
  267. int iObjectInList = 0;
  268. LV_ITEM lvItem;
  269. pListCtrl->SetRedraw(FALSE); // turn off drawing...
  270. while (nObjectsInList--)
  271. {
  272. lvItem.mask = LVIF_PARAM;
  273. lvItem.iItem = iObjectInList;
  274. lvItem.iSubItem = 0;
  275. VERIFY(pListCtrl->GetItem(&lvItem));
  276. pObject = (CCmdTarget*)lvItem.lParam;
  277. VALIDATE_OBJECT(pObject, CCmdTarget);
  278. if (iObject < nObjects)
  279. {
  280. pObject->InternalRelease(); // release before...
  281. pObject = (CCmdTarget*)pObArray->GetAt(iObject++);
  282. VALIDATE_OBJECT(pObject, CCmdTarget);
  283. pObject->InternalAddRef(); // add ref...
  284. lvItem.mask = LVIF_TEXT|LVIF_PARAM;
  285. lvItem.pszText = LPSTR_TEXTCALLBACK;
  286. lvItem.cchTextMax = LPSTR_TEXTCALLBACK_MAX;
  287. lvItem.lParam = (LPARAM)(LPVOID)pObject;
  288. VERIFY(pListCtrl->SetItem(&lvItem)); // overwrite...
  289. iObjectInList++; // increment count...
  290. }
  291. else
  292. {
  293. VERIFY(pListCtrl->DeleteItem(iObjectInList));
  294. pObject->InternalRelease(); // release after...
  295. }
  296. }
  297. lvItem.mask = LVIF_TEXT|
  298. LVIF_PARAM|
  299. LVIF_IMAGE;
  300. lvItem.pszText = LPSTR_TEXTCALLBACK;
  301. lvItem.cchTextMax = LPSTR_TEXTCALLBACK_MAX;
  302. lvItem.iImage = I_IMAGECALLBACK;
  303. lvItem.iSubItem = 0;
  304. int iItem;
  305. int iSubItem;
  306. while (iObject < nObjects)
  307. {
  308. lvItem.iItem = iObject;
  309. pObject = (CCmdTarget*)pObArray->GetAt(iObject++);
  310. VALIDATE_OBJECT(pObject, CCmdTarget);
  311. pObject->InternalAddRef(); // add ref...
  312. lvItem.lParam = (LPARAM)(LPVOID)pObject;
  313. iItem = pListCtrl->InsertItem(&lvItem);
  314. ASSERT((iItem == lvItem.iItem) && (iItem != -1));
  315. for (iSubItem = 1; iSubItem < plvColumnInfo->nColumns; iSubItem++)
  316. {
  317. VERIFY(pListCtrl->SetItemText(iItem, iSubItem, LPSTR_TEXTCALLBACK));
  318. }
  319. }
  320. LvResizeColumns(pListCtrl, plvColumnInfo);
  321. pListCtrl->Invalidate(TRUE);
  322. pListCtrl->SetRedraw(TRUE); // turn on drawing...
  323. return TRUE;
  324. }
  325. void LvReleaseObArray(CListCtrl* pListCtrl)
  326. /*++
  327. Routine Description:
  328. Release objects inserted into list view.
  329. Arguments:
  330. pListCtrl - list control.
  331. Return Values:
  332. None.
  333. --*/
  334. {
  335. VALIDATE_OBJECT(pListCtrl, CListCtrl);
  336. LV_ITEM lvItem;
  337. CCmdTarget* pObject;
  338. lvItem.mask = LVIF_PARAM;
  339. lvItem.iItem = 0;
  340. lvItem.iSubItem = 0;
  341. int nObjectsInList = pListCtrl->GetItemCount();
  342. pListCtrl->BeginWaitCursor();
  343. pListCtrl->SetRedraw(FALSE); // turn off drawing...
  344. while (nObjectsInList--)
  345. {
  346. VERIFY(pListCtrl->GetItem(&lvItem));
  347. pObject = (CCmdTarget*)lvItem.lParam;
  348. VALIDATE_OBJECT(pObject, CCmdTarget);
  349. VERIFY(pListCtrl->DeleteItem(lvItem.iItem));
  350. pObject->InternalRelease(); // release after...
  351. }
  352. pListCtrl->SetRedraw(TRUE); // turn on drawing...
  353. pListCtrl->EndWaitCursor();
  354. }
  355. void LvReleaseSelObjs(CListCtrl* pListCtrl)
  356. /*++
  357. Routine Description:
  358. Release selected objects in list view.
  359. Arguments:
  360. pListCtrl - list control.
  361. Return Values:
  362. None.
  363. --*/
  364. {
  365. VALIDATE_OBJECT(pListCtrl, CListCtrl);
  366. int iItem = -1;
  367. CCmdTarget* pObject;
  368. pListCtrl->SetRedraw(FALSE); // turn off drawing...
  369. while (pObject = (CCmdTarget*)::LvGetNextObj(pListCtrl, &iItem))
  370. {
  371. pObject->InternalRelease();
  372. pListCtrl->DeleteItem(iItem);
  373. iItem = -1;
  374. }
  375. LvSelObjIfNecessary(pListCtrl);
  376. pListCtrl->SetRedraw(TRUE); // turn on drawing...
  377. }
  378. void LvSelObjIfNecessary(CListCtrl* pListCtrl, BOOL bSetFocus)
  379. /*++
  380. Routine Description:
  381. Ensure that object selected.
  382. Arguments:
  383. pListCtrl - list control.
  384. bSetFocus - true if focus to be set focus as well.
  385. Return Values:
  386. None.
  387. --*/
  388. {
  389. VALIDATE_OBJECT(pListCtrl, CListCtrl);
  390. if (!IsItemSelectedInList(pListCtrl) && pListCtrl->GetItemCount())
  391. {
  392. pListCtrl->SendMessage(WM_KEYDOWN, VK_RIGHT); // HACKHACK...
  393. int iItem = pListCtrl->GetNextItem(-1, LVNI_FOCUSED|LVNI_ALL);
  394. int nState = bSetFocus ? (LVIS_SELECTED|LVIS_FOCUSED) : LVIS_SELECTED;
  395. VERIFY(pListCtrl->SetItemState((iItem == -1) ? 0 : iItem, nState, nState));
  396. }
  397. }
  398. #ifdef _DEBUG
  399. void LvDumpObArray(CListCtrl* pListCtrl)
  400. /*++
  401. Routine Description:
  402. Release objects inserted into list view.
  403. Arguments:
  404. pListCtrl - list control.
  405. Return Values:
  406. None.
  407. --*/
  408. {
  409. VALIDATE_OBJECT(pListCtrl, CListCtrl);
  410. LV_ITEM lvItem;
  411. CString strDump;
  412. CCmdTarget* pObject;
  413. lvItem.mask = LVIF_STATE|LVIF_PARAM;
  414. lvItem.stateMask = (DWORD)-1;
  415. lvItem.iSubItem = 0;
  416. int nObjectsInList = pListCtrl->GetItemCount();
  417. pListCtrl->SetRedraw(FALSE); // turn off drawing...
  418. while (nObjectsInList--)
  419. {
  420. lvItem.iItem = nObjectsInList;
  421. VERIFY(pListCtrl->GetItem(&lvItem));
  422. pObject = (CCmdTarget*)lvItem.lParam;
  423. VALIDATE_OBJECT(pObject, CCmdTarget);
  424. strDump.Format(_T("iItem %d"), lvItem.iItem);
  425. strDump += (lvItem.state & LVIS_CUT) ? _T(" LVIS_CUT ") : _T("");
  426. strDump += (lvItem.state & LVIS_FOCUSED) ? _T(" LVIS_FOCUSED ") : _T("");
  427. strDump += (lvItem.state & LVIS_SELECTED) ? _T(" LVIS_SELECTED ") : _T("");
  428. strDump += _T("\r\n");
  429. afxDump << strDump;
  430. }
  431. pListCtrl->SetRedraw(TRUE); // turn on drawing...
  432. }
  433. #endif
  434. //
  435. // Tree view utilities
  436. //
  437. LPVOID TvGetSelObj(CTreeCtrl* pTreeCtrl)
  438. /*++
  439. Routine Description:
  440. Retrieves the object selected from treeview.
  441. Arguments:
  442. pTreeCtrl - tree control.
  443. Return Values:
  444. Returns object pointer or null.
  445. --*/
  446. {
  447. VALIDATE_OBJECT(pTreeCtrl, CTreeCtrl);
  448. TV_ITEM tvItem;
  449. if (tvItem.hItem = pTreeCtrl->GetSelectedItem())
  450. {
  451. tvItem.mask = TVIF_PARAM;
  452. VERIFY(pTreeCtrl->GetItem(&tvItem));
  453. return (LPVOID)tvItem.lParam;
  454. }
  455. return NULL;
  456. }
  457. BOOL
  458. TvInsertObArray(
  459. CTreeCtrl* pTreeCtrl,
  460. HTREEITEM hParent,
  461. CObArray* pObArray,
  462. BOOL bIsContainer
  463. )
  464. /*++
  465. Routine Description:
  466. Insert collection into tree view.
  467. Arguments:
  468. pTreeCtrl - tree control.
  469. hParent - parent tree item.
  470. pObArray - object array.
  471. bIsContainer - container object.
  472. Return Values:
  473. VT_BOOL.
  474. --*/
  475. {
  476. VALIDATE_OBJECT(pObArray, CObArray);
  477. VALIDATE_OBJECT(pTreeCtrl, CTreeCtrl);
  478. BOOL bItemsInserted = FALSE;
  479. TV_ITEM tvItem;
  480. TV_INSERTSTRUCT tvInsert;
  481. tvItem.mask = TVIF_TEXT|
  482. TVIF_PARAM|
  483. TVIF_IMAGE|
  484. TVIF_CHILDREN|
  485. TVIF_SELECTEDIMAGE;
  486. tvItem.pszText = LPSTR_TEXTCALLBACK;
  487. tvItem.cchTextMax = LPSTR_TEXTCALLBACK_MAX;
  488. tvItem.iImage = I_IMAGECALLBACK;
  489. tvItem.iSelectedImage = I_IMAGECALLBACK;
  490. tvItem.cChildren = bIsContainer;
  491. tvInsert.hInsertAfter = (HTREEITEM)TVI_LAST;
  492. tvInsert.hParent = (HTREEITEM)hParent;
  493. int iItem;
  494. INT_PTR nItems = pObArray->GetSize();
  495. HTREEITEM hNewItem = (HTREEITEM)-1; // init for loop...
  496. pTreeCtrl->SetRedraw(FALSE); // turn off drawing...
  497. CCmdTarget* pObject = NULL;
  498. for (iItem = 0; hNewItem && (iItem < nItems); iItem++)
  499. {
  500. pObject = (CCmdTarget*)pObArray->GetAt(iItem);
  501. VALIDATE_OBJECT(pObject, CCmdTarget);
  502. pObject->InternalAddRef(); // add ref...
  503. tvItem.lParam = (LPARAM)(LPVOID)pObject;
  504. tvInsert.item = tvItem;
  505. hNewItem = pTreeCtrl->InsertItem(&tvInsert);
  506. }
  507. if (hNewItem && (iItem == nItems))
  508. {
  509. bItemsInserted = TRUE;
  510. }
  511. else
  512. {
  513. LlsSetLastStatus(STATUS_NO_MEMORY);
  514. }
  515. pTreeCtrl->SetRedraw(TRUE); // turn on drawing...
  516. return bItemsInserted;
  517. }
  518. BOOL
  519. TvRefreshObArray(
  520. CTreeCtrl* pTreeCtrl,
  521. HTREEITEM hParent,
  522. CObArray* pObArray,
  523. TV_EXPANDED_INFO* pExpandedInfo,
  524. BOOL bIsContainer
  525. )
  526. /*++
  527. Routine Description:
  528. Refresh objects in tree view.
  529. Arguments:
  530. pTreeCtrl - tree control.
  531. hParent - parent tree item.
  532. pObArray - object array.
  533. pExpandedInfo - refresh information.
  534. bIsContainer - container object.
  535. Return Values:
  536. Returns true if successful.
  537. --*/
  538. {
  539. ASSERT(pExpandedInfo);
  540. VALIDATE_OBJECT(pObArray, CObArray);
  541. VALIDATE_OBJECT(pTreeCtrl, CTreeCtrl);
  542. pExpandedInfo->nExpandedItems = 0; // initialize...
  543. pExpandedInfo->pExpandedItems = NULL;
  544. LONG_PTR nObjects = pObArray->GetSize();
  545. long nObjectsInTree = TvSizeObArray(pTreeCtrl, hParent);
  546. if (!nObjects) // tree no longer exists...
  547. {
  548. TvReleaseObArray(pTreeCtrl, hParent);
  549. return TRUE;
  550. }
  551. else if (!nObjectsInTree) // tree is currently empty...
  552. {
  553. return TvInsertObArray(
  554. pTreeCtrl,
  555. hParent,
  556. pObArray,
  557. bIsContainer
  558. );
  559. }
  560. TV_EXPANDED_ITEM* pExpandedItem = new TV_EXPANDED_ITEM[nObjectsInTree];
  561. if (!pExpandedItem)
  562. {
  563. LlsSetLastStatus(STATUS_NO_MEMORY);
  564. return FALSE;
  565. }
  566. pExpandedInfo->pExpandedItems = pExpandedItem;
  567. TV_ITEM tvItem;
  568. HTREEITEM hItem;
  569. BOOL bIsItemExpanded;
  570. CCmdTarget* pObject;
  571. int iObject = 0;
  572. hItem = pTreeCtrl->GetChildItem(hParent);
  573. while (hItem)
  574. {
  575. tvItem.hItem = hItem;
  576. tvItem.mask = TVIF_STATE|TVIF_PARAM;
  577. VERIFY(pTreeCtrl->GetItem(&tvItem));
  578. pObject = (CCmdTarget*)tvItem.lParam;
  579. VALIDATE_OBJECT(pObject, CCmdTarget);
  580. if (!(bIsItemExpanded = tvItem.state & TVIS_EXPANDEDONCE))
  581. {
  582. pObject->InternalRelease(); // release now...
  583. }
  584. else
  585. {
  586. pExpandedItem->hItem = tvItem.hItem;
  587. pExpandedItem->pObject = pObject; // don't release yet...
  588. pExpandedItem++;
  589. pExpandedInfo->nExpandedItems++;
  590. ASSERT(pExpandedInfo->nExpandedItems <= nObjectsInTree);
  591. }
  592. hItem = pTreeCtrl->GetNextSiblingItem(tvItem.hItem);
  593. if (iObject < nObjects)
  594. {
  595. pObject = (CCmdTarget*)pObArray->GetAt(iObject++);
  596. VALIDATE_OBJECT(pObject, CCmdTarget);
  597. pObject->InternalAddRef(); // add ref...
  598. tvItem.mask = TVIF_PARAM;
  599. tvItem.lParam = (LPARAM)(LPVOID)pObject;
  600. VERIFY(pTreeCtrl->SetItem(&tvItem)); // overwrite...
  601. }
  602. else if (bIsItemExpanded)
  603. {
  604. tvItem.mask = TVIF_PARAM;
  605. tvItem.lParam = (LPARAM)(LPVOID)NULL; // place holder...
  606. VERIFY(pTreeCtrl->SetItem(&tvItem)); // remove later...
  607. }
  608. else
  609. {
  610. VERIFY(pTreeCtrl->DeleteItem(tvItem.hItem)); // trim excess...
  611. }
  612. }
  613. if (iObject < nObjects)
  614. {
  615. TV_INSERTSTRUCT tvInsert;
  616. tvItem.mask = TVIF_TEXT|
  617. TVIF_PARAM|
  618. TVIF_IMAGE|
  619. TVIF_CHILDREN|
  620. TVIF_SELECTEDIMAGE;
  621. tvItem.pszText = LPSTR_TEXTCALLBACK;
  622. tvItem.cchTextMax = LPSTR_TEXTCALLBACK_MAX;
  623. tvItem.iImage = I_IMAGECALLBACK;
  624. tvItem.iSelectedImage = I_IMAGECALLBACK;
  625. tvItem.cChildren = bIsContainer;
  626. tvInsert.hInsertAfter = (HTREEITEM)TVI_LAST;
  627. tvInsert.hParent = (HTREEITEM)hParent;
  628. hItem = (HTREEITEM)-1; // init for loop...
  629. for (; hItem && (iObject < nObjects); iObject++)
  630. {
  631. pObject = (CCmdTarget*)pObArray->GetAt(iObject);
  632. VALIDATE_OBJECT(pObject, CCmdTarget);
  633. pObject->InternalAddRef(); // AddRef each...
  634. tvItem.lParam = (LPARAM)(LPVOID)pObject;
  635. tvInsert.item = tvItem;
  636. hItem = pTreeCtrl->InsertItem(&tvInsert);
  637. }
  638. if (!(hItem && (iObject == nObjects)))
  639. {
  640. pExpandedItem = pExpandedInfo->pExpandedItems;
  641. while (pExpandedInfo->nExpandedItems--)
  642. (pExpandedItem++)->pObject->InternalRelease();
  643. delete [] pExpandedInfo->pExpandedItems;
  644. pExpandedInfo->pExpandedItems = NULL;
  645. LlsSetLastStatus(STATUS_NO_MEMORY);
  646. return FALSE;
  647. }
  648. }
  649. if (!pExpandedInfo->nExpandedItems)
  650. {
  651. delete [] pExpandedInfo->pExpandedItems;
  652. pExpandedInfo->pExpandedItems = NULL;
  653. }
  654. return TRUE;
  655. }
  656. void TvReleaseObArray(CTreeCtrl* pTreeCtrl, HTREEITEM hParent)
  657. /*++
  658. Routine Description:
  659. Release objects inserted into tree view.
  660. Arguments:
  661. pTreeCtrl - tree control.
  662. hParent - parent tree item.
  663. Return Values:
  664. None.
  665. --*/
  666. {
  667. if (!hParent)
  668. return; // nothing to release...
  669. VALIDATE_OBJECT(pTreeCtrl, CTreeCtrl);
  670. TV_ITEM tvItem;
  671. HTREEITEM hItem;
  672. CCmdTarget* pObject;
  673. tvItem.mask = TVIF_STATE|TVIF_PARAM;
  674. hItem = pTreeCtrl->GetChildItem(hParent);
  675. while (hItem)
  676. {
  677. tvItem.hItem = hItem;
  678. VERIFY(pTreeCtrl->GetItem(&tvItem));
  679. if (tvItem.state & TVIS_EXPANDEDONCE)
  680. {
  681. TvReleaseObArray(pTreeCtrl, tvItem.hItem);
  682. }
  683. hItem = pTreeCtrl->GetNextSiblingItem(tvItem.hItem);
  684. pObject = (CCmdTarget*)tvItem.lParam;
  685. VALIDATE_OBJECT(pObject, CCmdTarget);
  686. pObject->InternalRelease(); // release now...
  687. pTreeCtrl->DeleteItem(tvItem.hItem);
  688. }
  689. tvItem.hItem = hParent;
  690. tvItem.mask = TVIF_STATE|TVIF_PARAM;
  691. VERIFY(pTreeCtrl->GetItem(&tvItem));
  692. if (!tvItem.lParam)
  693. {
  694. pTreeCtrl->DeleteItem(hParent); // delete placeholder...
  695. }
  696. else if (tvItem.state & TVIS_EXPANDEDONCE)
  697. {
  698. tvItem.state = 0;
  699. tvItem.stateMask = TVIS_EXPANDED|TVIS_EXPANDEDONCE;
  700. VERIFY(pTreeCtrl->SetItem(&tvItem)); // no longer expanded...
  701. }
  702. }
  703. long TvSizeObArray(CTreeCtrl* pTreeCtrl, HTREEITEM hParent)
  704. /*++
  705. Routine Description:
  706. Count objects in tree view.
  707. Arguments:
  708. pTreeCtrl - tree control.
  709. hParent - parent tree item.
  710. Return Values:
  711. None.
  712. --*/
  713. {
  714. VALIDATE_OBJECT(pTreeCtrl, CTreeCtrl);
  715. long nObjects = 0;
  716. HTREEITEM hItem = pTreeCtrl->GetChildItem(hParent);
  717. while (hItem)
  718. {
  719. nObjects++;
  720. hItem = pTreeCtrl->GetNextSiblingItem(hItem);
  721. }
  722. return nObjects;
  723. }
  724. void
  725. TvSwitchItem(
  726. CTreeCtrl* pTreeCtrl,
  727. HTREEITEM hRandomItem,
  728. TV_EXPANDED_ITEM* pExpandedItem
  729. )
  730. /*++
  731. Routine Description:
  732. Move object from random node to previously expanded node. If there
  733. is an object in the previously expanded node we move it to the random
  734. node to be sorted later.
  735. Arguments:
  736. pTreeCtrl - tree control.
  737. hRandomItem - handle to random node with object of interest.
  738. pExpandedItem - state information.
  739. Return Values:
  740. None.
  741. --*/
  742. {
  743. ASSERT(pExpandedItem);
  744. VALIDATE_OBJECT(pTreeCtrl, CTreeCtrl);
  745. CCmdTarget* pRandomObject;
  746. CCmdTarget* pExpandedObject;
  747. TV_ITEM tvRandomItem;
  748. TV_ITEM tvExpandedItem;
  749. if (hRandomItem != pExpandedItem->hItem)
  750. {
  751. tvRandomItem.hItem = hRandomItem;
  752. tvRandomItem.mask = LVIF_PARAM;
  753. tvExpandedItem.hItem = pExpandedItem->hItem;
  754. tvExpandedItem.mask = LVIF_PARAM;
  755. VERIFY(pTreeCtrl->GetItem(&tvRandomItem));
  756. pExpandedObject = (CCmdTarget*)tvRandomItem.lParam;
  757. VALIDATE_OBJECT(pExpandedObject, CCmdTarget);
  758. VERIFY(pTreeCtrl->GetItem(&tvExpandedItem));
  759. pRandomObject = (CCmdTarget*)tvExpandedItem.lParam; // could be null...
  760. if (pRandomObject)
  761. {
  762. VALIDATE_OBJECT(pRandomObject, CCmdTarget);
  763. tvRandomItem.lParam = (LPARAM)(LPVOID)pRandomObject;
  764. VERIFY(pTreeCtrl->SetItem(&tvRandomItem)); // switch position...
  765. }
  766. else
  767. {
  768. VERIFY(pTreeCtrl->DeleteItem(tvRandomItem.hItem)); // delete placeholder...
  769. }
  770. tvExpandedItem.lParam = (LPARAM)(LPVOID)pExpandedObject;
  771. VERIFY(pTreeCtrl->SetItem(&tvExpandedItem));
  772. }
  773. }
  774. HTREEITEM TvGetDomain(CTreeCtrl* pTreeCtrl, HTREEITEM hParent, CCmdTarget* pObject)
  775. /*++
  776. Routine Description:
  777. Find domain in tree view.
  778. Arguments:
  779. pTreeCtrl - tree control.
  780. hParent - parent tree item.
  781. pObject - object to find.
  782. Return Values:
  783. Handle of located object.
  784. --*/
  785. {
  786. VALIDATE_OBJECT(pObject, CDomain);
  787. VALIDATE_OBJECT(pTreeCtrl, CTreeCtrl);
  788. CDomain* pDomain;
  789. TV_ITEM tvItem;
  790. tvItem.mask = TVIF_PARAM;
  791. tvItem.hItem = pTreeCtrl->GetChildItem(hParent);
  792. while (tvItem.hItem)
  793. {
  794. VERIFY(pTreeCtrl->GetItem(&tvItem));
  795. pDomain = (CDomain*)tvItem.lParam; // can be NULL if placeholder...
  796. if ( NULL != pDomain )
  797. {
  798. VALIDATE_OBJECT(pDomain, CDomain);
  799. if (!((CDomain*)pObject)->m_strName.CompareNoCase(pDomain->m_strName))
  800. {
  801. return tvItem.hItem; // found it...
  802. }
  803. }
  804. tvItem.hItem = pTreeCtrl->GetNextSiblingItem(tvItem.hItem);
  805. }
  806. return NULL;
  807. }
  808. HTREEITEM TvGetServer(CTreeCtrl* pTreeCtrl, HTREEITEM hParent, CCmdTarget* pObject)
  809. /*++
  810. Routine Description:
  811. Find server in tree view.
  812. Arguments:
  813. pTreeCtrl - tree control.
  814. hParent - parent tree item.
  815. pObject - object to find.
  816. Return Values:
  817. Handle of located object.
  818. --*/
  819. {
  820. VALIDATE_OBJECT(pObject, CServer);
  821. VALIDATE_OBJECT(pTreeCtrl, CTreeCtrl);
  822. CServer* pServer;
  823. TV_ITEM tvItem;
  824. tvItem.mask = TVIF_PARAM;
  825. tvItem.hItem = pTreeCtrl->GetChildItem(hParent);
  826. while (tvItem.hItem)
  827. {
  828. VERIFY(pTreeCtrl->GetItem(&tvItem));
  829. pServer = (CServer*)tvItem.lParam;
  830. VALIDATE_OBJECT(pServer, CServer);
  831. if (!((CServer*)pObject)->m_strName.CompareNoCase(pServer->m_strName))
  832. {
  833. return tvItem.hItem; // found it...
  834. }
  835. tvItem.hItem = pTreeCtrl->GetNextSiblingItem(tvItem.hItem);
  836. }
  837. return NULL;
  838. }
  839. HTREEITEM TvGetService(CTreeCtrl* pTreeCtrl, HTREEITEM hParent, CCmdTarget* pObject)
  840. /*++
  841. Routine Description:
  842. Find service in tree view.
  843. Arguments:
  844. pTreeCtrl - tree control.
  845. hParent - parent tree item.
  846. pObject - object to find.
  847. Return Values:
  848. Handle of located object.
  849. --*/
  850. {
  851. VALIDATE_OBJECT(pObject, CService);
  852. VALIDATE_OBJECT(pTreeCtrl, CTreeCtrl);
  853. CService* pService;
  854. TV_ITEM tvItem;
  855. tvItem.mask = TVIF_PARAM;
  856. tvItem.hItem = pTreeCtrl->GetChildItem(hParent);
  857. while (tvItem.hItem)
  858. {
  859. VERIFY(pTreeCtrl->GetItem(&tvItem));
  860. pService = (CService*)tvItem.lParam;
  861. VALIDATE_OBJECT(pService, CService);
  862. if (!((CService*)pObject)->m_strName.CompareNoCase(pService->m_strName))
  863. {
  864. return tvItem.hItem; // found it...
  865. }
  866. tvItem.hItem = pTreeCtrl->GetNextSiblingItem(tvItem.hItem);
  867. }
  868. return NULL;
  869. }
  870. //
  871. // Tab control utilities
  872. //
  873. void TcInitTabs(CTabCtrl* pTabCtrl, PTC_TAB_INFO ptcTabInfo)
  874. /*++
  875. Routine Description:
  876. Initializes tab items.
  877. Arguments:
  878. pTabCtrl - tab control.
  879. ptcTabInfo - tab information.
  880. Return Values:
  881. None.
  882. --*/
  883. {
  884. ASSERT(ptcTabInfo);
  885. VALIDATE_OBJECT(pTabCtrl, CTabCtrl);
  886. CString strText;
  887. TC_ITEM tcItem;
  888. int nTabs = ptcTabInfo->nTabs;
  889. PTC_TAB_ENTRY ptcTabEntry = ptcTabInfo->tcTabEntry;
  890. tcItem.mask = TCIF_TEXT;
  891. while (nTabs--)
  892. {
  893. strText.LoadString(ptcTabEntry->nStringId);
  894. tcItem.pszText = MKSTR(strText);
  895. pTabCtrl->InsertItem(ptcTabEntry->iItem, &tcItem);
  896. ptcTabEntry++;
  897. }
  898. SetDefaultFont(pTabCtrl);
  899. }
  900. //
  901. // Miscellaneous utilities
  902. //
  903. #define NUMBER_OF_SECONDS_IN_MINUTE (60)
  904. #define NUMBER_OF_SECONDS_IN_DAY (60 * 60 * 24)
  905. double SecondsSince1980ToDate(DWORD sysSeconds)
  906. /*++
  907. Routine Description:
  908. Converts time format to OLE-compliant.
  909. Arguments:
  910. hParent - parent item.
  911. pDomains - domain collection.
  912. Return Values:
  913. None.
  914. --*/
  915. {
  916. WORD dosDate = 0;
  917. WORD dosTime = 0;
  918. double dateTime = 0;
  919. FILETIME fileTime;
  920. LARGE_INTEGER locTime;
  921. DWORD locDays;
  922. DWORD locSeconds;
  923. TIME_ZONE_INFORMATION tzi;
  924. GetTimeZoneInformation(&tzi);
  925. locSeconds = sysSeconds - (tzi.Bias * NUMBER_OF_SECONDS_IN_MINUTE);
  926. locDays = locSeconds / NUMBER_OF_SECONDS_IN_DAY; // round off to days
  927. locSeconds = locDays * NUMBER_OF_SECONDS_IN_DAY; // for displaying time...
  928. RtlSecondsSince1980ToTime(locSeconds, &locTime);
  929. fileTime.dwLowDateTime = locTime.LowPart;
  930. fileTime.dwHighDateTime = locTime.HighPart;
  931. // JonN 5/15/00 PREFIX 112121
  932. // ignore error returns here
  933. (void)FileTimeToDosDateTime(&fileTime, &dosDate, &dosTime);
  934. (void)DosDateTimeToVariantTime(dosDate, dosTime, &dateTime);
  935. return dateTime;
  936. }
  937. void SetDefaultFont(CWnd* pWnd)
  938. /*++
  939. Routine Description:
  940. Set default font.
  941. Arguments:
  942. pWnd - window to change font.
  943. Return Values:
  944. None.
  945. --*/
  946. {
  947. VALIDATE_OBJECT(pWnd, CWnd);
  948. HFONT hFont;
  949. LOGFONT lFont;
  950. memset(&lFont, 0, sizeof(LOGFONT)); // initialize
  951. lFont.lfHeight = -12;
  952. lFont.lfWeight = FW_NORMAL; // normal
  953. CHARSETINFO csi;
  954. DWORD dw = ::GetACP();
  955. if (!::TranslateCharsetInfo((DWORD*)UintToPtr(dw), &csi, TCI_SRCCODEPAGE))
  956. csi.ciCharset = ANSI_CHARSET;
  957. lFont.lfCharSet = (BYTE)csi.ciCharset;
  958. ::lstrcpy(lFont.lfFaceName, TEXT("MS Shell Dlg"));
  959. hFont = ::CreateFontIndirect(&lFont);
  960. pWnd->SetFont(CFont::FromHandle(hFont));
  961. }
  962. void SafeEnableWindow(CWnd* pEnableWnd, CWnd* pNewFocusWnd, CWnd* pOldFocusWnd, BOOL bEnableWnd)
  963. /*++
  964. Routine Description:
  965. Enable/disable window without losing focus.
  966. Arguments:
  967. pEnableWnd - window to enable/disable.
  968. bEnableWnd - true if window to be enabled.
  969. pOldFocusWnd - window with current focus.
  970. pNewFocusWnd - window to receive focus.
  971. Return Values:
  972. None.
  973. --*/
  974. {
  975. VALIDATE_OBJECT(pEnableWnd, CWnd);
  976. VALIDATE_OBJECT(pNewFocusWnd, CWnd);
  977. if (bEnableWnd)
  978. {
  979. pEnableWnd->EnableWindow(TRUE);
  980. }
  981. else if (pOldFocusWnd == pEnableWnd)
  982. {
  983. ASSERT(pNewFocusWnd->IsWindowEnabled());
  984. pNewFocusWnd->SetFocus();
  985. pEnableWnd->EnableWindow(FALSE);
  986. }
  987. else
  988. {
  989. pEnableWnd->EnableWindow(FALSE);
  990. }
  991. }