PMGuide - Container Controls
A container control (WC_CONTAINER window class) is a visual component that holds objects. It provides a powerful and flexible component for easily developing products that conform to the Common User Access (CUA) user interface guidelines. This chapter describes the container control component and how to use it in PM applications.
About Container Controls
A container can display objects in various formats and views. Generally speaking, each view displays different information about each object. If a container's data is too large for the window's work area, scrolling mechanisms are enabled. The CUA direct manipulation protocol is fully supported, thereby enabling a user to visually drag an object in a container window and drop it on another object or container window. Containers are an integral component of the CUA user interface.
Container Control Functionality
The container control provides multiple views of a container's contents, such as Icon, Name, Text, Tree, and Details views. The container control lets you change container views quickly and easily, display each view with a different font, or vertically split the Details view into two parts so that a user can widen one part to see more information.
Graphical user interface (GUI) support is part of the container control. GUI support allows:
- Direct manipulation
- Multiple selection types: single, extended, and multiple selections
- Multiple selection techniques: marquee, swipe, and first-letter selection
- Multiple selection mechanisms: mouse button 1, mouse button 2, and keyboard augmentation
- Multiple forms of emphasis: selected-state, unavailable-state, in-use, and target emphasis
- Scrolling when a container's work area is not large enough for all the container items to be visible
- Dynamic scrolling to provide visible feedback to show the movement of the container items relative to the position of the scroll box
The container control supports various data types, such as icons or bit maps for the Icon, Name, Tree, and Details views. In the Details view, this includes the ability to use icons or bit maps in column headings as well as in the columns themselves. The container control also supports text in the following situations:
- For container titles in all views
- Beneath icons or bit maps in the Icon view
- To the right of icons or bit maps in the Name and Tree views
- For any column or column heading in the Details view
- For container items in the Text view
- For container items in the Details view, text in date, time, and number format
The container control provides a variety of options for enhancing the performance of the container:
- Direct editing of container control text
- Blank text fields in all views
- Ownerdraw, which enables an application, rather than the container control, to draw the container items
- Automatic reposition mode which is used in the Icon view. The container control provides an automatic reposition mode that repositions the items as a result of inserting, removing, sorting, filtering items, or changing window or font size.
- Arrange message mode that arranges overlapping icons or bit maps so they no longer overlap
- Data caching to efficiently remove items from and insert items into a container as they scroll in and out of view
- Methods for sharing records among multiple containers
- Memory usage optimization
Container Items
Container items can be anything that your application or a user might store in a container. Examples are executable programs, word processing files, graphic images, and database records.
Container item data is stored in the RECORDCORE and MINIRECORDCORE data structures. Both the application and the container have access to the data stored in these records.
The application must allocate memory for each record by using the CM_ALLOCRECORD message.
The maximum number of records is limited only by the amount of memory in the user's computer. The container control does not limit the number of records that a container can have.
Container Views
When a user opens a container, the contents of that container are displayed in a window. A container window can present various views of its contents, and each view can provide different information about its container items. The following table describes the views the container control provides:
┌───────────────┬─────────────────────────────────────────────┐ │View Type │Contents Displayed │ ├───────────────┼─────────────────────────────────────────────┤ │Icon view │Displays either icons or bit maps, with text │ │ │beneath the icons or bit maps, to represent │ │ │container items. These are called icon/text │ │ │or bit-map/text pairs. Each icon/text or │ │ │bit-map/text pair represents one container │ │ │item. This is the default view. │ ├───────────────┼─────────────────────────────────────────────┤ │Name view │Displays either icons or bit maps, with text │ │ │to the right of the icons or bit maps, to │ │ │represent container items. These are called │ │ │icon/text or bit-map/text pairs. Each │ │ │icon/text or bit-map/text pair represents one│ │ │container item. │ ├───────────────┼─────────────────────────────────────────────┤ │Text view │Displays a simple text list to represent │ │ │container items. │ ├───────────────┼─────────────────────────────────────────────┤ │Tree view │Displays a hierarchical view of the container│ │ │items. Three types of Tree views are │ │ │available: Tree text, Tree icon, and Tree │ │ │name. │ ├───────────────┼─────────────────────────────────────────────┤ │Details view │Displays detailed information about each │ │ │container item. The same type of data is │ │ │displayed for each container item, arranged │ │ │in columns. The data in each column can │ │ │consist of an icon or bit map, text, numbers,│ │ │dates, or times. │ └───────────────┴─────────────────────────────────────────────┘
If a text string is not specified for a view in a place where a text string could be used, a blank space is used as a placeholder. For example, if a text string is not placed beneath an icon in the Icon view, a blank space is inserted just as though the text string were there. If this blank space is not a read-only field, the user can put text into the space by editing it directly.
Icon View
The Icon view (CV_ICON attribute) displays icon/text pairs or bit-map/text pairs to represent container items; this is the default view. CV_ICON is an attribute of the CNRINFO data structure's flWindowAttr field.
In the Icon view, icon/text pairs and bit-map/text pairs are icons and bit maps, respectively, with one or more lines of text displayed below each icon or bit map. Each line can contain one or more text characters, which are centered below the icon or bit map. The container control does not limit the number of lines or the number of characters in each line.
Generally, the icon or bit map contains an image that depicts the type of container item that it represents. For example, an icon or bit map that represents a bar chart might contain an image of a bar chart.
Because the container control does not support both icons and bit maps in the same view, an application must specify which are used by setting either the CA_DRAWICON attribute or the CA_DRAWBITMAP attribute in the flWindowAttr field of the CNRINFO data structure. The default is the CA_DRAWICON attribute. The size of the icon or bit map can be specified in the slBitmapOrIcon field of the CNRINFO data structure.
In the Icon view, container items are positioned according to x- and y-coordinate positions. These are called workspace coordinates. You can supply these coordinates for each container item by using the ptlIcon field of the RECORDCORE data structure.
If you do not specify x- and y-coordinate positions, the container control places the icons or bit maps at (0,0). However, your application can arrange the icons or bit maps either by sending the CM_ARRANGE message or by setting the CCS_AUTOPOSITION style bit when creating a container. With both of these methods, the container items are arranged in rows, and any coordinates specified in the ptlIcon field are ignored. As they are arranged each ptlIcon is updated with its new location.
The container items fill the topmost row until the width of the work area is reached. The items then wrap to form another row immediately below the filled row. This process is repeated until all the container items are positioned in rows. Default spacing is implemented according to the guidelines for the CUA user interface.
If the CCS_AUTOPOSITION style bit is set and the container is displaying the Icon view, container items are arranged automatically, without the CM_ARRANGE message being sent, when:
- The window size changes
- Container items are inserted, removed, sorted, invalidated, or filtered
- The font or font size changes
In all of these cases, container items are arranged the same as when the CM_ARRANGE message is sent. The CCS_AUTOPOSITION style bit is valid only when it is used with the Icon view.
If the CM_ARRANGE message is issued and the container control is not currently displaying the Icon view, the container items are still arranged logically. Nothing changes in the current view; the arrangement of the container items is not visible until the user switches to the Icon view.
Name View
The Name view (CV_NAME attribute) displays icon/text or bit-map/text pairs to represent container items. CV_NAME is an attribute of the CNRINFO data structure's flWindowAttr field.
In the Name view, icon/text pairs and bit-map/text pairs are icons and bit maps, respectively, with one or more lines of text displayed to the right of each icon or bit map. Each line can contain one or more text characters, which are left-justified. The container control does not limit the number of lines or the number of characters in each line.
The container control offers the option of flowing or not flowing the container items in the Name view. To flow container items means to dynamically arrange them in columns.
Non-Flowed Name View
If the container items are not flowed, the icon/text or bit-map/text pairs are placed in a single column in the leftmost portion of the work area.
Flowed Name View
If the container items are flowed (CV_NAME | CV_FLOW), the container appears. In this case, the container items fill the leftmost column until the depth of the work area is reached. The items then wrap to form another column immediately to the right of the filled column. This process is repeated until all of the container items are positioned in columns.
The width of each column is determined by the widest text string within the column. The height of the work area is determined by the size of the window.
Text View
The Text view (CV_TEXT attribute) displays one or more lines of text to represent container items. CV_TEXT is an attribute of the CNRINFO data structure's flWindowAttr field.
Each line can contain one or more text characters, which are left-justified. The container control does not limit the number of lines or the number of characters in each line.
The container control offers the option of flowing or not flowing the container items in the Text view.
Non-Flowed Text View
If the text strings are not flowed, the text for each container item is placed in a single column in the leftmost portion of the work area.
Flowed Text View
If the text strings are flowed (CV_TEXT | CV_FLOW), the container appears. In this case, the text strings fill the leftmost column until the depth of the work area is reached. The text strings then wrap to form another column immediately to the right of the filled column. This process is repeated until all the text strings are positioned in columns.
The width of each column is determined by the widest text string within the column. The height of the work area is determined by the size of the window.
Tree View
The Tree view (CV_TREE attribute) displays container items arranged hierarchically. CV_TREE is an attribute of the CNRINFO data structure's flWindowAttr field.
The leftmost items displayed in the Tree view are at the root level and are the same items displayed in all the other container views. Items that contain other items are called parent items. The items that a parent item contains are called child items and can be displayed only in the Tree view. Child items that contain other items serve a dual role: they are the children of their parent item, but they are parent items as well, with children of their own. For example, a parent item might be a book that contains individual child items for its chapters or a folder that contains several reports. The chapters or reports, in turn, could be parent items that contain their own children, such as the major sections of a chapter or report.
If the child items of a parent item are not displayed, the parent item can be Expanded to display them as a new branch in the Tree view. Once a parent item has been expanded, it can be Collapsed to remove its child items from the display.
You can use the cxTreeIndent and cxTreeLine fields of the CNRINFO data structure to specify the number of pels that a new branch is to be indented horizontally, and the width of the lines that are used to connect branches of the tree. These lines are displayed only if the CA_TREELINE attribute is specified in the flWindowAttr field.
The Tree view has three different types: Tree icon view, Tree text view, and Tree name view. If CV_TREE is specified, the Tree icon view is the default view. If neither CV_ICON, CV_TEXT, or CV_NAME are specified, CV_ICON is assumed.
Tree Icon View and Tree Text View
The Tree icon and Tree text views are identical in every aspect except their appearance on the screen. Container items in the Tree icon view (CV_TREE | CV_ICON) are displayed as either icon/text pairs or bit-map/text pairs. The items are drawn as icons or bit maps with one or more lines of text displayed to the right of each icon or bit map.
Container items in the Tree text view (CV_TREE | CV_TEXT) are displayed as text strings. In both views, the container control does not limit the number of lines of text or the number of characters in each line.
In the Tree icon and Tree text views, a parent item is expanded by selecting the Collapsed icon/bit map, which is displayed to the left of the parent item.
The Collapsed icon/bit map should contain some visible indication that the item can be expanded. The default Collapsed bit map that is provided by the container control uses a plus sign (+) to indicate that more items, the children of this parent, can be added to the view.
When the child items of a parent item are displayed, the Collapsed icon/bit map to the left of that parent item changes to an Expanded icon/bit map. Just as the Collapsed icon/bit map provides a visible indication that an item can be expanded, so should the Expanded icon/bit map indicate that an item can be collapsed. The default Expanded bit map provided by the container control uses a minus sign (-) to indicate that the child items of this parent can be subtracted from the view. If any of the child items have children of their own, a Collapsed or Expanded icon/bit map is displayed to their immediate left as well.
To display your own Collapsed and Expanded icons or bit maps, specify their handles by using the hptrCollapsed and hptrExpanded fields of the CNRINFO data structure for icons, and the hbmCollapsed and hbmExpanded fields for bit maps. Also, you can use the slTreeBitmapOrIcon field to specify the size, in pels, of these Collapsed and Expanded icons and bit maps.
Tree Name View
Container items in the Tree name view (CV_TREE | CV_NAME) are displayed as either icon/text pairs or bit-map/text pairs. Similar to the Tree icon view, the items are drawn as icons or bit maps with one or more lines of text displayed to the right of each icon or bit map. The container control does not limit the number of lines or the number of characters in each line of text.
Unlike the Tree icon view, however, separate Collapsed and Expanded icons/bit maps are not used. Instead, if an item is a parent, the icon or bit map that represents that item contains the same type of visible indication that is placed in a separate icon/bit map in the Tree icon view to show that an item can be collapsed or expanded. In this way, the icon or bit map that represents the parent item can serve a dual purpose and thus preserve space on the screen, an important consideration if the text strings used to describe items become too long.
The container control does not provide default icons or bit maps for the Tree name view. To display your own Collapsed and Expanded icons or bit maps, specify their handles using the hptrCollapsed and hptrExpanded fields of the TREEITEMDESC data structure for icons, and the hbmCollapsed and hbmExpanded fields for bit maps. Also, you can use the slBitmapOrIcon field of the CNRINFO data structure to specify the size, in pels, of these Collapsed and Expanded icons and bit maps.
Details View
The Details view (CV_DETAIL attribute) of the container control can display the following data types to represent container item: icons or bit maps, text, numbers, dates, and times. CV_DETAIL is an attribute of the CNRINFO data structure's flWindowAttr field.
The data is arranged in columns, which can have headings. Each column can contain data that belongs to only one of the valid data types. Column headings can contain text, icons, or bit maps.
The width of each column can be explicitly specified in the cxWidth field of the FIELDINFO data structure. If a column width is not specified, it is determined by the widest entry in the column.
Columns can be inserted or removed dynamically. All of the columns in a given row belong to a single container item; selecting the data portion of a row selects the entire row, not just the individual column.
Details view column headings and data can be top- or bottom-justified or vertically centered, as well as left- or right-justified or horizontally centered. In addition, horizontal separator lines can be specified between the column headings and the data; vertical separator lines can be placed between columns.
Determining the Width of a Column in a Details View
There are instances when you might want to determine the width of a column in the Details view. A function has been added to the container control to allow you to determine the width of the data in a column. You can then compute the width of the entire column by adding the width of the data to the left and right margins of the column. To determine the width of a column:
1.- Define an attribute with a value of 0x0200 and give it a name such as CMA_DATAWIDTH.
2.- Issue the CM_QUERYDETAILFIELDINFO message with the following values:
a. Provide a pointer to the FIELDINFO data structure in param1.
b. Specify your attribute (see step 1) in param2.
c. Request a return value with a type of LONG, not PFIELDINFO, to retrieve the width of the column in the FIELDINFO data structure to which you are pointing. The value returned is the width of the data (text, icon, or bit map) in this column.
3.- Use GpiQueryFontMetrics to query the average character width of the font used by the container. This value will be used to calculate the total column width.
4.- Multiply 3 by the average character width and add this to the data width returned from step 2 for all columns except the following:
- The first and last columns in each split window. In these cases, multiply 2.5 by the average character width and add the column data width returned from step 2.
- The only other special case is where there is only 1 column in either the left or right split windows. In this case, you would multiply 2 by the average character width and add the column data width returned from step 2.
5.- The value returned is the total width of the column.
Split Bar Support for the Details View
A split bar enables the application to split the container window vertically between two column boundaries. This function is available only in the Details view.
The two portions of the work area on either side of the split bar appear side-by-side. They scroll in unison vertically, but they scroll independently horizontally.
The application is responsible for specifying the position of the split bar, which is defined with the xVertSplitbar field. Also, the rightmost column of the left split window is specified with the pFieldInfoLast field. xVertSplitbar and pFieldInfoLast are fields of the CNRINFO data structure.
The left split window cannot be empty if there is data in the right window. The right split window is not required to have data. However, because data cannot be scrolled from the right split window into the left split window, or from left to right, the split bar loses much of its usefulness if the right split window is empty.
The user can drag the vertical split bar within the limits of the window. As the user drags the split bar to the left, the right split window becomes wider; as the user drags the split bar to the right, the left split window becomes wider.
Each container control can have one vertical split bar. Horizontal split bars are not supported.
Using Container Controls
This section provides information about the following topics:
Creating a container Allocating memory for container records Allocating memory for container columns Inserting container records Removing container records Setting the container control focus Using container views Changing a container view Arranging icons in a grid
Note: Most of the sample code in this section is part of a complete program that creates a container for a small address book. The program is illustrated in "Sample Code for Container Controls".
Creating a Container
You create a container by using the WC_CONTAINER window class name in the ClassName parameter of WinCreateWindow. Before you create the container, you can create a frame window as a parent. If you create the frame window, it sizes the container to fill its work area. The following sample code shows the code to create both the frame and the container:
HAB hab; HWND hPopupMenu; HWND hFrameWnd, hCnrWnd; /* Frame and Container window handles */ PFNWP SysWndProc; INT main (VOID) { HMQ hmq; FRAMECDATA fcd; QMSG qmsg; if (!(hab = WinInitialize(0))) return FALSE; if (!(hmq = WinCreateMsgQueue(hab, 0))) return FALSE; /***********************************************************************/ /* Set up the frame control data for the frame window. */ /***********************************************************************/ fcd.cb = sizeof(FRAMECDATA); fcd.flCreateFlags = FCF_TITLEBAR | FCF_SYSMENU | FCF_SIZEBORDER | FCF_SHELLPOSITION | FCF_MINMAX | FCF_TASKLIST; fcd.hmodResources = NULLHANDLE; fcd.idResources = 0; /***********************************************************************/ /* Create the frame to hold the container control. */ /***********************************************************************/ hFrameWnd = WinCreateWindow(HWND_DESKTOP, WC_FRAME, "Phone Book", 0, 0, 0, 0, 0, NULLHANDLE, HWND_TOP, 0, &fcd, NULL); /***********************************************************************/ /* Verify that the frame was created; otherwise, stop. */ /***********************************************************************/ if (!hFrameWnd) return FALSE; /***********************************************************************/ /* Set an icon for the frame window. */ /***********************************************************************/ WinSendMsg(hFrameWnd, WM_SETICON, (MPARAM)WinQuerySysPointer(HWND_DESKTOP, SPTR_FOLDER, FALSE), NULL); /***********************************************************************/ /* Create the container. */ /***********************************************************************/ hCnrWnd = WinCreateWindow(hFrameWnd, WC_CONTAINER, NULL, CCS_AUTOPOSITION | CCS_READONLY | CCS_SINGLESEL, 0, 0, 0, 0, hFrameWnd, HWND_BOTTOM, FID_CLIENT, NULL, NULL);
The container is created with a default set of control data, which can be changed using the CM_SETCNRINFO message.
Allocating Memory for Container Records
Your application must allocate memory for a container record by using the CM_ALLOCRECORD message, which also enables you to allocate memory for additional application data.
The maximum number of records is limited by the amount of memory in the user's computer. The container control does not limit the number of records that a container can have.
The following sample code shows how to allocate memory for records that populate the container. A pointer to the record is returned.
HWND hIcon; PRECORDCORE Address, FirstRec; RECORDINSERT recsIn; ULONG x; /**********************************************************************/ /* Allocate MAXFRIENDS records all at once - */ /* CM_ALLOCRECORD returns them in a linked list. */ /**********************************************************************/ Address = (PRECORDCORE)WinSendMsg(hWnd, CM_ALLOCRECORD, 0, MPFROMLONG(MAXFRIENDS));
Your application can use the CM_ALLOCRECORD message to allocate memory for one or more container records. The application can request n container records with an nRecords parameter. If n is one, a pointer to that record is returned. If n is greater than one, a pointer to the first record in a linked list of n records is returned.
Allocating Memory for Container Columns
In addition to allocating memory for records, an application also must allocate memory for columns of data if the details view is used. In the Details view, a container's data is displayed in columns, each of which is described in a FIELDINFO data structure.
Memory is allocated for FIELDINFO data structures using the CM_ALLOCDETAILFIELDINFO message. Unlike the CM_ALLOCRECORD message, the CM_ALLOCDETAILFIELDINFO message does not allow the application to allocate memory for additional application data. However, the pUserData field of the FIELDINFO data structure can be used to store a pointer to the application-allocated data.
Multiple FIELDINFO data structures can be allocated with the nFieldInfo parameter of the CM_ALLOCDETAILFIELDINFO message.
Inserting Container Records
After the memory is allocated, you can insert one or more container records by using the CM_INSERTRECORD message.
The following sample code inserts records into a container for which memory was allocated in the previous code fragment:
/**********************************************************************/ /* We will need the first record's address to */ /* insert them into the container. */ /**********************************************************************/ FirstRec = Address; /**********************************************************************/ /* Loop through the address book, loading as we go. */ /* Because the CM_ALLOCRECORD returns a linked */ /* list, the address of the next record is retrieved */ /* from each record as we go (preccNextRecord). */ /**********************************************************************/ for (x = 0; x < MAXFRIENDS; x++) { Address->cb = sizeof(RECORDCORE); /* Standard records */ Address->hptrIcon = hIcon; /* File icon */ Address->pszIcon = Friends[x].NickName; Address->pszName = Friends[x].FullName; Address->pszText = Friends[x].FullName; Address = Address->preccNextRecord; /* Next record in list */ } /**********************************************************************/ /* Set up the insert record structure to place the */ /* records in the container. */ /**********************************************************************/ recsIn.cb = sizeof(RECORDINSERT); /* Put the records in after any others */ recsIn.pRecordOrder = (PRECORDCORE)CMA_END; /* All the records are top level (not children of other records) */ recsIn.pRecordParent = NULL; /* The icons are top level */ recsIn.zOrder = (USHORT)CMA_TOP; /* Redraw the container */ recsIn.fInvalidateRecord = TRUE; /* Set the number of records to insert */ recsIn.cRecordsInsert = MAXFRIENDS; /**********************************************************************/ /* Insert the records into the container. */ /**********************************************************************/ WinSendMsg(hWnd, CM_INSERTRECORD, (PRECORDCORE)FirstRec, &recsIn); }
The CM_INSERTRECORD message requires you to provide two pointers. The first pointer points to the record that is to be inserted, which is specified in the FirstRec parameter. When you are inserting multiple records, use this parameter to specify a pointer to a linked list of records.
The second pointer points to a RECORDINSERT data structure (&recsIn), which specifies information the container needs for inserting records.
One of the elements of information that this data structure contains is the order in which the records are to be inserted, which is specified in the pRecordOrder field. In this field you have two options. The first option is to specify a pointer to a container record. The records being inserted are placed immediately after that record. In this case, the pRecordParent field is ignored.
The second option is to specify whether the records being inserted are to be placed at the beginning or end of a list of records. This is done by specifying either the CMA_FIRST or CMA_END attributes. If you choose this option, the list of records used depends on the value of the pRecordParent field.
If CMA_FIRST or CMA_END is specified and the value of the pRecordParent field is NULL, the inserted records are placed at the beginning or end of the root-level records. However, if CMA_FIRST or CMA_END is specified and pRecordParent contains a pointer to a parent item record, the records are inserted at the beginning or end of the list of child item records that this parent record contains.
The RECORDINSERT data structure also lets you specify the z-order position of the records being inserted. The CMA_TOP and CMA_BOTTOM attributes of the zOrder field place the record at the top or bottom, relative to the other records in the z-order list. This field applies to the Icon view only.
To specify the number of records that are being inserted, use the cRecordsInsert field. The value of this field must be greater than 0.
The last field in the RECORDINSERT data structure is flInvalidateRecord, which enables you to control whether the records are displayed automatically when they are inserted. If you specify TRUE in this field, the display is updated automatically. However, if you specify FALSE, the application must send the CM_INVALIDATERECORD message after the records are inserted to update the display.
Where items are positioned in a container depends on the view the user has specified. If the Icon view is specified and the CCS_AUTOPOSITION style bit is not set, the x- and y-coordinates for each record, which are stored in the ptlIcon field of the RECORDCORE and MINIRECORDCORE data structures, determine its position. Records displayed in the Name view, Text view, Tree view, and Details view are positioned as previously described in this section.
Note: Records inserted into a list of child record items can be displayed in the Tree view only. These records are visible only if the parent record item to which these child record items belong is expanded.
Removing Container Records
The CM_REMOVERECORD message can be used to remove one or more container records from the container control. The following sample code removes all records from a container and frees the memory associated with those records. It is the application's responsibility to free all application-allocated memory that is associated with the removed container records. The container is invalidated and repainted.
USHORT cNumRecord; /* Number of records to be removed */ USHORT fRemoveRecord; /* Container message attributes */ /**********************************************************************/ /* Zero means remove all records. */ /**********************************************************************/ cNumRecord = 0; /**********************************************************************/ /* Specify attributes to invalidate the container */ /* and free the memory. */ /**********************************************************************/ fRemoveRecord = CMA_INVALIDATERECORD | CMA_FREE; /**********************************************************************/ /* Remove the records. */ /**********************************************************************/ WinSendMsg(hwndCnr, /* Container window handle */ CM_REMOVERECORD, /* Container message for removing */ /* records */ NULL, /* NULL PRECORDARRAY */ MPFROM2SHORT( cNumRecord, /* Number of records */ fRemoveRecord)); /* Memory invalidation flags */
The application must set the pointers to each record to be removed in an array. If the fRemoveRecord parameter of this message includes the CMA_FREE attribute, the records are removed and the memory is freed. If this attribute is not set, the records are removed from the list of items in the container, and the application must use the CM_FREERECORD message to free the memory. The default is not to free the memory.
If the fRemoveRecord parameter includes the CMA_INVALIDATERECORD attribute, the container is invalidated after the records are removed. The default is not to invalidate the container. The CMA_INVALIDATERECORD attribute can be used with the CMA_FREE attribute, separated by a logical OR operator (|), to free the record's memory and invalidate the container.
Setting the Container Control Focus
The application must set the focus to the container control using WinSetFocus so that all mouse and keyboard activity goes to the container window. The following code fragment shows how to use WinSetFocus:
WinSetFocus(HWND_DESKTOP, /* Desktop window handle */ hListWnd) /* Handle of window to receive focus */
Using Container Views
Container views are specified by using attributes on the flWindowAttr field of the CNRINFO data structure.
Because the container control does not support both icons and bit maps in the same view, an application must specify which are used by setting either the CA_DRAWICON attribute or the CA_DRAWBITMAP attribute in the flWindowAttr field of the CNRINFO data structure. The default is the CA_DRAWICON attribute. The size of the icon or bit map can be specified in the slBitmapOrIcon field of the CNRINFO data structure.
Changing a Container View
The following sample code shows how to use the CM_SETCNRINFO message to change from the current view of a container (Name, Details, or Text) to the Icon view:
CNRINFO cnrInfo; /**********************************************************************/ /* Set the attribute field to the Icon view. */ /**********************************************************************/ cnrInfo.flWindowAttr = CV_ICON; /**********************************************************************/ /* Change the view from the current view to the Icon view. */ /**********************************************************************/ WinSendMsg( hwndCnr, /* Container window handle */ CM_SETCNRINFO, /* Container message for setting */ MPFROMP(&cnrInfo), /* Container control data */ MPFROMLONG( CMA_FLWINDOWATTR)); /* Message attribute that sets */ /* container window attributes */
Creating a Grid for Icons
This section will describe how to create a grid.
Graphical User Interface Support for Container Controls
This section describes the container control support for graphical user interfaces (GUIs). Except where noted, this support conforms to CUA interface design guidelines. The GUI support provided by the container control consists of the following:
- Scrolling
- Dynamic scrolling
- Selecting container items
- Providing emphasis
- Using direct manipulation
Scrolling
The container control automatically provides horizontal or vertical scroll bars, or both, whenever the container window's work area is not large enough to display all of the container items.
If all container items are visible in the work area, the scroll bars are either removed or disabled, depending on the view and how the items are positioned, as follows:
- If container items are displayed in the icon or tree view, and one or more items are not visible in the work area, a horizontal scroll bar, vertical scroll bar, or both, are provided, depending on the position of the items outside of the work area. If container items are positioned to the right or left of the work area, a horizontal scroll bar is provided; if container items are positioned below or above the work area, a vertical scroll bar is provided.
- Scroll bars are not provided if all the container items are visible in the work area. Scroll bars are removed from the container window if either of the following occurs:
- Container items positioned outside the work area are moved into the work area.
- The size of the container window is increased so that container items formerly not visible become visible.
- If container items are displayed in non-flowed text and non-flowed Name views, a vertical scroll bar is provided; this scroll bar is disabled if all the container items are visible in the work area. A horizontal scroll bar is used in these views only when the work area is too narrow to allow the widest container item to be seen in its entirety. If the user changes the window size to allow the entire widest container item to be seen, the horizontal scroll bar is removed.
- If container items are displayed in flowed text and flowed name views, a horizontal scroll bar is provided; this scroll bar is disabled if all the container items are visible in the work area. A vertical scroll bar is used in these views only when the work area is too short to allow the tallest container item to be seen in its entirety. If the user changes the window size to allow the entire tallest container item to be seen, the vertical scroll bar is removed.
- If container items are displayed in the Details view, both horizontal and vertical scroll bars are provided. These scroll bars are disabled if all the container items are visible in the work area.
- Note: A Details view that is split has two horizontal scroll bars, one for each portion of the split window.
Dynamic Scrolling
The container control supports dynamic scrolling, which enables the user to drag the scroll box in the scroll bar and get immediate visible feedback on where the scrolling stops when the scroll box is dropped. If the scrolling range is greater than 32K pels, dynamic scrolling is disabled.
Selecting Container Items
Except during direct manipulation and direct editing of text in a container, a user must select a container item before performing an action on it. The container control provides several selection types, along with selection techniques to implement those types. The container control also supports two selection mechanisms: pointing device, such as a mouse, and the keyboard.
Selection Types
The container control supports the following selection types:
- Single selection
- Single selection enables a user to select only one container item at a time. This is the default selection type for all views and is the only selection type supported for the Tree view.
- Extended selection
- Extended selection enables a user to select one or more container items, in any combination. The CUA-defined keyboard augmentation keys are implemented for extended selection. When used with a pointing device, these keys enable a user to select discontiguous sets of container items. Extended selection is valid for all views except the Tree view.
- Multiple selection
- Multiple selection enables a user to select none, some, or all of the container items. Multiple selection is valid for all views except the Tree view.
Only one of these selection types can be used for each container. The selection type for a container is defined when the container is created.
Selection Techniques
Depending on the type of view and the type of selection, a user can select container items using the following selection techniques:
- Marquee selection
- Marquee selection is supported only in the Icon view and is only valid with the extended and multiple selection types. This selection technique enables a user to begin selection from an anchor point that is established by moving the pointer to white space in the container and pressing, but not releasing, the select button on the pointing device. As the user presses the select button and drags the pointer, a tracking rectangle is drawn between the anchor point and the current pointer position. All items whose icons or bit maps are entirely within the tracking rectangle are dynamically selected.
- Swipe selection
- Swipe selection is valid only with the extended and multiple selection types. The container control implements two techniques for swipe selection: touch swipe and range swipe.
- Touch swipe
- Touch-swipe selection is implemented in the Icon view. With this selection technique, the pointer must pass over some portion of a container item while the user is pressing the select button for that item to be selected.
- Range swipe
- In views other than the Icon and Tree views, range-swipe selection is available. With this method, the user presses the select button while moving the pointer. However, the pointer does not have to pass directly over a container item for that item to be selected. Aside from pressing the select button and moving the pointer, the only other requirement for selection is that the container item must be within a range of items that is being selected. The range begins at the pointer's position when the user presses the select button; it ends at the pointer's position when the user releases the select button.
- First-letter selection
- For the Icon, Name, Text, and Tree views, first letter selection occurs when a character key is pressed, and the first container item whose text begins with that character is displayed with selected-state emphasis. The same is true for the Details view, except that all the columns for a record are searched for a matching character before the next record is searched. The effect of first letter selection on other selected container items depends on the chosen selection type (single, multiple, or extended).
- Note
- If more than one container window is open, selecting a container item in one window has no effect on the selections in any other window.
Selection Mechanisms
Mouse button 1 (the select button) is used for selecting container items, and mouse button 2 (the drag button) is used for dragging and dropping container items during direct manipulation. These definitions also apply to the same buttons on any other pointing device.
In addition, a user can press a keyboard key while pressing a mouse button; this is called keyboard augmentation. The only instance of keyboard augmentation defined specifically for the container control is pressing the Alt key with the select button, which starts direct editing of text in a container.
In addition, the container control supports two keyboard cursors that can be moved by using keyboard navigation keys:
- The selection cursor, a dotted black box drawn around a container item, which represents the current position for the purpose of keyboard navigation.
- The text cursor, a vertical line that shows the user where text can be inserted or deleted when container text is being edited directly.
Keyboard navigation consists of the use of the Up and Down Arrow, Left and Right Arrow, Home, End, PgUp, and PgDn keys. If container items are not visible within the work area, navigation with these keys causes the items to scroll into view if the user is not editing container text directly.
Providing Emphasis
The container control supports various types of emphasis. The following list describes forms of emphasis that have a distinct visible representation in the container control:
- Selected-state and unavailable-state emphasis
- When a container item is selected, the container item receives selected-state emphasis, which means that the emphasis is applied to icon/text or bit-map/text pairs in the Icon, Name, Tree icon, and Tree name views; text strings in the Text and Tree text views; and an entire row that represents a container item in the Details view.
- The color for selected-state emphasis can be changed by using the control panel or WinSetPresParam, which results in a WM_PRESPARAMCHANGED message being sent to the container.
- In-use emphasis
- Cross-hatching behind an icon or bit map indicates in-use emphasis. In-use emphasis is not applied to container items in the Text view, Tree text view, or Details view when it contains text only. However, the Details view often includes icons or bit maps in one column of each record, usually the leftmost column. In this situation, specify the column that contains the icons or bit maps so that in-use emphasis can be applied to them. This column can be set by using the pFieldInfoObject field of the CNRINFO data structure.
- Target emphasis
- Target emphasis is used during direct manipulation. When a user drags one container item over another, the item beneath the dragged item displays target emphasis. Two forms of target emphasis (visible feedback) are available: a black line and a black border. These forms of emphasis indicate the target, where the container item is dropped if the user releases the drag button.
Using Direct Manipulation
Direct manipulation is a protocol that enables the user to drag a container item within its current window or from one window to another. The user can drop the container item either on white space in a window or on another item.
Direct manipulation can be performed with all views of the container control. A function is provided so that the application is notified if an item is dropped on another item in the container and if an item is dragged from the container.
The user can drag any container item, whether or not it is selected. If the user presses the drag button when the pointer is over a selected container item, the application drags all selected items.
If the user presses the drag button when the pointer is over a container item that is not selected, the application drags only the item that the pointer is over.
The container control fully supports direct manipulation.
Enhancing Container Controls Performance and Effectiveness
Positioning Container Items
Scrollable Workspace Areas Workspace and Work Area Origins
Specifying Space between Container Items
Providing Source Emphasis
Providing Target Emphasis
Specifying Deltas for Large Amounts of Data
Direct Editing of Text in a Container
Searching for Exact Text String Matches
Specifying Container Titles
Specifying Fonts and Colors
Drawing Container Items and Painting Backgrounds
Filtering Container Items
Optimizing Container Memory Usage
Allocating Memory for when Using MINIRECORDCORE Sharing Records among Multiple Containers Invalidating Records Shared by Multiple Containers Freeing Records Shared by Multiple Containers