test: lboxvar.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# lboxvar.c

Go to the documentation of this file.

    00001 /**************************** Module Header ********************************\
    00002 * Module Name: lboxvar.c
    00003 *
    00004 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00005 *
    00006 * List Box variable height owner draw routines
    00007 *
    00008 * History:
    00009 * ??-???-???? ianja    Ported from Win 3.0 sources
    00010 * 14-Feb-1991 mikeke   Added Revalidation code (None)
    00011 \***************************************************************************/
    00012
    00013 #include "precomp.h"
    00014 #pragma hdrstop
    00015
    00016 /***************************************************************************\
    00017 * LBGetVariableHeightItemHeight
    00018 *
    00019 * Returns the height of the given item number. Assumes variable
    00020 * height owner draw.
    00021 *
    00022 * History:
    00023 \***************************************************************************/
    00024
    00025 INT LBGetVariableHeightItemHeight(
    00026     PLBIV plb,
    00027     INT itemNumber)
    00028 {
    00029     BYTE itemHeight;
    00030     int offsetHeight;
    00031
    00032     if (plb->cMac) {
    00033         if (plb->fHasStrings)
    00034             offsetHeight = plb->cMac * sizeof(LBItem);
    00035         else
    00036             offsetHeight = plb->cMac * sizeof(LBODItem);
    00037
    00038         if (plb->wMultiple)
    00039             offsetHeight += plb->cMac;
    00040
    00041         offsetHeight += itemNumber;
    00042
    00043         itemHeight = *(plb->rgpch+(UINT)offsetHeight);
    00044
    00045         return (INT)itemHeight;
    00046
    00047     }
    00048
    00049     /*
    00050      *Default, we return the height of the system font.  This is so we can draw
    00051      * the focus rect even though there are no items in the listbox.
    00052      */
    00053     return gpsi->cySysFontChar;
    00054 }
    00055
    00056
    00057 /***************************************************************************\
    00058 * LBSetVariableHeightItemHeight
    00059 *
    00060 * Sets the height of the given item number. Assumes variable height
    00061 * owner draw, a valid item number and valid height.
    00062 *
    00063 *
    00064 * History:
    00065 \***************************************************************************/
    00066
    00067 void LBSetVariableHeightItemHeight(
    00068     PLBIV plb,
    00069     INT itemNumber,
    00070     INT itemHeight)
    00071 {
    00072     int offsetHeight;
    00073
    00074     if (plb->fHasStrings)
    00075         offsetHeight = plb->cMac * sizeof(LBItem);
    00076     else
    00077         offsetHeight = plb->cMac * sizeof(LBODItem);
    00078
    00079     if (plb->wMultiple)
    00080         offsetHeight += plb->cMac;
    00081
    00082     offsetHeight += itemNumber;
    00083
    00084     *(plb->rgpch + (UINT)offsetHeight) = (BYTE)itemHeight;
    00085
    00086 }
    00087
    00088
    00089 /***************************************************************************\
    00090 * CItemInWindowVarOwnerDraw
    00091 *
    00092 * Returns the number of items which can fit in a variable height OWNERDRAW
    00093 * list box. If fDirection, then we return the number of items which
    00094 * fit starting at sTop and going forward (for page down), otherwise, we are
    00095 * going backwards (for page up). (Assumes var height ownerdraw) If fPartial,
    00096 * then include the partially visible item at the bottom of the listbox.
    00097 *
    00098 * History:
    00099 \***************************************************************************/
    00100
    00101 INT CItemInWindowVarOwnerDraw(
    00102     PLBIV plb,
    00103     BOOL fPartial)
    00104 {
    00105     RECT rect;
    00106     INT sItem;
    00107     INT clientbottom;
    00108
    00109     _GetClientRect(plb->spwnd, (LPRECT)&rect);
    00110     clientbottom = rect.bottom;
    00111
    00112     /*
    00113      * Find the number of var height ownerdraw items which are visible starting
    00114      * from plb->iTop.
    00115      */
    00116     for (sItem = plb->iTop; sItem < plb->cMac; sItem++) {
    00117
    00118         /*
    00119          * Find out if the item is visible or not
    00120          */
    00121         if (!LBGetItemRect(plb, sItem, (LPRECT)&rect)) {
    00122
    00123             /*
    00124              * This is the first item which is completely invisible, so return
    00125              * how many items are visible.
    00126              */
    00127             return (sItem - plb->iTop);
    00128         }
    00129
    00130         if (!fPartial && rect.bottom > clientbottom) {
    00131
    00132             /*
    00133              * If we only want fully visible items, then if this item is
    00134              * visible, we check if the bottom of the item is below the client
    00135              * rect, so we return how many are fully visible.
    00136              */
    00137             return (sItem - plb->iTop - 1);
    00138         }
    00139     }
    00140
    00141     /*
    00142      * All the items are visible
    00143      */
    00144     return (plb->cMac - plb->iTop);
    00145 }
    00146
    00147
    00148 /***************************************************************************\
    00149 * LBPage
    00150 *
    00151 * For variable height ownerdraw listboxes, calaculates the new iTop we must
    00152 * move to when paging (page up/down) through variable height listboxes.
    00153 *
    00154 * History:
    00155 \***************************************************************************/
    00156
    00157 INT LBPage(
    00158     PLBIV plb,
    00159     INT startItem,
    00160     BOOL fPageForwardDirection)
    00161 {
    00162     INT     i;
    00163     INT height;
    00164     RECT    rc;
    00165
    00166     if (plb->cMac == 1)
    00167         return(0);
    00168
    00169     _GetClientRect(plb->spwnd, &rc);
    00170     height = rc.bottom;
    00171     i = startItem;
    00172
    00173     if (fPageForwardDirection) {
    00174         while ((height >= 0) && (i < plb->cMac))
    00175             height -= LBGetVariableHeightItemHeight(plb, i++);
    00176
    00177         return((height >= 0) ? plb->cMac - 1 : max(i - 2, startItem + 1));
    00178     } else {
    00179         while ((height >= 0) && (i >= 0))
    00180             height -= LBGetVariableHeightItemHeight(plb, i--);
    00181
    00182         return((height >= 0) ? 0 : min(i + 2, startItem - 1));
    00183     }
    00184
    00185 }
    00186
    00187
    00188 /***************************************************************************\
    00189 * LBCalcVarITopScrollAmt
    00190 *
    00191 * Changing the top most item in the listbox from iTopOld to iTopNew we
    00192 * want to calculate the number of pixels to scroll so that we minimize the
    00193 * number of items we will redraw.
    00194 *
    00195 * History:
    00196 \***************************************************************************/
    00197
    00198 INT LBCalcVarITopScrollAmt(
    00199     PLBIV plb,
    00200     INT iTopOld,
    00201     INT iTopNew)
    00202 {
    00203     RECT rc;
    00204     RECT rcClient;
    00205
    00206     _GetClientRect(plb->spwnd, (LPRECT)&rcClient);
    00207
    00208     /*
    00209      * Just optimize redrawing when move +/- 1 item.  We will redraw all items
    00210      * if moving more than 1 item ahead or back.  This is good enough for now.
    00211      */
    00212     if (iTopOld + 1 == iTopNew) {
    00213
    00214         /*
    00215          * We are scrolling the current iTop up off the top off the listbox so
    00216          * return a negative number.
    00217          */
    00218         LBGetItemRect(plb, iTopOld, (LPRECT)&rc);
    00219         return (rcClient.top - rc.bottom);
    00220     }
    00221
    00222     if (iTopOld - 1 == iTopNew) {
    00223
    00224         /*
    00225          * We are scrolling the current iTop down and the previous item is
    00226          * becoming the new iTop so return a positive number.
    00227          */
    00228         LBGetItemRect(plb, iTopNew, (LPRECT)&rc);
    00229         return -rc.top;
    00230     }
    00231
    00232     return rcClient.bottom - rcClient.top;
    00233 }