Leaked source code of windows server 2003
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.

881 lines
22 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. fdlistbx.c
  5. Abstract:
  6. Routines for handling the subclassed owner-draw listbox used by NT fdisk
  7. to display the state of attached disks.
  8. Author:
  9. Ted Miller (tedm) 7-Jan-1992
  10. --*/
  11. #include "fdisk.h"
  12. // constants used when listbox or its focus rectangle is
  13. // scrolled/moved.
  14. #define DIR_NONE 0
  15. #define DIR_UP 1
  16. #define DIR_DN 2
  17. // original window procedure for our subclassed listbox
  18. WNDPROC OldListBoxProc;
  19. // item which has focus
  20. DWORD LBCursorListBoxItem,LBCursorRegion;
  21. BOOL LBCursorOn = FALSE;
  22. VOID
  23. ToggleLBCursor(
  24. IN HDC hdc
  25. );
  26. VOID
  27. ToggleRegion(
  28. IN PDISKSTATE DiskState,
  29. IN DWORD RegionIndex,
  30. IN HDC hdc
  31. );
  32. LONG
  33. ListBoxSubProc(
  34. IN HWND hwnd,
  35. IN UINT msg,
  36. IN DWORD wParam,
  37. IN LONG lParam
  38. )
  39. /*++
  40. Routine Description:
  41. This routine is the window procedure used for our subclassed listbox.
  42. We subclass the listbox so that we can handle keyboard input processing.
  43. All other messages are passed through to the original listbox procedure.
  44. Significant keys are arrows, pageup/dn, tab, space, return, home, and end.
  45. Control may be used to modify space and return.
  46. Shift may be used to modify tab.
  47. Arguments:
  48. hwnd - window handle of listbox
  49. msg - message #
  50. wParam - user param # 1
  51. lParam - user param # 2
  52. Return Value:
  53. see below
  54. --*/
  55. {
  56. int focusDir = DIR_NONE;
  57. USHORT vKey;
  58. DWORD maxRegion;
  59. PDISKSTATE diskState;
  60. LONG topItem,
  61. bottomWholeItem,
  62. visibleItems;
  63. RECT rc;
  64. switch (msg) {
  65. case WM_CHAR:
  66. break;
  67. case WM_KEYDOWN:
  68. switch (vKey = LOWORD(wParam)) {
  69. case VK_LEFT:
  70. case VK_RIGHT:
  71. case VK_UP:
  72. case VK_DOWN:
  73. ToggleLBCursor(NULL);
  74. switch (vKey) {
  75. case VK_LEFT:
  76. LBCursorRegion = LBCursorRegion ? LBCursorRegion-1 : 0;
  77. break;
  78. case VK_RIGHT:
  79. maxRegion = Disks[LBCursorListBoxItem]->RegionCount - 1;
  80. if (LBCursorRegion < maxRegion) {
  81. LBCursorRegion++;
  82. }
  83. break;
  84. case VK_UP:
  85. if (LBCursorListBoxItem) {
  86. LBCursorListBoxItem--;
  87. LBCursorRegion = 0;
  88. focusDir = DIR_UP;
  89. }
  90. break;
  91. case VK_DOWN:
  92. if (LBCursorListBoxItem < DiskCount-1) {
  93. LBCursorListBoxItem++;
  94. LBCursorRegion = 0;
  95. focusDir = DIR_DN;
  96. }
  97. break;
  98. }
  99. // don't allow list box cursor to fall on extended partition
  100. diskState = Disks[LBCursorListBoxItem];
  101. maxRegion = diskState->RegionCount - 1;
  102. if (IsExtended(diskState->RegionArray[LBCursorRegion].SysID)) {
  103. if (LBCursorRegion && ((vKey == VK_LEFT) || (LBCursorRegion == maxRegion))) {
  104. LBCursorRegion--;
  105. } else {
  106. LBCursorRegion++;
  107. }
  108. }
  109. ToggleLBCursor(NULL);
  110. break;
  111. case VK_TAB:
  112. ToggleLBCursor(NULL);
  113. if (GetKeyState(VK_SHIFT) & ~1) { // shift-tab
  114. LBCursorListBoxItem--;
  115. focusDir = DIR_UP;
  116. } else {
  117. LBCursorListBoxItem++;
  118. focusDir = DIR_DN;
  119. }
  120. if (LBCursorListBoxItem == (DWORD)(-1)) {
  121. LBCursorListBoxItem = DiskCount-1;
  122. focusDir = DIR_DN;
  123. } else if (LBCursorListBoxItem == DiskCount) {
  124. LBCursorListBoxItem = 0;
  125. focusDir = DIR_UP;
  126. }
  127. ResetLBCursorRegion();
  128. ToggleLBCursor(NULL);
  129. break;
  130. case VK_HOME:
  131. case VK_END:
  132. ToggleLBCursor(NULL);
  133. topItem = (vKey == VK_HOME) ? 0 : DiskCount-1;
  134. SendMessage(hwndList, LB_SETTOPINDEX, (DWORD)topItem, 0);
  135. LBCursorListBoxItem = topItem;
  136. ResetLBCursorRegion();
  137. ToggleLBCursor(NULL);
  138. break;
  139. case VK_PRIOR:
  140. case VK_NEXT:
  141. ToggleLBCursor(NULL);
  142. topItem = SendMessage(hwndList, LB_GETTOPINDEX, 0, 0);
  143. GetClientRect(hwndList,&rc);
  144. visibleItems = (rc.bottom - rc.top) / GraphHeight;
  145. if (!visibleItems) {
  146. visibleItems = 1;
  147. }
  148. topItem = (vKey == VK_PRIOR)
  149. ? max(topItem - visibleItems, 0)
  150. : min(topItem + visibleItems, (LONG)DiskCount-1);
  151. SendMessage(hwndList, LB_SETTOPINDEX, (DWORD)topItem, 0);
  152. LBCursorListBoxItem = SendMessage(hwndList, LB_GETTOPINDEX, 0, 0);
  153. ResetLBCursorRegion();
  154. ToggleLBCursor(NULL);
  155. break;
  156. case VK_RETURN:
  157. case VK_SPACE:
  158. // Select the region that currently has the list box selection cursor.
  159. if (!Disks[LBCursorListBoxItem]->OffLine) {
  160. Selection(GetKeyState(VK_CONTROL) & ~1, // strip toggle bit
  161. Disks[LBCursorListBoxItem],
  162. LBCursorRegion);
  163. }
  164. break;
  165. }
  166. // now scroll the newly focused item into view if necessary
  167. switch (focusDir) {
  168. case DIR_UP:
  169. if (LBCursorListBoxItem < (DWORD)SendMessage(hwndList, LB_GETTOPINDEX, 0, 0)) {
  170. SendMessage(hwndList, LB_SETTOPINDEX, LBCursorListBoxItem, 0);
  171. }
  172. break;
  173. case DIR_DN:
  174. GetClientRect(hwndList, &rc);
  175. topItem = SendMessage(hwndList, LB_GETTOPINDEX, 0, 0);
  176. bottomWholeItem = topItem + ((rc.bottom - rc.top) / GraphHeight) - 1;
  177. if (bottomWholeItem < topItem) {
  178. bottomWholeItem = topItem;
  179. }
  180. if ((DWORD)bottomWholeItem > DiskCount-1) {
  181. bottomWholeItem = DiskCount-1;
  182. }
  183. if (LBCursorListBoxItem > (DWORD)bottomWholeItem) {
  184. SendMessage(hwndList,
  185. LB_SETTOPINDEX,
  186. topItem + LBCursorListBoxItem - bottomWholeItem,
  187. 0);
  188. }
  189. break;
  190. }
  191. break;
  192. default:
  193. return CallWindowProc(OldListBoxProc, hwnd, msg, wParam, lParam);
  194. }
  195. return 0;
  196. }
  197. VOID
  198. SubclassListBox(
  199. IN HWND hwnd
  200. )
  201. {
  202. OldListBoxProc = (WNDPROC)GetWindowLong(hwnd, GWL_WNDPROC);
  203. SetWindowLong(hwnd, GWL_WNDPROC, (LONG)ListBoxSubProc);
  204. // There is a scantily documented 'feature' of a listbox wherein it will
  205. // use its parent's DC. This means that drawing is not always clipped to
  206. // the client area of the listbox. Seeing as we're subclassing listboxes
  207. // anyway, take care of this here.
  208. SetClassLong(hwnd, GCL_STYLE, GetClassLong(hwnd, GCL_STYLE) & ~CS_PARENTDC);
  209. }
  210. VOID
  211. DeselectSelectedRegions(
  212. VOID
  213. )
  214. /*++
  215. Routine Description:
  216. This routine visually unselects all selected regions. The selection
  217. state is also updated in the master disk structures.
  218. Arguments:
  219. None.
  220. Return Value:
  221. None.
  222. --*/
  223. {
  224. DWORD i,
  225. j;
  226. PDISKSTATE diskState;
  227. for (i=0; i<DiskCount; i++) {
  228. diskState = Disks[i];
  229. for (j=0; j<diskState->RegionCount; j++) {
  230. if (diskState->Selected[j]) {
  231. diskState->Selected[j] = FALSE;
  232. ToggleRegion(diskState, j, NULL);
  233. }
  234. }
  235. }
  236. }
  237. VOID
  238. Selection(
  239. IN BOOL MultipleSel,
  240. IN PDISKSTATE DiskState,
  241. IN DWORD RegionIndex
  242. )
  243. /*++
  244. Routine Description:
  245. This routine handles a user selection of a disk region. It is called
  246. directly for a keyboard selection or indirectly for a mouse selection.
  247. If not a multiple selection, all selected regions are deselected.
  248. The focus rectangle is moved to the selected region, which is then
  249. visually selected.
  250. Arguments:
  251. MultipleSel - whether the user has made a multiple selection
  252. (ie, control-clicked).
  253. DiskState - master disk structure for disk containing selected region
  254. RegionIndex - index of selected region on the disk
  255. Return Value:
  256. None.
  257. --*/
  258. {
  259. PFT_OBJECT ftObject,
  260. ftObj;
  261. PFT_OBJECT_SET ftSet;
  262. ULONG disk,
  263. r;
  264. if (!MultipleSel) {
  265. // need to deselect all selected regions first.
  266. DeselectSelectedRegions();
  267. }
  268. // remove the list box selection cursor from its previous region
  269. ToggleLBCursor(NULL);
  270. // The selected region might be part of an ft object set. If it is,
  271. // scan each region in each disk and select each item in the set.
  272. if (ftObject = GET_FT_OBJECT(&DiskState->RegionArray[RegionIndex])) {
  273. ftSet = ftObject->Set;
  274. for (disk=0; disk<DiskCount; disk++) {
  275. PDISKSTATE diskState = Disks[disk];
  276. for (r=0; r<diskState->RegionCount; r++) {
  277. PREGION_DESCRIPTOR regionDescriptor = &diskState->RegionArray[r];
  278. if (DmSignificantRegion(regionDescriptor)) {
  279. if (ftObj = GET_FT_OBJECT(regionDescriptor)) {
  280. if (ftObj->Set == ftSet) {
  281. diskState->Selected[r] = (BOOLEAN)(!diskState->Selected[r]);
  282. ToggleRegion(diskState, r, NULL);
  283. }
  284. }
  285. }
  286. }
  287. }
  288. } else {
  289. DiskState->Selected[RegionIndex] = (BOOLEAN)(!DiskState->Selected[RegionIndex]);
  290. ToggleRegion(DiskState, RegionIndex, NULL);
  291. }
  292. LBCursorListBoxItem = DiskState->Disk;
  293. LBCursorRegion = RegionIndex;
  294. ToggleLBCursor(NULL);
  295. AdjustMenuAndStatus();
  296. }
  297. VOID
  298. MouseSelection(
  299. IN BOOL MultipleSel,
  300. IN OUT PPOINT Point
  301. )
  302. /*++
  303. Routine Description:
  304. This routine is called when the user clicks in the list box. It determines
  305. which disk region the user has clicked on before calling the common
  306. selection subroutine.
  307. Arguments:
  308. MultipleSel - whether the user has made a multiple selection
  309. (ie, control-clicked).
  310. point - screen coords of the click
  311. Return Value:
  312. None.
  313. --*/
  314. {
  315. PDISKSTATE diskState;
  316. DWORD selectedItem;
  317. DWORD x,
  318. y;
  319. DWORD i;
  320. RECT rc;
  321. BOOL valid;
  322. if ((selectedItem = SendMessage(hwndList, LB_GETCURSEL, 0, 0)) == LB_ERR) {
  323. return;
  324. }
  325. // user has clicked on a list box item.
  326. diskState = Disks[selectedItem];
  327. // Ignore clicks on off-line disks.
  328. if (diskState->OffLine) {
  329. return;
  330. }
  331. ScreenToClient(hwndList, Point);
  332. x = Point->x;
  333. y = Point->y;
  334. GetClientRect(hwndList,&rc);
  335. // first make sure that the click was within a bar and not in space
  336. // between two bars
  337. for (valid=FALSE, i=rc.top; i<=(DWORD)rc.bottom; i+=GraphHeight) {
  338. if ((y >= i+BarTopYOffset) && (y <= i+BarBottomYOffset)) {
  339. valid = TRUE;
  340. break;
  341. }
  342. }
  343. if (!valid) {
  344. return;
  345. }
  346. // determine which region he has clicked on
  347. for (i=0; i<diskState->RegionCount; i++) {
  348. if ((x >= (unsigned)diskState->LeftRight[i].Left) && (x <= (unsigned)diskState->LeftRight[i].Right)) {
  349. break;
  350. }
  351. }
  352. if (i == diskState->RegionCount) {
  353. return; // region not found. Ignore the click.
  354. }
  355. Selection(MultipleSel, diskState, i);
  356. }
  357. LONG
  358. CalcBarTop(
  359. DWORD Bar
  360. )
  361. /*++
  362. Routine Description:
  363. This routine calculates the current top y coord of a given bar.
  364. The value is in listbox client coords.
  365. Arguments:
  366. Bar - # of bar whose position is desired
  367. Return Value:
  368. Y-coord, or -1 if bar is not visible.
  369. --*/
  370. {
  371. LONG barDelta = (LONG)Bar - SendMessage(hwndList, LB_GETTOPINDEX, 0, 0);
  372. LONG pos = -1;
  373. RECT rc;
  374. if (barDelta >= 0) { // BUGBUG check bottom too
  375. GetClientRect(hwndList,&rc);
  376. pos = rc.top + (barDelta * GraphHeight);
  377. }
  378. return pos;
  379. }
  380. VOID
  381. ResetLBCursorRegion(
  382. VOID
  383. )
  384. /*++
  385. Routine Description:
  386. This routine resets the list box focus cursor to the 0th (leftmost)
  387. region on the current disk. If the 0th region is the extended
  388. partition, focus is set to the first logical volume or free space
  389. with the extended partition instead.
  390. Arguments:
  391. None.
  392. Return Value:
  393. None.
  394. --*/
  395. {
  396. PDISKSTATE diskState = Disks[LBCursorListBoxItem];
  397. unsigned i;
  398. LBCursorRegion = 0;
  399. if (IsExtended(diskState->RegionArray[LBCursorRegion].SysID)) {
  400. for (i=0; i<diskState->RegionCount; i++) {
  401. if (diskState->RegionArray[i].RegionType == REGION_LOGICAL) {
  402. LBCursorRegion = i;
  403. return;
  404. }
  405. }
  406. FDASSERT(0);
  407. }
  408. }
  409. VOID
  410. ToggleLBCursor(
  411. IN HDC hdc
  412. )
  413. /*++
  414. Routine Description:
  415. This routine visually toggles the focus state of the disk region
  416. described by the LBCursorListBoxItem and LBCursorRegion globals.
  417. Arguments:
  418. hdc - If non-NULL, device context to use for drawing. If NULL,
  419. we'll first get a DC via GetDC().
  420. Return Value:
  421. None.
  422. --*/
  423. {
  424. PDISKSTATE lBCursorDisk = Disks[LBCursorListBoxItem];
  425. LONG barTop = CalcBarTop(LBCursorListBoxItem);
  426. RECT rc;
  427. HDC hdcActual;
  428. if (barTop != -1) {
  429. hdcActual = hdc ? hdc : GetDC(hwndList);
  430. LBCursorOn = !LBCursorOn;
  431. rc.left = lBCursorDisk->LeftRight[LBCursorRegion].Left;
  432. rc.right = lBCursorDisk->LeftRight[LBCursorRegion].Right + 1;
  433. rc.top = barTop + BarTopYOffset;
  434. rc.bottom = barTop + BarBottomYOffset;
  435. FrameRect(hdcActual,
  436. &rc,
  437. GetStockObject(LBCursorOn ? WHITE_BRUSH : BLACK_BRUSH));
  438. if (LBCursorOn) {
  439. // BUGBUG really want a dotted line.
  440. DrawFocusRect(hdcActual, &rc);
  441. }
  442. if (!hdc) {
  443. ReleaseDC(hwndList, hdcActual);
  444. }
  445. }
  446. }
  447. VOID
  448. ForceLBRedraw(
  449. VOID
  450. )
  451. /*++
  452. Routine Description:
  453. This routine forces redraw of the listbox by invalidating its
  454. entire client area.
  455. Arguments:
  456. None.
  457. Return Value:
  458. None.
  459. --*/
  460. {
  461. InvalidateRect(hwndList,NULL,FALSE);
  462. UpdateWindow(hwndList);
  463. }
  464. VOID
  465. ToggleRegion(
  466. IN PDISKSTATE DiskState,
  467. IN DWORD RegionIndex,
  468. IN HDC hdc
  469. )
  470. /*++
  471. Routine Description:
  472. This routine visually toggles the selection state of a given disk region.
  473. Arguments:
  474. DiskState - master structure for disk containing region to select
  475. RegionIndex - which region on the disk to toggle
  476. hdc - if non-NULL, device context to use for drawing. If NULL, we'll
  477. first get a device context via GetDC().
  478. Return Value:
  479. None.
  480. --*/
  481. {
  482. PLEFTRIGHT leftRight = &DiskState->LeftRight[RegionIndex];
  483. LONG barTop = CalcBarTop(DiskState->Disk); // BUGBUG disk# as lb index#
  484. BOOL selected = (BOOL)DiskState->Selected[RegionIndex];
  485. HBRUSH hbr = GetStockObject(BLACK_BRUSH);
  486. HDC hdcActual;
  487. RECT rc;
  488. int i;
  489. if (barTop != -1) {
  490. hdcActual = hdc ? hdc : GetDC(hwndList);
  491. rc.left = leftRight->Left + 1;
  492. rc.right = leftRight->Right;
  493. rc.top = barTop + BarTopYOffset + 1;
  494. rc.bottom = barTop + BarBottomYOffset - 1;
  495. if (selected) {
  496. for (i=0; i<SELECTION_THICKNESS; i++) {
  497. FrameRect(hdcActual, &rc, hbr);
  498. InflateRect(&rc, -1, -1);
  499. }
  500. } else {
  501. // Blt the region from the off-screen bitmap onto the
  502. // screen. But first exclude the center of the region
  503. // from the clip region so we only blt the necessary bits.
  504. // This sppeds up selections noticably.
  505. InflateRect(&rc, -SELECTION_THICKNESS, -SELECTION_THICKNESS);
  506. ExcludeClipRect(hdcActual, rc.left, rc.top, rc.right, rc.bottom);
  507. BitBlt(hdcActual,
  508. leftRight->Left,
  509. barTop + BarTopYOffset,
  510. leftRight->Right - leftRight->Left,
  511. barTop + BarBottomYOffset,
  512. DiskState->hDCMem,
  513. leftRight->Left,
  514. BarTopYOffset,
  515. SRCCOPY);
  516. }
  517. if (!hdc) {
  518. ReleaseDC(hwndList, hdcActual);
  519. }
  520. }
  521. }
  522. DWORD
  523. InitializeListBox(
  524. IN HWND hwndListBox
  525. )
  526. /*++
  527. Routine Description:
  528. This routine sets up the list box. This includes creating disk state
  529. structures, drawing the graphs for each disk off screen, and adding the
  530. disks to the list box.
  531. It also includes determining the initial volume labels and type names
  532. for all significant partitions.
  533. Arguments:
  534. hwndListBox - handle of the list box that will hold the disk graphs
  535. Return Value:
  536. Windows error code (esp. out of memory)
  537. --*/
  538. {
  539. PPERSISTENT_REGION_DATA regionData;
  540. TCHAR windowsDir[MAX_PATH];
  541. unsigned i;
  542. PDISKSTATE diskState;
  543. DWORD ec;
  544. ULONG r;
  545. BOOL diskSignaturesCreated,
  546. temp;
  547. // First, create the array that will hold the diskstates,
  548. // the IsDiskRemovable array and the RemovableDiskReservedDriveLetters
  549. // array.
  550. Disks = Malloc(DiskCount * sizeof(PDISKSTATE));
  551. IsDiskRemovable = (PBOOLEAN)Malloc(DiskCount * sizeof(BOOLEAN));
  552. RemovableDiskReservedDriveLetters = (PCHAR)Malloc(DiskCount * sizeof(CHAR));
  553. // Determine which disks are removable and which are unpartitioned.
  554. for (i=0; i<DiskCount; i++) {
  555. IsDiskRemovable[i] = IsRemovable( i );
  556. }
  557. // next, create all disk states
  558. FDASSERT(DiskCount);
  559. diskSignaturesCreated = FALSE;
  560. for (i=0; i<DiskCount; i++) {
  561. // first create the disk state structure
  562. CreateDiskState(&diskState, i, &temp);
  563. diskSignaturesCreated = diskSignaturesCreated || temp;
  564. Disks[i] = diskState;
  565. // next determine the state of the disk's partitioning scheme
  566. DeterminePartitioningState(diskState);
  567. // Next create a blank logical disk structure for each region.
  568. for (r=0; r<diskState->RegionCount; r++) {
  569. if (DmSignificantRegion(&diskState->RegionArray[r])) {
  570. regionData = Malloc(sizeof(PERSISTENT_REGION_DATA));
  571. DmInitPersistentRegionData(regionData, NULL, NULL, NULL, NO_DRIVE_LETTER_YET);
  572. regionData->VolumeExists = TRUE;
  573. } else {
  574. regionData = NULL;
  575. }
  576. DmSetPersistentRegionData(&diskState->RegionArray[r], regionData);
  577. }
  578. // add the item to the listbox
  579. while (((ec = SendMessage(hwndListBox, LB_ADDSTRING, 0, 0)) == LB_ERR) || (ec == LB_ERRSPACE)) {
  580. ConfirmOutOfMemory();
  581. }
  582. }
  583. // Read the configuration registry
  584. if ((ec = InitializeFt(diskSignaturesCreated)) != NO_ERROR) {
  585. ErrorDialog(ec);
  586. return ec;
  587. }
  588. // Determine drive letter mappings
  589. InitializeDriveLetterInfo();
  590. // Determine volume labels and type names.
  591. InitVolumeLabelsAndTypeNames();
  592. // Determine which disk is the boot disk.
  593. if (GetWindowsDirectory(windowsDir, sizeof(windowsDir)/sizeof(TCHAR)) < 2 ||
  594. windowsDir[1] != TEXT(':')) {
  595. BootDiskNumber = (ULONG)-1;
  596. BootPartitionNumber = (ULONG)-1;
  597. } else {
  598. BootDiskNumber = GetDiskNumberFromDriveLetter((CHAR)windowsDir[0]);
  599. BootPartitionNumber = GetPartitionNumberFromDriveLetter((CHAR)windowsDir[0]);
  600. }
  601. // Locate and create data structures for any DoubleSpace volumes
  602. DblSpaceInitialize();
  603. for (i=0; i<DiskCount; i++) {
  604. DrawDiskBar(Disks[i]);
  605. }
  606. return NO_ERROR;
  607. }
  608. VOID
  609. WMDrawItem(
  610. IN PDRAWITEMSTRUCT pDrawItem
  611. )
  612. {
  613. DWORD temp;
  614. PDISKSTATE pDiskState;
  615. if ((pDrawItem->itemID != (DWORD)(-1))
  616. && (pDrawItem->itemAction == ODA_DRAWENTIRE)) {
  617. pDiskState = Disks[pDrawItem->itemID];
  618. // blt the disk's bar from the off-screen bitmap to the screen
  619. BitBlt(pDrawItem->hDC,
  620. pDrawItem->rcItem.left,
  621. pDrawItem->rcItem.top,
  622. pDrawItem->rcItem.right - pDrawItem->rcItem.left + 1,
  623. pDrawItem->rcItem.bottom - pDrawItem->rcItem.top + 1,
  624. pDiskState->hDCMem,
  625. 0,
  626. 0,
  627. SRCCOPY);
  628. // if we just overwrote the focus cursor, redraw it
  629. if (pDrawItem->itemID == LBCursorListBoxItem) {
  630. LBCursorOn = FALSE;
  631. ToggleLBCursor(pDrawItem->hDC);
  632. }
  633. // select any items selected in this bar
  634. for (temp=0; temp<pDiskState->RegionCount; temp++) {
  635. if (pDiskState->Selected[temp]) {
  636. ToggleRegion(pDiskState, temp, pDrawItem->hDC);
  637. }
  638. }
  639. }
  640. }