Implementing Working Areas in List Controls
By default, a list control arranges all items in a standard grid fashion. However, another method is supported, working areas, that arranges the list items into rectangular groups. For an image of a list control that implements working areas, see Using List-View Controls in the Windows SDK.
Note
Working areas are visible only when the list control is in icon or small icon mode. However, any current working areas are maintained if the view is switched to the report or list mode.
Working areas can be used to display an empty border (on the left, top and/or right of the items), or cause a horizontal scroll bar to be displayed when there normally wouldn't be one. Another common usage is to create multiple working areas to which items can be moved or dropped. With this method, you could create areas in a single view that have different meanings. The user could then categorize the items by placing them in a different area. An example of this would be a view of a file system that has an area for read/write files and another area for read-only files. If a file item were moved into the read-only area, it would automatically become read-only. Moving a file from the read-only area into the read/write area would make the file read/write.
CListCtrl provides several member functions for creating and managing working areas in your list control. GetWorkAreas and SetWorkAreas retrieve and set an array of CRect objects (or RECT structures), which store the currently implemented working areas for your list control. In addition, GetNumberOfWorkAreas retrieves the current number of working areas for your list control (by default, zero).
Items and Working Areas
When a working area is created, items that lie within the working area become members of it. Similarly, if an item is moved into a working area, it becomes a member of the working area to which it was moved. If an item does not lie within any working area, it automatically becomes a member of the first (index 0) working area. If you want to create an item and have it placed within a specific working area, you will need to create the item and then move it into the desired working area with a call to SetItemPosition. The second example below demonstrates this technique.
The following example implements four working areas (rcWorkAreas), of equal size with a 10-pixel-wide border around each working area, in a list control (m_WorkAreaListCtrl).
CSize size;
size = m_WorkAreaListCtrl.ApproximateViewRect();
size.cx += 100;
size.cy += 100;
CRect rcWorkAreas[4];
rcWorkAreas[0].SetRect(0, 0, (size.cx/2) - 5, (size.cy/2) - 5);
rcWorkAreas[1].SetRect((size.cx/2) + 5, 0, size.cx, (size.cy/2) - 5);
rcWorkAreas[2].SetRect(0, (size.cy/2) + 5, (size.cx/2) - 5, size.cy);
rcWorkAreas[3].SetRect((size.cx/2) + 5, (size.cy/2) + 5, size.cx, size.cy);
//set work areas
m_WorkAreaListCtrl.SetWorkAreas(4, rcWorkAreas);
The call to ApproximateViewRect was made to get an estimate of the total area required to display all items in one region. This estimate is then divided into four regions and padded with a 5-pixel-wide border.
The next example assigns the existing list items to each group (rcWorkAreas) and refreshes the control view (m_WorkAreaListCtrl) to complete the effect.
// set insertion points for each work area
CPoint rgptWork[4];
for (int i = 0; i < 4; i++)
{
rgptWork[i].x = rcWorkAreas[i].left + 10;
rgptWork[i].y = rcWorkAreas[i].top + 10;
}
// now move all the items to the different quadrants
for (int i = 0; i < 20; i++)
{
m_WorkAreaListCtrl.SetItemPosition(i, rgptWork[i % 4]);
}
// force the control to rearrange the shuffled items
m_WorkAreaListCtrl.Arrange(LVA_DEFAULT);