═══ 1. Introduction ═══ This document is the programmer's reference for the MultiColumn ListBox (MCLB) PM control. For more information on programming with this control, see OS/2 Developer Magazine, Nov/Dec 1995. Acknowledgments This control was originally conceived at the IBM United Kingdom Warwick Development group by Charles Cooper. The control was rewritten and enhanced by Mark McMillan of IBM, Research Triangle Park, USA. Description The MultiColumn ListBox is a very useful PM custom control designed to overcome some of the limitations of the standard PM listbox and container controls. It is simpler and in many cases faster than a container, but provides multicolumn (tabular) support for display of column-oriented data. The MCLB supports individually sizable columns, optional horizontal scroll bars at the base of each column, seperate font and color support for the titles and column data, owner-drawn lists, and a simple listbox-style programming model. The MCLB can be subclassed with the DMLB (Direct Manipulation ListBox) function also supplied in this toolkit to provide drag/drop reordering capability to the MCLB. ═══ 2. Creating an MCLB ═══ To create an MCLB the application must create an MCLBINFO data structure and initialize it. At a minimum, the following fields must be supplied: o Size o Cols o Titles o InitSizes o TabChar The application must then call MCLBCreateWindow to create the MCLB control. As supplied in the toolkit, the MCLB does not support direct creation from a dialog template. However, it is very easy to get the same effect by defining a static rectangle (or any other control) in the dialog template to act as a placeholder. During WM_INITDLG processing the application can create the MCLB and size/position it exactly on top of the placeholder control. See the SAMP1 sample for code that does this. ═══ 3. Styles ═══ The visual appearance of an MCLB can be modified through the use of 'style' flags which are passed to the MCLBCreateWindow API when the control is created. The style flags cannot be changed after the MCLB is created. In addition to the flags described below, any standard PM WS_* window style flags can be used (e.g. WS_VISIBLE). The standard PM listbox styles are shown here, along with the extended styles unqiue to MCLB controls: o LS_MULTIPLESEL Allow multiple items to be selected in the list (same as normal PM listbox control). o LS_EXTENDEDSEL Allows extended selection methods to be used in the list (same as normal PM listbox control). o LS_HORZSCROLL When this style is specified each column of the MCLB will have a horizontal scroll bar at the bottom. Note that for LS_OWNERDRAW style, the application must properly process WM_MEASUREITEM messages in order for the scroll bar to work correctly. This is true even if the application returns FALSE from WM_DRAWITEM and lets PM draw the text of an ownerdraw listbox. o LS_OWNERDRAW The listbox items are to be drawn by the application. When this style is used the application must respond to the WM_MEASUREITEM and WM_DRAWITEM messages. This style applies to all columns of the MCLB (e.g. the application will be responsible for drawing all items in all columns). o LS_NOADJUSTPOS When this style is specified the control is sized exactly as specified and the last row may be partially visible. When this style is not specified, the columns will be vertically sized such that the last row is not clipped. The overall MCLB control size is never altered (the size of the title area will be adjusted to prevent clipping if this style is not specified). o MCLBS_CUASELECT When this style is specified the LS_MULTIPLESEL and LS_EXTENDEDSEL styles will also be used. This style causes the MCLB to deselect all items except one when the left button is pressed. This behaviour is consistent with the container control. Without this style, a left button press on an already selected item will have no effect. o MCLBS_NOCOLRESIZE When this style is specified the user is not allowed to change the relative column sizes. The MCLB will be displayed without splitbars between the columns (just thin vertical lines will be drawn between the columns). This style applies to all columns of the MCLB. It is not possible to have some sizable and some fixed-width columns in the same MCLB control. The default is for the columns to be sizable and movable splitbars to be displayed between each column. o MCLBS_SIZEMETHOD_PROP This is the default SIZEMETHOD style if none is specified. The SIZEMETHOD styles determine how the column sizes are adjusted if the MCLB control is resized by the application. Note that this is not related to user-initiated column sizing, but only to what happens when the entire MCLB size is changed. This method will cause each column size to be adjusted in proportion to its previous size. For example, if a column was 20% of the width of the MCLB before resizing, it will be adjusted to be 20% of the width after resizing. Thus each column remains the same relative size when the size of the control is changed. o MCLBS_SIZEMETHOD_LEFT With this SIZEMETHOD style, any change in the size of the MCLB control is reflected in the leftmost MCLB columns. If the MCLB size is increased, the leftmost column will increase by the same amount. If the size is decreased, column size reduction starts in the leftmost column and continues left-to-right reducing each column to zero width until the new overall control width is achieved. o MCLBS_SIZEMETHOD_CUSTOM With this SIZEMETHOD style, any change in the size of the MCLB control must be handled by the application. When the size of the MCLB is changed the application will be sent a WM_CONTROL message with a notification code of MCLBN_CUSTOMSIZE . Message parameter 2 will be a pointer to array of n+1 LONG values where "n" is the number of columns. The [0] element will contain the new overall width (accounting for margins, dividers, etc). The [1]-[n] elements contain the current column widths in pixels. The application must set the new column widths in the [1]-[n] array elements. The sum of the [1]-[n] values should equal the overall width given in element [0]. This style can be used to implement specific column sizing rules as may be required for particular applications. For example, it might be used to prevent a particular column of being reduced below a certain minimum size. There are some important notes to consider in using this style: 1. This style effects only the adjustment of column sizes that occures when the MCLB control size is changed. It does not effect user-controlled column sizing. 2. If the sum of the [1]-[n] elements is not equal to the value of the [0] element, the last column will be used to make up the difference. 3. The application can choose to use the default sizing method by returning FALSE from the MCLBN_CUSTOMSIZE control message. ═══ 4. MCLBINFO Data Structure ═══ The MCLBINFO structure describes the characteristics of an MCLB control. This structure is created and filled in by an application prior to calling the MCLBCreateWindow API. It is also returned to the application with the current values when the application sends a MCLB_QUERYINFO message. typedef struct _MCLBINFO { ULONG Size; /* Length of this structure */ char *Titles; /* Title strings (TabChar separated) */ char TitleFont[MAX_FONTLEN]; /* Title font (null to inherit from owner) */ char ListFont[MAX_FONTLEN]; /* List font (null to inherit from owner) */ ULONG TitleBColor; /* Title background color (RGB) */ ULONG TitleFColor; /* Title foreground color (RGB) */ ULONG ListBColor; /* List background color (RGB) */ ULONG ListFColor; /* List foreground color (RGB) */ LONG *InitSizes; /* Ptr to array of initial sizes */ char _Reserved[64]; /* Reserved for future use */ USHORT Cols; /* Number of columns */ char TabChar; /* Data column separator character */ char _Padd; /* Padd for separator character (zero) */ } MCLBINFO; ═══ 5. WM_CONTROL Message Reference ═══ This section describes all the WM_CONTROL messages generated by a MCLB control and sent to the control owner. Note that most of the standard LN_* messages are the same as for standard PM listbox controls. Only LN_* messages that differ from the PM definitions are shown here. For some WM_CONTROL messages it may be necessary for the application to know which column of the MCLB generated the message. The application may send the MCLB_QUERYCTLCOL message to get the number of the column which caused the current WM_CONTROL message. Note that MCLB_QUERYCTLCOL must only be sent during the processing of a WM_CONTROL message. ═══ 5.1. LN_* ═══ The following WM_CONTROL listbox notification messages retain their normal PM meanings. Note that the control ID in SHORT 1 of mp1, and the window handle in mp2 are those of the MCLB control itself. LN_ENTER LN_KILLFOCUS LN_SETFOCUS LN_SCROLL LN_SELECT ═══ 5.2. MCLBN_COLSIZED ═══ This WM_CONTROL notification is sent by the MCLB to its owner when the user has moved a column divider. Param1 MCLBID (USHORT) ID of the MCLB control NotifyCode (USHORT) MCLBN_COLSIZED Param2 ColNum (USHORT) Number of the column to the left of the moved divider. Note that this column and the ColNum+1 column have both changed size. Returns Nothing Remarks This message occures only when the user moves a column divider in the MCLB. It does not occure when the size of the MCLB control is changed. The MCLB_QUERYCOLSIZES message can be used to find the new column sizes. Related MCLBS_NOCOLRESIZE style MCLB_QUERYCOLSIZES message ═══ 5.3. MCLBN_CUSTOMSIZE ═══ This WM_CONTROL notification is sent by the MCLB to its owner when the control window size has been changed and the control has the MCLBS_SIZEMETHOD_CUSTOM style. Param1 MCLBID (USHORT) ID of the MCLB control NotifyCode (USHORT) MCLBN_CUSTOMSIZE Param2 Sizes (LONG *) Pointer to array of LONG values. The array has N+1 elements where N is the number of columns. The [0] element contains the new width the columns must fit into. The [1] to [N] elements contain the current column sizes in pixels. Returns Processed (BOOL) Return TRUE if the application has updated the [1] to [N] elements of the array with the new column widths. Return FALSE for the MCLB control to proportionally resize the columns. Remarks This message occures only if the MCLBS_SIZEMETHOD_CUSTOM style is used. The application can choose to process this message and return TRUE, or return FALSE and let the MCLB control perform default proportional column sizing. If the application returns TRUE, the [1] to [N] elements of the array must be updated with the new adjusted column sizes. The sum of the [1] to [N] elements should be equal to the supplied [0] element value. E.g. the new column sizes must add up to the new width allocated for the columns. Related MCLBS_SIZEMETHOD_CUSTOM style ═══ 5.4. MCLBN_PPCHANGED ═══ This WM_CONTROL notification is sent by the MCLB to its owner when any presentation parameter is altered. Param1 MCLBID (USHORT) ID of the MCLB control NotifyCode (USHORT) MCLBN_PPCHANGED Param2 ColNum (USHORT) Number of the column that originated the presentation parameter changes or zero if the title area was changed. Note that all columns will have the same presentation parameters (e.g. all columns will use the same font and colors). PPType (USHORT) Indicates the type of presentation parameter that was changed: MCLBPP_FONT Font changed MCLBPP_FORECOLOR Foreground color changed MCLBPP_BACKCOLOR Background color changed Returns Nothing Remarks The MCLB_QUERYINFO message can be used to determine the current fonts and colors of the MCLB. Related MCLB_QUERYINFO ═══ 6. Owner-Draw Messages ═══ This section describes messages the owner of an MCLB will receive if the LS_OWNERDRAW style is used. ═══ 6.1. WM_MEASUREITEM ═══ This message is sent to the owner of an owner-draw style MCLB to determine the size of a listbox item. This message will occure for each item of each column of the listbox. The measurements returned must be for just one column, not the aggregate size of all columns. This standard PM message is extended for an MCLB to include the column number in SHORT 2 of mp1 (unused by PM). Param1 MCLBId (SHORT) ID of the MCLB control. Col (USHORT) Column number of the item to be measured. Param2 ItemIndex (SHORT) Index of the item to be measured. Returns Height (SHORT) Height of the item. Width (SHORT) Width of the item. Remarks The application should be prepared to receive this message when the MCLB control is created (e.g. during MCLBCreateWindow processing). Note that the vertical height of all items in all columns must be the same, and this value must be equal to or greater than the vertical font size for the listbox items. The width must be the actual width of the item in the column. If the column contains text the width returned should be the actual drawn text width. Related ═══ 6.2. WM_DRAWITEM ═══ This message is sent to the owner of an owner-draw style MCLB when any item in any column needs to be redrawn. Note that this draw message applies to just a single item in a single column, not to an entire row. This standard PM message is extended for an MCLB to include the column number in SHORT 2 of mp1 (unused by PM). Param1 MCLBId (SHORT) ID of the MCLB control. Col (USHORT) Column number of the item to be drawn. Param2 DrawInfo (OWNERITEM *) Pointer to an OWNERITEM data structure. Returns Drawn (BOOL) Return TRUE if the application has drawn the item. Return FALSE for the listbox to draw the item text. Remarks Related ═══ 7. MCLB Messages ═══ This section describes all the messages an application can send to a MCLB control. Unless noted otherwise here, all the PM listbox LM_* messages work as documented for a listbox control. Also unless stated otherwise, item text consists of all the column data separated with the column separator character. ═══ 7.1. LM_INSERTITEM ═══ This standard listbox message is extended to include the column number by which the inserted item is to be sorted. SHORT 2 of mp1 is unused by PM, but is defined for an MCLB as the column number by which sorting is to be done. If it is zero or greater than the number of columns, LIT_ERORR will be returned. It is recomended that if many items are to be inserted in the MBLB, that WinEnableWindowUpdate() be used to improve performance. Window updating should be disabled before the first insert and enabled after the last insert. Param1 InsertIndex (SHORT) Position in the list at which to insert, or LIT_END, LIT_SORTASCENDING, or LIT_SORTDECENDING. SortCol (USHORT) If InsertIndex is LIT_SORTASCENDING or LIT_SORTDECENDING then the specified column number is used to determine the sorting sequence. Param2 Text (char *) Pointer to string to be inserted. Column data is separated in the string by the column separator charcter defined in MCLBINFO when the MCLB was created. Returns InsertedAt (SHORT) Index of newly inserted item or LIT_MEMERROR, or LIT_ERROR. Remarks Related ═══ 7.2. LM_INSERTMULTITEMS ═══ (Note: This is a new message in OS/2 Warp.) This standard listbox message is extended to include the column number by which the inserted items are to be sorted. The reserved2 field of the LBOXINFO structure is used to define the column number by which sorting is to be done. If it is zero or greater than the number of columns, LIT_ERORR will be returned. Note that due to the implementation of the MCLB, there is little performance difference between using this message to insert items and repeated use of LM_INSERTITEM. Param1 Info (LBOXINFO *) Pointer to LBOXINFO structure (new in Warp 3.0 toolkit). Param2 Strings (char **) Pointer to array of string pointers. Each string represents one row of the MCLB using the column separator character to separate the data into columns. Returns InsertedAt (SHORT) Index of newly inserted item or LIT_MEMERROR, or LIT_ERROR. Remarks Related ═══ 7.3. LM_SEARCHSTRING ═══ This message is not fully implemented for an MCLB control. The search is performed only on the first column. ═══ 7.4. MCLB_SETTITLES ═══ This message is sent to the MCLB to set the title strings (column headers). Param1 Titles (* char) Pointer to a character string which contains the new column titles. The titles must be separated by the MCLB column separator character as defined in the MCLBINFO structure when the MCLB was created. Param2 Reserved Returns Nothing Remarks Related ═══ 7.5. MCLB_SETTITLEFONT ═══ This message is sent to the MCLB to set the font to be used for the titles. Param1 FontNameSize (* char) Pointer to a character string which contains the new font to be used. The format of the string is the same as that used in the WinSetPresParam() call such as "8.Helv". This parameter may be NULL in which case the title font is reset to the default font. Param2 Reserved Returns Nothing Remarks Related ═══ 7.6. MCLB_SETLISTFONT ═══ This message is sent to the MCLB to set the font to be used for the list items. Param1 FontNameSize (* char) Pointer to a character string which contains the new font to be used. The format of the string is the same as that used in the WinSetPresParam() call such as "8.Helv". This parameter may be NULL in which case the list font is reset to the default font. Param2 Reserved Returns Nothing Remarks Related ═══ 7.7. MCLB_SETTITLECOLORS ═══ This message is sent to the MCLB to set the colors to be used for the titles. Param1 Foreground (LONG) Contains the RGB value of the foreground color. Param2 Background (LONG) Contains the RGB value of the background color. Returns Nothing Remarks If the foreground and background colors specified are the same, the title colors are reset to the default colors. Related ═══ 7.8. MCLB_SETLISTCOLORS ═══ This message is sent to the MCLB to set the colors to be used for the list items. Param1 Foreground (LONG) Contains the RGB value of the foreground color. Param2 Background (LONG) Contains the RGB value of the background color. Returns Nothing Remarks If the foreground and background colors specified are the same, the list colors are reset to the default colors. Related ═══ 7.9. MCLB_SETCOLSIZES ═══ This message is sent to the MCLB to set the columns to specific sizes. Param1 NewSizes (LONG *) Pointer to array of LONG values. Array must contain at least N elements, where N is the number of columns in the MCLB. Param2 Reserved Returns Nothing Remarks The value of the [0] to [N-1] elements of the array must add up to the current width of all the columns. The current sum of the column widths can be deterined with the MCLB_QUERYFULLSIZE message. Related ═══ 7.10. MCLB_QUERYCOLSIZES ═══ This message is sent to the MCLB to query the current size of the columns. Param1 Sizes (LONG *) Pointer to array of LONG values. Array must contain at least N elements, where N is the number of columns in the MCLB. Param2 Reserved Returns Nothing Remarks The value of the [0] to [N-1] elements of the array will be set to the current column widths in pixels. Related ═══ 7.11. MCLB_QUERYINFO ═══ This message is sent to the MCLB to query the current MCLB configuration. Param1 Info (* MCLBINFO) Pointer to MCLBINFO structure. Upon return the structured will be filled with the current values. Param2 Reserved Returns Nothing Remarks The value of the InitSizes array will be set to the current column sizes. NOTE: The application must free the InitSizes array and the Titles string. Related ═══ 7.12. MCLB_QUERYSTYLE ═══ This message is sent to the MCLB to query the MCLB styles flags. Param1 Reserved Param2 Reserved Returns Styles (ULONG) Only the MCLB-specific style bits (MCLBS_* flags) will be returned. Remarks Related ═══ 7.13. MCLB_QUERYFULLSIZE ═══ This message is sent to the MCLB to query the sum of the column widths Param1 Reserved Param2 Reserved Returns Width (LONG) The sum of the current column widths. Remarks Note that this value is not the same as the width of the control window. This value is the width of the control minus the width of all dividers, vertical scroll bars, borders, etc. It is the number of pixels actually allocated for the columns of data. Related ═══ 7.14. MCLB_QUERYCTLCOL ═══ This message is sent to the MCLB to query column which caused the current WM_CONTROL message. Param1 Reserved Param2 Reserved Returns Col (USHORT) The number of the column which caused the current WM_CONTROL message. Remarks This message must be sent to the MCLB, not posted. The results of this message are only defined during WM_CONTROL message processing. It can be useful at times to know which column of an MCLB has caused a particular WM_CONTROL message to be sent to the owner. The owner can discover this by sending the MCLB this message. This message must be sent while the owner is processing the WM_CONTROL message of interest. Related ═══ 8. Programming Interfaces (API) ═══ This section describes each of the callable MCLB programming interfaces. ═══ 8.1. MCLBCreateWindow ═══ This function creates an MCLB and returns its window handle. Syntax: MCLBHwnd MCLBCreateWindow(Parent, Owner, Style, x, y, cx, cy, Behind, Id, MCLBInfo) ┌───────────────┬──────────┬──────────┬──────────────────────────────────────────────────┐ │Name │Type │In/Out │Description │ ├───────────────┼──────────┼──────────┼──────────────────────────────────────────────────┤ │Parent │HWND │input │Handle of the parent window. │ ├───────────────┼──────────┼──────────┼──────────────────────────────────────────────────┤ │Owner │HWND │input │Handle of the owner window. This window will │ │ │ │ │recieve WM_CONTROL messages from the MCLB. │ ├───────────────┼──────────┼──────────┼──────────────────────────────────────────────────┤ │Style │ULONG │input │Style flags. This is a logical-OR combination of │ │ │ │ │WS_* window styles, LS_* listbox styles, and │ │ │ │ │MCLBS_* MCLB styles. │ ├───────────────┼──────────┼──────────┼──────────────────────────────────────────────────┤ │x │LONG │input │X position of the window relative to the Parent │ │ │ │ │window. │ ├───────────────┼──────────┼──────────┼──────────────────────────────────────────────────┤ │y │LONG │input │Y position of the window relative to the Parent │ │ │ │ │window. │ ├───────────────┼──────────┼──────────┼──────────────────────────────────────────────────┤ │cx │LONG │input │Width of the window. │ ├───────────────┼──────────┼──────────┼──────────────────────────────────────────────────┤ │cy │LONG │input │Height of the window. │ ├───────────────┼──────────┼──────────┼──────────────────────────────────────────────────┤ │Behind │HWND │input │Sibling window behind which this window is to be │ │ │ │ │placed. HWND_TOP or HWND_BOTTOM can be used to │ │ │ │ │place this window on top of, or behind all other │ │ │ │ │sibling windows. │ ├───────────────┼──────────┼──────────┼──────────────────────────────────────────────────┤ │Id │USHORT │input │Id of this window. This Id is encoded in all │ │ │ │ │WM_CONTROL messages from this MCLB. │ ├───────────────┼──────────┼──────────┼──────────────────────────────────────────────────┤ │Info │MCLBINFO *│input │Pointer to completed MCLBINFO data structure. │ └───────────────┴──────────┴──────────┴──────────────────────────────────────────────────┘ Returns ┌───────────────┬──────────┬──────────┬──────────────────────────────────────────────────┐ │MCLBHwnd │HWND │return │Handle of the MCLB window, or NULLHANDLE if │ │ │ │ │creation failed. │ └───────────────┴──────────┴──────────┴──────────────────────────────────────────────────┘ Remarks Related MCLBINFO