Introduction to PM Programming - Sep 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 began looking at the WC_LISTBOX window class, how it is used, what its limitations are, and some of the messages associated with it. We resume this track this month, and take another look at nameDlgProc() in HELLO.C (see intro.zip).

nameDlgProc() and Listboxes

If you'll look at HELLO.C, you will see comments to the right of the source code of the form "@n", where n is a number. These are landmarks that are referenced, so if you don't have the source handy, please make it available. Our first one is...

Macros

landmark number 7.

WinInsertLboxItem(hwndLb,LIT_END,achText);                  // @7

This line, while it looks like a function call, is a macro defined in the Programmer's Toolkit. This macro expands to:

#define WinInsertLboxItem(hwndLbox, index, psz) \
((LONG)WinSendMsg(hwndLbox, LM_INSERTITEM, MPFROMLONG(index), \
MPFROMP(psz)))

There are two points to this:

  1. there are handy macros which can shorten your coding time if you know what they are, and
  2. this function call is really nothing more than the sending of an LM_INSERTITEM message, which we looked at briefly last month.

Now, find numbers...

Notifications

8 and 9. This is a notification sent to the owner of the listbox - the dialog - via the WM_CONTROL message.

case WM_CONTROL:                                                  // @8
   switch (SHORT1FROMMP(mpParm1)) {
   case DNAME_LB_NAMELIST:
      switch (SHORT2FROMMP(mpParm1)) {
      case LN_SELECT:                                             // @9
         {
            HWND hwndLb;
            SHORT sIndex;

            hwndLb=WinWindowFromID(hwndWnd,DNAME_LB_NAMELIST);

            sIndex=WinQueryLboxSelectedItem(hwndLb);
            WinQueryLboxItemText(hwndLb,
                                 sIndex,
                                 pndiInfo->achName,
                                 sizeof(pndiInfo->achName));

            WinSetDlgItemText(hwndWnd,
                              DNAME_EF_NAME,
                              pndiInfo->achName);
         }
         break;

The notification LN_SELECT is sent to let you know that an item was selected by the user. This could be using the mouse or the keyboard (using the up and down arrows, if single-select, or the spacebar, if multi-select). It needs to be pointed out that the item that was selected is not passed as a parameter of the message, and no matter how many complaints were filed when this was noticed, IBM would not change it.

"Big deal", you think. For single-select listboxes, this is not a problem, but for multi-select it is a huge problem. Consider why: you determine the selected item using the message LM_QUERYSELECTION which returns the first selected item after the index specified, or the macro WinQueryLboxItemText() which always searches from the beginning. However, what happens if the user selects one item, and then an item following the first selection? There is a solution to this problem, fortunately, but it will not be discussed until we look at ownerdraw listboxes.

The next notification is at landmark 10.

case LN_ENTER:                                        // @10
   WinPostMsg(hwndWnd,WM_COMMAND,MPFROMSHORT(DID_OK),0);
   break;

This notification comes whenever the user double-clicks on an item in the listbox or presses the ENTER key while the listbox has the input focus. As with the LN_SELECT notification, this has its shortcomings. The first is the same as the last notification - finding out which item was selected in a multi-select listbox. The second occurs whenever you have a default pushbutton and the user presses the ENTER key (vs. double-clicking, which doesn't have this problem). A default pushbutton is one the acts as though it was selected if the user presses ENTER and the window with the input focus is not a pushbutton. In this scenario, you receive both the LN_ENTER notification and the WM_COMMAND message (which is sent by the pushbutton). Unfortunately, there is no good solution to this problem other than to avoid placing yourself in this situation.


We are slowly, but surely, making progress in dissecting HELLO.C. We will return for the last time when we have looked at buttons, but I suspect that by now you have already figured out the rest of the program.

More Messages

Let's look at more of the common messages used by the listbox. Unlike the entryfield, we will not examine all of the listbox messages, nor all of the messages of any future controls we will look at. This is because, with few exceptions, each control has so many messages that it would quickly become a hinderance to this column's effectiveness.

LM_DELETEITEM
This message is sent to delete an item from the listbox.
Parameters
	param1
		lIndex (LONG)
			0-based index of the item to be deleted.

	param2
		ulReserved (ULONG)
			Reserved, 0.

Returns
	reply
		bSuccess (BOOL)
			TRUE   successful completion
			FALSE   error occurred
LM_DELETEALL
This message is sent to delete all items from the listbox.
Parameters
	param1
		ulReserved (ULONG)
			Reserved, 0.
	param2
		ulReserved (ULONG)
			Reserved, 0.

Returns
	reply
		bSuccess (BOOL)
			TRUE   successful completion
			FALSE   error occurred

Notes and Next Month

I do apologize for the snail's pace being taken in this column, but I do not want to overwhelm anyone by presenting too much information. I have received little feedback and even though it was positive, the ether is too silent for me to think that I am doing everything correctly. Please send me your comments about this column and any questions you might have about topics that I delicately skirt.

Next month, we will begin looking at the WC_BUTTON class, specifically the pushbutton, and also will look at the ownerdraw window from both a listbox and a pushbutton perspective.