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
233 lines
6.3 KiB
/**************************** 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;
|
|
}
|