Introduction to PM Programming - Dec 1994

From EDM2
Jump to: navigation, search

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 curiousity, 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

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).

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.

More Bad Design

So far we have...

  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 <a HREF="../0203/intropm.html">volume 2, issue 3.</a>

Figure 1) HELLO in action

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.

Message and Purpose Parameters Returns
LM_DELETEALL
Deletes all of the items within the listbox
This message accepts no parameters SHORT1FROMMR()
TRUE-----Success
FALSE----Failure
LM_DELETEITEM
Deletes a single item within the listbox.
SHORT1FROMMP(mpParm1)
Index of the item to delete.
SHORT1FROMMR()
Number of items remaining.
LM_INSERTITEM
Inserts a single item within the listbox.
Notes
SHORT1FROMMP(mpParm1)
Index at which to insert the item.
PVOIDFROMMP(mpParm2)
Pointer to the item text.
No returns
LM_QUERYITEMCOUNT
Returns the number of items within the listbox.
This message accepts no parameters. SHORT1FROMMR()
Number of items
Notes

The insertion point can also be one of the following values:

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.