The information in this article applies to:
SUMMARYLisThorz.exe and ListHsc.exe demonstrate how to fully control the horizontal scroll bar on a list box. This information is also available in Tips.hlp, which is included with Microsoft Visual C/C++. LisThorz.exe and ListHsc.exe contain a set of horizontal scroll bar support functions that maintain the extents of all strings in the list box and change the scrollable list box extent as required. Additional details on these samples are found in the Sample Code section of this article. MORE INFORMATIONThe following files are available for download from the Microsoft
Download Center. Click the file names below to download the files: LisThorz.exe ListHsc.exeFor more information about how to download files from the Microsoft Download Center, please visit the Download Center at the following Web address http://www.microsoft.com/downloads/search.aspand then click How to use the Microsoft Download Center. LisThorz.exe contains a complete sample application demonstrating a list box with a horizontal scroll bar. The necessary support functions are contained in a C module that can be compiled and linked to any Windows- based application. ListHsc.exe contains the complete sources for a DLL that contains the necessary list box support functions. These functions are exactly the same as those in LisThorz.exe. Included in this archive is an application that uses the services of the DLL to perform the same functions as the application in LisThorz.exe. The following is an outline of the information presented in this article: A. Windows support for a horizontal scroll bar on a list box
G. Sample code
Windows Support for Horizontal Scroll Bar in a List BoxMicrosoft Windows version 3.0 is the first version that recognizes the WS_HSCROLL window style for list boxes. This style adds a horizontal scroll bar to the list box. However, the scroll bar does not appear automatically when a string that is too long to display in a list box is added to that list box. Similarly, when the last string longer than the list box is removed, Windows will not hide the scroll bar. This behavior is different from that of the vertical scroll bar of a list box, which is added and removed as needed.An application must maintain the width, in pixels, of each string in the list box. The LB_SETHORIZONTALEXTENT list box message controls both the scrolling range and the visibility of a horizontal scroll bar. In this article, the term "extent" is defined to be the width of an object in screen pixels. Each string has an extent as does the list box itself. The other sections of this article provide more detailed information about special considerations that must occur when dealing with horizontal scroll bars in list boxes. New List Box Messages: LB_SETHORIZONTALEXTENT and LB_GETHORIZONTALEXTENTTwo messages have been added to Windows 3.0 to support horizontal scroll bars in list boxes:
By default, the horizontal scroll bar extent of a list box is 0 (zero).
Because 0 is less than the width of the list box client area, Windows will
not add a scroll bar to the window until the scroll bar extent is changed
to a value larger than the list box extent.
However, the LB_SETHORIZONTALEXTENT message does not affect the visibility of a horizontal scroll bar. If a scroll bar is visible, sending this message with a small extent specified will not remove it. Likewise, if a scroll bar is not present, sending this message with a large extent will not create one. The next two sections of this article explain how to add and remove a horizontal scroll bar as strings are added and deleted. The major point is that Windows will only show or hide the scroll bar when a string is added, inserted, or deleted. Making the Scroll Bar Visible When Adding or Inserting a StringWhen a string with an extent larger than the width of the list box is to be added, an application must send the LB_SETHORIZONTALEXTENT message before sending an LB_ADDSTRING or LB_INSERTSTRING message.During the process of adding or inserting a string, Windows compares the horizontal scroll bar extent stored in the list box to the width of the list box client area. If the client area extent is smaller than the scroll bar extent, the scroll bar is made visible the next time the list box is drawn. The client area width of the list box does not include the width of the vertical scroll bar, if it is visible. Consider a list box without a vertical scroll bar, that is filled with strings. Each of these strings is slightly narrower than the list box. When another string is added, and the vertical scroll bar is caused to appear, Windows discovers that the horizontal scroll bar extent is now greater than the width of the list box, and adds a horizontal scroll bar. If the scroll bar extent is less than the width of the client area of the list box, the status of the scroll bar remains unchanged. If the list box is not drawn after the string is added, the scroll bar will not appear. Therefore, if the WM_SETREDRAW message is used to turn redraw off, adding a string will not show the horizontal scroll bar until the list box is redrawn. Hiding the Scroll Bar When Deleting a StringWindows only removes the horizontal scroll bar during the processing of an LB_DELETESTRING message. Therefore, if the string to be deleted is the longest in the list box, the horizontal scroll bar extent must be changed to the next smaller extent value before that string is deleted. After the string is deleted, Windows compares the stored scroll bar extent to the width of the client area of the list box, and if the extent is smaller, the scroll bar is removed.If the list box is not drawn after the string is deleted, the scroll bar will not disappear. Therefore, if the WM_SETREDRAW message is used to turn redraw off, deleting a string will not remove the horizontal scroll bar until the list box is redrawn. However, if the list box is scrolled to the right by as little as one pixel, the scroll bar will remain visible, regardless of the extent that is set. This is done so that the user can always scroll back to the extreme left. If the scroll bar was removed, the list box might be left in a state where it is scrolled to the right by some amount without any way to scroll back completely to the left. To work around this problem, always scroll the list box to the extreme left before deleting the longest string. If a shorter string is deleted, the extent will remain the same and the horizontal scroll bar will not be affected anyway. Only scroll the list box if the longest string is being deleted. The list box can be scrolled either completely to the left (in the case where a long string still exists in the list box) or just enough so that the next longest string is visible, assuming that the list box requires a scroll bar. The sample code in the Software Library (described above) always scrolls the list box completely left, using the WM_HSCROLL message, as follows:
The LB_RESETCONTENT message does not affect the state of the horizontal
scroll bar even though all strings in the list box are deleted. Before an
LB_RESETCONTENT message is sent, an application must perform the following
steps:
Calculating Horizontal Extents of StringsThe previous discussion mentions the extents of strings, but provides no methods for determining these values.Pixel extents of strings are calculated by the GetTextExtent function. This is a GDI call that sums the pixel width of each character in a string using the font that is currently selected into a display context represented by an hDC. If lpString holds a representative string and hWndListBox is the window handle to the list box, the following steps are required to determine the size of each string:
The tmAveCharWidth field in the TEXTMETRIC structure provides a consistent number of pixels to add to the length of the string, no matter what font is presently in use. This buffer space keeps the strings from being clipped. As a side note, the value of tmAveCharWidth is the number of pixels by which the list box is scrolled horizontally when the scroll bar arrows are clicked. If a fixed pitch font is used, the list box is scrolled horizontally by one character for each click. Maintenance of All Extents in List BoxMany possible methods can be used to maintain a list of the extents of the strings in the list box. One of the most convenient methods is to use property lists, as shown in the sample code.Every window has a property list associated with it. Each property is a string and an associated data handle. A window stores and retrieves each data handle using the string that labels the handle. A sorted list of the extents for strings in the list box can be saved in a local or global memory object. This allows each window to keep its own list and does not require that the application maintain a mapping from the list box to the data handle itself. The list of extents should be sorted in descending order, so that the first extent in the list is that of the longest string in the list box. Keeping this list sorted also allows the application to use a binary search to find an extent in the list when one is being inserted or deleted. When a new string is added, insert that string's extent into the list, maintaining the sorted order. If the new extent is placed at the top of the list, send an LB_SETHORIZONTALEXTENT message to the list box specifying the new extent. Do not send the message for an extent that is not the largest. When a string is deleted, remove that string's extent from the list. If the extent is the first in the list, then that string is the longest in the list box. In this case, send an LB_SETHORIZONTALEXTENT to the list box specifying the next largest extent in the list. If a smaller string is deleted, do not send the message. When an LB_RESETCONTENT message is used, clear the entire list of extents. Send an LB_SETHORIZONTALEXTENT message specifying an extent of 0 (zero), followed by an LB_DELETESTRING as outlined in the last part of the section above titled "Hiding the Scroll Bar When Deleting a String." Sample CodeAs mentioned above, there are two archives in the Microsoft Software Library: LISTHORZ and LISTHSCR. Each of these samples provides five support functions that greatly facilitate the maintenance of horizontal scroll bars in list boxes.In LISTHORZ, these functions are found in the file LISTHELP.C. This file can be compiled separately and linked into an application. LISTHSCR contains the source files for a DLL that provides these five support functions. The C file for the DLL is exactly the same as in LISTHORZ, except that its name has changed. This archive also includes a LISTHORZ program that uses the services of the DLL to perform the same functions as the program in the other archive. The file LISTHAPI.H is the include file containing prototypes of the functions exported by the DLL. Also included is an import library, LISTHSCR.LIB, that is generated by the makefile. The DLL is most useful because it can support horizontal scroll bars in any number of list boxes in any number of applications. The remainder of this article documents the support functions:
Allocates local memory to store a list of string extents for the
list box identified by hList. The handle to this local memory is
saved in the property list of the list box. This function should be
called after the list box is created, such as during WM_INITDIALOG
processing.
Parameters: hList HWND Handle to the list box that will use a horizontal scroll bar. Return Value: BOOL TRUE if there are no errors, FALSE if memory could not be allocated. BOOL FFreeListboxExtents(HWND hList)Frees the memory allocated for the extent list of the list box identified by hList. The property that stores the memory handle set by FInitListboxExtents is removed. This function should be called when the list box is being destroyed. Parameters: hList HWND Handle to the list box that was previously used with FInitListboxExtents Return Value: BOOL TRUE if there are no errors, FALSE if memory could not be freed, in which case the property is not removed.
Removes all previously saved extents in the extent list. This is
accomplished by calling FFreeListboxExtents and FInitListboxExtents
in succession. The horizontal extent of the list box is set to 0
(zero) and any horizontal scroll bar is removed. This function
should be called before an LB_RESETCONTENT message is sent to the
list box.
Parameters: hList HWND Handle to the list box that will be reset. Return Value: none
Adds an extent entry into the list box's extent list. The extent
added is that of the string pointed to by psz using the current font
in the list box. If the extent added is larger than any other in the
extent list, an LB_SETHORIZONTALEXTENT message is sent to the list
box with this new extent.
This function must be called before the string is added to the list box with LB_ADDSTRING or LB_INSERTSTRING. Parameters: hList HWND Handle to the list box to which the string is to be added. psz LPSTR Pointer to string that is to be added. This function must be called before the string is added so that the horizontal scroll bar will be properly maintained. Return Value: WORD One of these three values: 0 if the string added was not the longest string in the list box and the visibility of the horizontal scroll bar did not change. The extent of the string added, if the added string was the longest and the visibility of the scroll bar may have changed. -1 for an error.
Removes the extent entry of the string identified by index iSel in
the list box. If the string to be removed is the longest in the list
box, the list box is scrolled completely to the left and the
horizontal extent is set to that of the next longest string.
This function must be called before an LB_DELETESTRING message is sent to the list box. Parameters: hList HWND Handle to the list box from which a string is to be removed. iSel WORD Index of the string to be removed. Return Value: WORD One of these three values: 0 if the string removed was not the longest in the list box and the visibility of the horizontal scroll bar did not change The extent of the string deleted, if the deleted string was the longest and the visibility of the scroll bar may have changed. -1 for an error. Additional query words: listbox LB_SETH LB_GETH
Keywords : kbfile kbsample kb16bitonly kbCtrl kbListBox kbGrpUser kbWinOS310 kbWinOS300 |
Last Reviewed: December 10, 1999 © 2000 Microsoft Corporation. All rights reserved. Terms of Use. |