Introduction to PM Programming - Jul 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 Questions and Answers, where an attempt to answer them will be made.

Last Month
Last month, we finished the WC_ENTRYFIELD window class. This month, we begin looking at the WC_LISTBOX window class, how it is used, what its limitations are, and some of the messages associated with it.

Listboxes
So what is a listbox anyway? A listbox is, as you probably well know, a collection of items. While originally intended for text only, ownerdraw listboxes allow you to place graphics, multicolored text, or whatever as long as you can code it. When the listbox was originally introduced in OS/2 1.1, it allowed for single and multiple selection only; the former deselected any currently selected item whenever a new one was selected by the user or the application, while the latter allowed for one or more items to be selected at any one time. When OS/2 2.0 was released, a third selection style - extended selection - was added which differed from multiple selection in that it was CUA in design (multiple selection was not).

To aid in the somewhat object-oriented design, listbox items can have associated with them handles, which are nothing more than a ULONG that is unique to a particular item. This ULONG is typically used to point to a data structure which contains information about the item, e.g. printer information associated with a name which is displayed. When the user selects the printer name, the application can get the rest of the information needed to open the printer device by checking the handle and following the pointer there.

Unfortunately, the designers of the listbox were constrained to the heaps that were provided by PM for their memory allocation and heaps were limited to 64K in size, so the listbox must contain all of its housekeeping data in 64K. The number of items that this maps to varies, based on the total length of the item text, but you typically cannot get more than 32K of items (and that much only if you are lucky) in a single listbox. To get around this limitation, you must use the container control or read the article series in the OS/2 Developer beginning with the January/February issue which develops a replacement class for the listbox.

Messages
Let's take a look at the more commonly used messages.

Parameters or LIT_SORTDESCENDING, the item is inserted in the appropriately sorted order. Returns Parameters Returns Parameters Returns Parameters Returns Parameters Returns
 * 1) LM_INSERTITEM - This message is sent to insert an item into a listbox.
 * 1) *param1 - usIndex (USHORT) the index where the item is to be inserted.
 * 2) **If LIT_END, the item is inserted at the end of the list.
 * 3) **If LIT_SORTASCENDING
 * 1) *param2 - pchText (PCHAR) pointer to the string to be inserted.
 * 1) *reply - lIndex (LONG)
 * 2) **LIT_ERROR  an error occurred.
 * 3) **index  0-based index of inserted item
 * 4) LM_QUERYSELECTION - This message is sent to query the index of the selected item.
 * 1) *param1 - ulReserved (ULONG)
 * 2) **Reserved, 0.
 * 3) *param2 - ulReserved (ULONG)
 * 4) **Reserved, 0.
 * 1) *reply - lIndex (LONG)
 * 2) **LIT_NONE  no item is selected
 * 3) **index  0-based index of inserted item
 * 4) LM_SETSELECTION - This message is sent to set the selected state of an item.
 * 1) *param1 - lIndex (LONG) 0-based index of the item whose selection state is to change
 * 2) *param2 - bSelect (BOOL)
 * 3) **TRUE  the item is to be selected
 * 4) **FALSE the item is to be unselected
 * 1) *reply - bSuccess (BOOL)
 * 2) **TRUE  successful completion
 * 3) **FALSE an error occurred
 * 4) LM_SETITEMHANDLE - This message is sent to set the handle for an item.
 * 1) *param1 - lIndex (LONG) 0-based index of the item whose handle is to be set.
 * 2) *param2 - ulHandle (ULONG) handle to be associated with this item.
 * 1) *reply - bSuccess (BOOL)
 * 2) **TRUE  successful completion
 * 3) **FALSE an error occurred
 * 4) LM_QUERYITEMHANDLE - This message is sent to return the handle associated with an item.
 * 1) *param1 - lIndex (LONG] 0-based index of the item whose handle is to be set.
 * 2) *param2 - ulReserved (ULONG)
 * 3) **Reserved, 0.
 * 1) *reply - ulHandle (ULONG)
 * 2) **LIT_ERROR  an error occurred
 * 3) **handle  handle of the specified item.

These should be fairly trivial to use, since the concepts behind them are not the difficult to understand. Next month, we'll continue with the remaining messages and will begin to look at the rest of nameDlgProc.