Introduction to PM Programming - Dec 1994

Written by Larry Salomon Jr.

Introduction
The purpose of this column is to provide the readers out there who are not familiar with PM application development the information necessary to satisfy their curiosity, educate themselves, and give them an advantage over the documentation supplied by IBM. Of course, much of this stuff could probably be found in one of the many books out there, but the problem with books in general is that they don't answer the questions you have after you read the book the first time through.

I will gladly entertain feedback from the readers about what was "glossed over" or what was detailed well, what tangential topics need to be covered and what superfluous crap should have been removed. This feedback is essential in guaranteeing that you get what you pay for.

It should be said that you must not depend solely on this column to teach you how to develop PM applications; instead, this should be viewed as a supplement to your other information storehouses (books, the network conferences, etc.). Because this column must take a general approach, there will be some topics that you would like to see discussed that really do not belong here. Specific questions can be directed to the Scratch Patch, where an attempt to answer them will be made.

Last month, we looked at the ownerdraw concept and how it specifically applies to the WC_BUTTON class. This month, we will begin looking at a new window class, the listbox (WC_LISTBOX).
 * Last Month

Purpose and Variations on a Theme
The purpose of the listbox is to store a list of items; no surprise there. Unfortunately, the original design (which had to be adhered to, for backward compatibility) only allowed for textual items to be stored. It is possible through "black magic" (read as ownerdraw) to display other items, however, but there is a lot more work involved, as we will see in the near future.

The styles of the listbox are described below:
 * LS_EXTENDEDSEL
 * Selection of items follows the CUA '91 specification.


 * LS_HORZSCROLL
 * A horizontal scrollbar should be provided, which is managed by the listbox.


 * LS_MULTIPLESEL
 * One or more items may be selected at any time. See below for more information.


 * LS_NOADJUSTPOS
 * The listbox should not adjust its height to be a integral multiple of the item height.


 * LS_OWNERDRAW
 * The listbox should allow the application to draw each item.

The difference between LS_MULTIPLESEL and LS_EXTENDEDSEL is that the former is brain-dead and utterly useless, while the latter is only somewhat useless. Seriously, try changing the sample in this issue to use the former and use it some. You will agree that it is quite cumbersome and that the latter is much easier from a usability point-of-view. The reasoning for the "(somewhat) useless" labelling will be seen later; I alluded to something similar last month with the WC_BUTTON class.

So far we have...
 * More Bad Design
 * 1) Text only allowed
 * 2) (Somewhat) useless selection strategies

What else is there?

IBM and Microsoft originally designed the listbox to hold modest amounts of data, but its ease-of-use quickly encouraged programmers to "push it to the limit." They quickly found out that the listbox will hold only so much. How much exactly depends on the length of each item, but it is generally accepted that you cannot - without some hokey-pokey - get more than 32K of items in a listbox, and that is only if every item is 1 character in length. The answer to why this is true deals with memory allocation within the original 16-bit PM subsystem and is beyond the scope of this article (as well as the hokey-pokey needed to circumvent it).


 * Don't Get Me Wrong:In spite of all of these shortcomings, there is no doubt that the listbox gives you the most "bang for the buck." It is very easy to use for most purposes and it is used quite frequently, so this ease-of-use saves you lots of heartache.
 * Final Notes:Each item within a listbox can have associated with it a ULONG. Typically, this is cast to a pointer to an application-specific structure for application housekeeping. These are referred to as item handles.

It is also important to note that all indices are 0-based.

The Days of Yesteryear
Let's go back to the HELLO.C program that was presented in [volume 2, issue 3].

If you'll remember, whenever a name was selected from the listbox, it appeared in the entryfield beneath it. We will finish the dangling ends of this application in the next issue or two, so keep this handy.


 * But First:First, let's list the listbox messages that can be sent to the control.


 * LM_DELETEALL:Deletes all of the items within the listbox.
 * LM_DELETEITEM:Deletes a single item within the listbox.
 * LM_INSERTITEM:Inserts a signle item within the listbox.
 * LM_QUERYITEMCOUNT:Returns the number of items within the listbox.
 * LM_QUERYITEMHANDLE:Returns a ULONG associated with an item within the listbox.
 * LM_QUERYITEMTEXT:Returns the text of an item within the listbox.
 * LM_QUERYITEMTEXTLENGTH:Returns the length of the text of an item within the listbox.
 * LM_QUERYSELECTION:Returns the index of the first item selected within the listbox after the one specified.
 * LM_QUERYTOPINDEX:Returns the index of the item shown at the top of the listbox.
 * LM_SEARCHSTRING:Searches for a string in the item text.
 * LM_SELECTITEM:Sets the selection state of an item within the listbox.
 * LM_SETITEMHANDLE:Associates a ULONG with an item within the listbox.
 * LM_SETITEMHEIGHT:Never implemented by IBM, but never removed from the Toolkit header files.
 * LM_SETITEMTEXT:Sets the text of an item within the listbox.
 * LM_SETTOPINDEX:Specifies the item to be displayed at the top of the listbox.


 * A Closer Look, Please:Let's now take a closer look at the more frequently used messages.

The insertion point can also be one of the following values:
 * Notes
 * LIT_END  Insert the item at the end of the listbox.
 * LIT_SORTASCENDING  Insert the item in ascending sorted order.
 * LIT_SORTDESCENDING  Insert the item in descending sorted order.
 * LM_DELETEITEM

Cleanliness
If you modify HELLO.C to insert "Tom" 100 times, you'll see that the initialization phase of the listbox looks quite ugly. It would be nice if the listbox would "pop-up" with everything already in it. The way to do this is to disable the update of the listbox before we begin and re-enable it after we finish the initialization. This brings us to our next API. (BOOL)WinEnableWindowUpdate(hwndWnd,bEnable); hwndWnd is the window to enable or disable. bEnable is the new enable state of the window. The function returns a success indicator.

Summary
This month, we looked at our next conquest - the listbox. We saw the various styles it has and the design limitations that accompany it. We also began looking at the listbox messages, and it is with this that we will continue next month.