Odvarlb.exe Pages Down in Owner-Draw Variable List Box |
Q112640
Using the Microsoft Windows 3.1 SDK, when page down is used in an owner-
draw variable list box, the selection is changed to the last visible item
in the list box (as it should). However, at this point no subsequent page
downs will work.
To address the page-down problem, the owner-draw variable list box is
subclassed. In the subclass procedure, WM_KEYDOWN is processed. When wParam
is VK_NEXT, the PAGE DOWN key was pressed, and the actual paging down is
implemented. The ODVARLB sample shows how to work around this problem.
The following files are available for download from the Microsoft
Download Center:
Odvarlb.exe
For additional information about how to download Microsoft Support
files, click the article number below
to view the article in the Microsoft Knowledge Base:
Q119591 How to Obtain Microsoft Support Files from Online ServicesMicrosoft used the most current virus detection software available on the date of posting to scan this file for viruses. Once posted, the file is housed on secure servers that prevent any unauthorized changes to the file.
// Get maximum number of items in the list box.
iMaxItems = SendMessage(hWnd,LB_GETCOUNT,0,0L);
// Get the index for the item which is to be at the top.
iTopIdx = SendMessage(hWnd,LB_GETCURSEL,0,0L);
// If the focus is already on the last item, we have reached
// the end of the list so just return.
if (iTopIdx != (iMaxItems -1))
// Continue we have more work to do.
// Get the client area rectangle of the list box.
GetClientRect(hWnd, &rc);
// Get the index for the last visible item in the list
// box based on the new top item.
iBottomIdx = GetLBIndex(hWnd,iTopIdx,iMaxItems,rc.bottom);
The GetLBIndex() function finds the last item that should be visible
after the page down is completed. Below is the code for GetLBIndex:
int GetLBIndex(HWND hLB,int iTopIdx,UINT iMaxLBItems, int lbHeight)
{
MEASUREITEMSTRUCT mis;
int ItmHeights = 0; // Keeps track of total item heights.
// Set up the measure item structures fields.
mis.CtlType = ODT_LISTBOX;
mis.itemID = iTopIdx;
while (mis.itemID <= (iMaxLBItems - 1))
{
// Get the items measurement, height in particular.
SendMessage(GetParent(hLB),WM_MEASUREITEM,
0, (LPARAM)(LPMEASUREITEMSTRUCT)&mis);
// Add it to our total height.
ItmHeights += mis.itemHeight;
// If the total item height is still less than
// the list box:
if (ItmHeights <= lbHeight)
// Unless we have reached the end of out list.
if (mis.itemID == (iMaxLBItems - 1))
// In this case, return the index to the last item in the list.
return (mis.itemID);
else
// Check the next item, we want to cycle through again.
++mis.itemID ;
else
// We have found the last item to be displayed in the list box
// so return it.
return (--mis.itemID);
}
return (iTopIdx);
}
// Special case: When the height of the list box is less than or
// equal to the height of an item, the list box displays only one
// item or part of an item at a time. So, when paging down we need
// to display the next item in the list.
if (iBottomIdx <= iTopIdx)
iBottomIdx = ++iTopIdx;
// Move the item that had the focus to the top, then set the
// selection to the last visible item in the list box.
SendMessage(hWnd,LB_SETCURSEL,(WPARAM) iBottomIdx, 0L);
SendMessage(hWnd,LB_SETTOPINDEX,(WPARAM) iTopIdx, 0L);
NOTE: Just doing this will cause flashing so the painting is turned off
in the list box until the page down process is complete. Then the entire
list box is invalidated and the list box window is updated to reflect
the changes.
// Turn off all painting to prevent flashing.
SendMessage(hWnd, WM_SETREDRAW, (WPARAM) FALSE,0L);
// Move the item that had the focus to the top, then set the
// focus to the last visible item in the list box.
SendMessage(hWnd,LB_SETCURSEL,(WPARAM) iBottomIdx, 0L);
SendMessage(hWnd,LB_SETTOPINDEX,(WPARAM) iTopIdx, 0L);
// We are done, so turn on painting. Invalidate the list box window
// for painting and then update the list window.
SendMessage(hWnd, WM_SETREDRAW, (WPARAM) TRUE,0L);
InvalidateRect(hWnd,NULL,TRUE);
UpdateWindow(hWnd);
However, adding the WM_SETREDRAW messages to eliminate flashing prevents
the scroll bar from being updated. To address this problem, the scroll
bar position is retrieved via GetScrollPos() and then reset and painted
via SetScrollPos().
pos = GetScrollPos(hWnd,SB_VERT);
SetScrollPos(hWnd,SB_VERT,pos,TRUE);
The code for this workaround is the ODLB.C file. All the necessary code
for this workaround is actually contained in two functions,
SbListSubProc() - The subclass procedure for the list box.
GetLBIndex() - Finds the last visible item in the list box
after paging down. Additional query words: owner draw listbox
Keywords : kbfile kbsample kb16bitonly kbCtrl kbListBox kbSDKPlatform kbGrpDSUser kbOSWin310
Issue type :
Technology : kbAudDeveloper kbWin3xSearch kbSDKSearch kbWinSDKSearch kbWinSDK310
|
Last Reviewed: December 10, 1999 © 2001 Microsoft Corporation. All rights reserved. Terms of Use. |