|
|
/**************************** Module Header ********************************\
* Module Name: lboxvar.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * List Box variable height owner draw routines * * History: * ??-???-???? ianja Ported from Win 3.0 sources * 14-Feb-1991 mikeke Added Revalidation code (None) \***************************************************************************/
#include "precomp.h"
#pragma hdrstop
/***************************************************************************\
* LBGetVariableHeightItemHeight * * Returns the height of the given item number. Assumes variable * height owner draw. * * History: \***************************************************************************/
INT LBGetVariableHeightItemHeight( PLBIV plb, INT itemNumber) { BYTE itemHeight; int offsetHeight;
if (plb->cMac) { if (plb->fHasStrings) offsetHeight = plb->cMac * sizeof(LBItem); else offsetHeight = plb->cMac * sizeof(LBODItem);
if (plb->wMultiple) offsetHeight += plb->cMac;
offsetHeight += itemNumber;
itemHeight = *(plb->rgpch+(UINT)offsetHeight);
return (INT)itemHeight;
}
/*
*Default, we return the height of the system font. This is so we can draw * the focus rect even though there are no items in the listbox. */ return gpsi->cySysFontChar; }
/***************************************************************************\
* LBSetVariableHeightItemHeight * * Sets the height of the given item number. Assumes variable height * owner draw, a valid item number and valid height. * * * History: \***************************************************************************/
void LBSetVariableHeightItemHeight( PLBIV plb, INT itemNumber, INT itemHeight) { int offsetHeight;
if (plb->fHasStrings) offsetHeight = plb->cMac * sizeof(LBItem); else offsetHeight = plb->cMac * sizeof(LBODItem);
if (plb->wMultiple) offsetHeight += plb->cMac;
offsetHeight += itemNumber;
*(plb->rgpch + (UINT)offsetHeight) = (BYTE)itemHeight;
}
/***************************************************************************\
* CItemInWindowVarOwnerDraw * * Returns the number of items which can fit in a variable height OWNERDRAW * list box. If fDirection, then we return the number of items which * fit starting at sTop and going forward (for page down), otherwise, we are * going backwards (for page up). (Assumes var height ownerdraw) If fPartial, * then include the partially visible item at the bottom of the listbox. * * History: \***************************************************************************/
INT CItemInWindowVarOwnerDraw( PLBIV plb, BOOL fPartial) { RECT rect; INT sItem; INT clientbottom;
_GetClientRect(plb->spwnd, (LPRECT)&rect); clientbottom = rect.bottom;
/*
* Find the number of var height ownerdraw items which are visible starting * from plb->iTop. */ for (sItem = plb->iTop; sItem < plb->cMac; sItem++) {
/*
* Find out if the item is visible or not */ if (!LBGetItemRect(plb, sItem, (LPRECT)&rect)) {
/*
* This is the first item which is completely invisible, so return * how many items are visible. */ return (sItem - plb->iTop); }
if (!fPartial && rect.bottom > clientbottom) {
/*
* If we only want fully visible items, then if this item is * visible, we check if the bottom of the item is below the client * rect, so we return how many are fully visible. */ return (sItem - plb->iTop - 1); } }
/*
* All the items are visible */ return (plb->cMac - plb->iTop); }
/***************************************************************************\
* LBPage * * For variable height ownerdraw listboxes, calaculates the new iTop we must * move to when paging (page up/down) through variable height listboxes. * * History: \***************************************************************************/
INT LBPage( PLBIV plb, INT startItem, BOOL fPageForwardDirection) { INT i; INT height; RECT rc;
if (plb->cMac == 1) return(0);
_GetClientRect(plb->spwnd, &rc); height = rc.bottom; i = startItem;
if (fPageForwardDirection) { while ((height >= 0) && (i < plb->cMac)) height -= LBGetVariableHeightItemHeight(plb, i++);
return((height >= 0) ? plb->cMac - 1 : max(i - 2, startItem + 1)); } else { while ((height >= 0) && (i >= 0)) height -= LBGetVariableHeightItemHeight(plb, i--);
return((height >= 0) ? 0 : min(i + 2, startItem - 1)); }
}
/***************************************************************************\
* LBCalcVarITopScrollAmt * * Changing the top most item in the listbox from iTopOld to iTopNew we * want to calculate the number of pixels to scroll so that we minimize the * number of items we will redraw. * * History: \***************************************************************************/
INT LBCalcVarITopScrollAmt( PLBIV plb, INT iTopOld, INT iTopNew) { RECT rc; RECT rcClient;
_GetClientRect(plb->spwnd, (LPRECT)&rcClient);
/*
* Just optimize redrawing when move +/- 1 item. We will redraw all items * if moving more than 1 item ahead or back. This is good enough for now. */ if (iTopOld + 1 == iTopNew) {
/*
* We are scrolling the current iTop up off the top off the listbox so * return a negative number. */ LBGetItemRect(plb, iTopOld, (LPRECT)&rc); return (rcClient.top - rc.bottom); }
if (iTopOld - 1 == iTopNew) {
/*
* We are scrolling the current iTop down and the previous item is * becoming the new iTop so return a positive number. */ LBGetItemRect(plb, iTopNew, (LPRECT)&rc); return -rc.top; }
return rcClient.bottom - rcClient.top; }
|