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.

233 lines
6.3 KiB

  1. /**************************** Module Header ********************************\
  2. * Module Name: lboxvar.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * List Box variable height owner draw routines
  7. *
  8. * History:
  9. * ??-???-???? ianja Ported from Win 3.0 sources
  10. * 14-Feb-1991 mikeke Added Revalidation code (None)
  11. \***************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. /***************************************************************************\
  15. * LBGetVariableHeightItemHeight
  16. *
  17. * Returns the height of the given item number. Assumes variable
  18. * height owner draw.
  19. *
  20. * History:
  21. \***************************************************************************/
  22. INT LBGetVariableHeightItemHeight(
  23. PLBIV plb,
  24. INT itemNumber)
  25. {
  26. BYTE itemHeight;
  27. int offsetHeight;
  28. if (plb->cMac) {
  29. if (plb->fHasStrings)
  30. offsetHeight = plb->cMac * sizeof(LBItem);
  31. else
  32. offsetHeight = plb->cMac * sizeof(LBODItem);
  33. if (plb->wMultiple)
  34. offsetHeight += plb->cMac;
  35. offsetHeight += itemNumber;
  36. itemHeight = *(plb->rgpch+(UINT)offsetHeight);
  37. return (INT)itemHeight;
  38. }
  39. /*
  40. *Default, we return the height of the system font. This is so we can draw
  41. * the focus rect even though there are no items in the listbox.
  42. */
  43. return gpsi->cySysFontChar;
  44. }
  45. /***************************************************************************\
  46. * LBSetVariableHeightItemHeight
  47. *
  48. * Sets the height of the given item number. Assumes variable height
  49. * owner draw, a valid item number and valid height.
  50. *
  51. *
  52. * History:
  53. \***************************************************************************/
  54. void LBSetVariableHeightItemHeight(
  55. PLBIV plb,
  56. INT itemNumber,
  57. INT itemHeight)
  58. {
  59. int offsetHeight;
  60. if (plb->fHasStrings)
  61. offsetHeight = plb->cMac * sizeof(LBItem);
  62. else
  63. offsetHeight = plb->cMac * sizeof(LBODItem);
  64. if (plb->wMultiple)
  65. offsetHeight += plb->cMac;
  66. offsetHeight += itemNumber;
  67. *(plb->rgpch + (UINT)offsetHeight) = (BYTE)itemHeight;
  68. }
  69. /***************************************************************************\
  70. * CItemInWindowVarOwnerDraw
  71. *
  72. * Returns the number of items which can fit in a variable height OWNERDRAW
  73. * list box. If fDirection, then we return the number of items which
  74. * fit starting at sTop and going forward (for page down), otherwise, we are
  75. * going backwards (for page up). (Assumes var height ownerdraw) If fPartial,
  76. * then include the partially visible item at the bottom of the listbox.
  77. *
  78. * History:
  79. \***************************************************************************/
  80. INT CItemInWindowVarOwnerDraw(
  81. PLBIV plb,
  82. BOOL fPartial)
  83. {
  84. RECT rect;
  85. INT sItem;
  86. INT clientbottom;
  87. _GetClientRect(plb->spwnd, (LPRECT)&rect);
  88. clientbottom = rect.bottom;
  89. /*
  90. * Find the number of var height ownerdraw items which are visible starting
  91. * from plb->iTop.
  92. */
  93. for (sItem = plb->iTop; sItem < plb->cMac; sItem++) {
  94. /*
  95. * Find out if the item is visible or not
  96. */
  97. if (!LBGetItemRect(plb, sItem, (LPRECT)&rect)) {
  98. /*
  99. * This is the first item which is completely invisible, so return
  100. * how many items are visible.
  101. */
  102. return (sItem - plb->iTop);
  103. }
  104. if (!fPartial && rect.bottom > clientbottom) {
  105. /*
  106. * If we only want fully visible items, then if this item is
  107. * visible, we check if the bottom of the item is below the client
  108. * rect, so we return how many are fully visible.
  109. */
  110. return (sItem - plb->iTop - 1);
  111. }
  112. }
  113. /*
  114. * All the items are visible
  115. */
  116. return (plb->cMac - plb->iTop);
  117. }
  118. /***************************************************************************\
  119. * LBPage
  120. *
  121. * For variable height ownerdraw listboxes, calaculates the new iTop we must
  122. * move to when paging (page up/down) through variable height listboxes.
  123. *
  124. * History:
  125. \***************************************************************************/
  126. INT LBPage(
  127. PLBIV plb,
  128. INT startItem,
  129. BOOL fPageForwardDirection)
  130. {
  131. INT i;
  132. INT height;
  133. RECT rc;
  134. if (plb->cMac == 1)
  135. return(0);
  136. _GetClientRect(plb->spwnd, &rc);
  137. height = rc.bottom;
  138. i = startItem;
  139. if (fPageForwardDirection) {
  140. while ((height >= 0) && (i < plb->cMac))
  141. height -= LBGetVariableHeightItemHeight(plb, i++);
  142. return((height >= 0) ? plb->cMac - 1 : max(i - 2, startItem + 1));
  143. } else {
  144. while ((height >= 0) && (i >= 0))
  145. height -= LBGetVariableHeightItemHeight(plb, i--);
  146. return((height >= 0) ? 0 : min(i + 2, startItem - 1));
  147. }
  148. }
  149. /***************************************************************************\
  150. * LBCalcVarITopScrollAmt
  151. *
  152. * Changing the top most item in the listbox from iTopOld to iTopNew we
  153. * want to calculate the number of pixels to scroll so that we minimize the
  154. * number of items we will redraw.
  155. *
  156. * History:
  157. \***************************************************************************/
  158. INT LBCalcVarITopScrollAmt(
  159. PLBIV plb,
  160. INT iTopOld,
  161. INT iTopNew)
  162. {
  163. RECT rc;
  164. RECT rcClient;
  165. _GetClientRect(plb->spwnd, (LPRECT)&rcClient);
  166. /*
  167. * Just optimize redrawing when move +/- 1 item. We will redraw all items
  168. * if moving more than 1 item ahead or back. This is good enough for now.
  169. */
  170. if (iTopOld + 1 == iTopNew) {
  171. /*
  172. * We are scrolling the current iTop up off the top off the listbox so
  173. * return a negative number.
  174. */
  175. LBGetItemRect(plb, iTopOld, (LPRECT)&rc);
  176. return (rcClient.top - rc.bottom);
  177. }
  178. if (iTopOld - 1 == iTopNew) {
  179. /*
  180. * We are scrolling the current iTop down and the previous item is
  181. * becoming the new iTop so return a positive number.
  182. */
  183. LBGetItemRect(plb, iTopNew, (LPRECT)&rc);
  184. return -rc.top;
  185. }
  186. return rcClient.bottom - rcClient.top;
  187. }