Feedback Search Top Backward Forward

Introduction to PM Programming

Written by Larry Salomon, Jr.



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

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 me via email and I will do my best to answer them in a timely fashion.

Last Month

Last month, we began looking at the WC_LISTBOX class. This month, we will take a good look at the ownerdraw capabilities of this control class.

A Message For You, Sir

Each month before I write the next installment of this column, I re-read what I wrote the prior month to discover what I have covered in order to determine in what direction I should continue. As I read last month's column, it became apparent that the message reference which I capitulated each month is nothing more than a rehash of what's available in many sources, including the on-line programming references and many books. I would like to discontinue my inclusion of this information, given this enlightening of mine, unless the teeming masses tell me that I should do otherwise. Any feedback on this would be appreciated.

This Isn't Picasso

But ownerdraw listboxes give you quite an opportunity to do some interesting things. For the original LaMail product from IBM, I wrote a LaGrep utility which searched mail folders for text. The found text was displayed in a listbox in a different color than the rest. Additionally, the configuration options allowed to you change the color that the text was displaying using, and the color selection was displayed in a listbox with the name of the color next to it. Both of these are perfectly valid, real-world examples of ownerdraw listboxes, and while there might be other window classes better suited for these tasks, knowing how the ownerdraw capabilities work is a useful asset to have tucked in your cap.

The ownerdraw architecture with regard to listboxes is represented by two messages, which - incidentally - are used in ownerdraw menuitems in a very similar fashion. These messages are the WM_MEASUREITEM and WM_DRAWITEM and their purpose is just as their names suggest. The former message is sent, usually upon the creation of the listbox, to determine the maximum height and (if LS_HORZSCROLL) maximum width of the items to be displayed. The result is returned to the listbox as MRFROM2SHORT(height,width). The latter message is where all of the work is done and is sent whenever an item needs to be redrawn. PVOIDFROMMP(mpParm2) points to an OWNERITEM structure, but you won't find its definition in the listbox section of PMWIN.H. You have to look in the menu section to find it, which is the following:

typedef struct _OWNERITEM {
   HWND hwnd;
   HPS hps;
   ULONG fsState;
   ULONG fsAttribute;
   ULONG fsStateOld;
   ULONG fsAttributeOld;
   RECTL rclItem;
   LONG idItem;
   ULONG hItem;
hwnd is the handle of the control. hps is the handle to the presentation space which must be used for drawing. fsState and fsStateOld are, when the structure refers to an ownerdraw listbox, BOOLs which are TRUE if the item is selected and FALSE otherwise (fsStateOld is the selection state of the item the last time it was drawn). fsAttribute and fsAttributeOld are not used when dealing with ownerdraw listboxes. rclItem is the bounding rectangle of the item to be drawn. idItem is the index of the item to be drawn. hItem is the item handle, if set.

It needs to be noted that, if the listbox is ownerdraw, PM will not do anything on your behalf except paint the highlight state of the item to be drawn. It does this using an XOR operation only if fsState and fsStateOld are different. There is no way to change this unless you know that the OWNERITEM structure is what the listbox checks upon return from this message when it determines if it needs to highlight the item or not. So, if you set fsState and fsStateOld to the same value before returning, PM will not do anything at all.

The nice thing about the first sentence in the last paragraph is that PM doesn't even look at the item text for you. Thus, you could interpret the text in a different way that would normally be done - for LaGrep, I changed the color by putting a tab character in the text followed by a BYTE which was an index into an array of CLR_* constants. When I painted the control, I did not draw this special sequence but used it to control the drawing.

The possibilities are endless and are only limited by your imagination.

API of the Month Club

Our API of the month is the one that the listbox uses to XOR the highlight of an item.

(BOOL)WinInvertRect(HPS hpsWnd,PRECTL prclRect);

hpsWnd is the handle to the HPS to invert within. prclRect points to the rectangle specifying the area to be inverted. Inversion here refers to the inversion of the colors within the rectangle. Thus, black becomes white, white becomes black, etc.

Next Month

I need to get upon my soapbox for a moment.

As I looked through the past issues to see where this column has gone already, in order to determine what shall be discussed next, I saw that, much to my embarrassment, the listbox window class has already been discussed. Yet, this is the third month in my second treatment of the topic and I never would have known because the silence from my audience is deafening. The embarrassment is not what I am worried about; I am instead concerned about providing a quality column, yet no one bothered to tell me that I was simply rehashing a topic that was discussed just a few months prior.

Please give me feedback! How else can I say it? I need to know what you think, where we should go next, etc. Since I have always considered the button, entryfield, and listbox classes to be the "simple" classes, it is more important now because I need to know what class should be discussed next. Should it be the menu, or the static? Should it be the scrollbar, or the titlebar? Please let me know; this humble request alone I make.