|
fig. 1: Sample with normal dialog template |
Introduction
During the development of a telecommunication server monitoring application I
encountered the requirement to display the status of a huge number of lines and
resources. One interesting way to give the user a general idea of the overall status
while maintaining the possibility to get also more detailed status information, is
to use a control that displays the status with small colored boxes.
This technique is also used in several disk optimizing programs in order to show
the user the progress and status of the operation.
After evaluating some checker controls, I decided to develop my own version, since
I had a set of requirements that I didn't find in the evaluated implementations. These
requirements are:
- Dynamic resize capability
- Dynamic Scroll Bar
- Static and dynamic ToolTips
- Live ToolTip update
- Unicode aware
- Low memory footprint
- Low memory fragmentation
- Low impact on system performance
The result is CCheckersCtrl
, a CWnd
-derived class that
can be used either as a control in dialog boxes, property sheets and form views, or
as a child window.
|
fig. 2: The control with scrollbar |
Usage
If you use the checkers control in a dialog template, simply add a user draw button
to the dialog template and associate it with a control variable in class wizard. You should
activate the following styles for the button: Visible, Tab Stop, Owner Draw, Client
Edge
. In Class Wizard assign a control variable to the button. After this you should change the
type of the control variable in the dialog class from CButton
to
CCheckersCtrl
. That's all. Now you are ready to use it.
Before starting, let me explain some basic concepts: Each box is handled as an Item
like items in CListView
. Each item is identified by an index number that starts
from 0 (zero) and keeps three kinds of information:
- The item status. This is a
BYTE
. The status is displayed as a color.
- An optional item data of type
DWORD
.
- An optional ToolTip-Text that can be set statically for an item, or dynamically via
an overridable method when needed for display.
The control stores some global information about the visualization of the items:
- The maximal and minimal size of the boxes
- An array of colors for each possible status
In order to use the control you must not specify all this stuff, since the control is
initialized with decent defaults: the item size is set to a range from 6 to 24 pixels
and the color array contains the 16 standard windows colors. BTW: if you set a status
for an item that is greater than the highest element in the color array, the control
does not crash: the color is determined with the following formula:
COLORREF crUsedColor = m_crColorArray;
If you do not want the boxes to resize automatically, simply set the item size range
to the same value.
During the lifetime of the CCheckersCtrl
you can reconfigure, resize,
add items, delete items, set values and attributes in any order. The control is able
to handle all these operations. The only limitation of this version is that the control is not thread-safe, so please
DO NOT use it from multiple threads. In a future version I will make it thread-safe.
Reference
The style of the methods resembles the style of standard item oriented MFC controls like
CListView
, so there should not be much to explain.
BOOL CCheckersCtrl::SetSizeLimits (int iMinSize, int iMaxSize,
BOOL bRedraw = TRUE);
With this function you define in which range the boxes can be automatically resized.
If you do not want the boxes to automatically resize, specify the same value for
iMinSize
and iMaxSize
.
int CCheckersCtrl::GetMinSize () const;
int CCheckersCtrl::GetMaxSize () const;
BOOL CCheckersCtrl::IsAutoResize () const;
With these functions you can retrieve the size range for the boxes.
int CCheckersCtrl::GetItemCount () const;
Retrieves the number of items in a checkers control.
BOOL CCheckersCtrl::SetItemCount (
int iCheckers,
BYTE bInitialState = 0,
DWORD dwData = 0,
LPCTSTR pszTip = LPSTR_TEXTCALLBACK,
BOOL bRedraw = TRUE
);
Sets the number of items in a checker control. If the number of items is larger than
the number of existing items, new items are created with the specified state, item data
and tool tip text. If LPSTR_TEXTCALLBACK
is used, the tool tip text will be
requested just in time by invoking the overridable method
CCheckersCtrl::OnGetToolTipText
.
BOOL CCheckersCtrl::SetColorsArray (COLORREF *pColors,
int iNumColors, BOOL bRedraw = TRUE)
Specifies the array of colors to be used to represent each state. Since the state
is a BYTE
the maximal size for the array should not exceed 256.
void CCheckersCtrl::SetDefaultColors (BOOL bRedraw = TRUE)
Resets the array of colors to be used to represent each state to the 16 standard
windows colors.
BOOL CCheckersCtrl::SetItemData (int nItem, DWORD dwData);
DWORD CCheckersCtrl::GetItemData (int nItem) const;
These functions allow you to associate an application defined value to each item
and to retrieve it.
BOOL CCheckersCtrl::SetItemState (int nItem, BYTE bState,
BOOL bRedraw = TRUE);
BYTE CCheckersCtrl::GetItemState (int nItem) const;
These functions allow you to get or modify the state of an item. Changes are
reflected immediately.
BOOL CCheckersCtrl::SetItemStateArray (BYTE *baState,
int cbSize = -1, BOOL bRedraw = TRUE);
BOOL CCheckersCtrl::GetItemStateArray (BYTE *baState,
int cbSize) const;
These functions allow you to get or modify the state of all items. Changes are
reflected immediately.
BOOL CCheckersCtrl::SetItemToolTip (int nItem,
LPCTSTR pszTip = LPSTR_TEXTCALLBACK);
BOOL CCheckersCtrl::GetItemToolTip (int nItem,
CString& str) const
These functions allow you to get or modify the text of an item's tooltip.
Changes are reflected immediately.
BOOL CCheckersCtrl::Create (DWORD dwStyle, const RECT& rect,
CWnd* pParentWnd, UINT nID);
Use this function to create a checkers control as a child window. The function is used
like in any other common control. There are no specific styles for the checker control.
BOOL CCheckersCtrl::ResetState (BYTE bState = 0, BOOL bRedraw = TRUE);
Resets the state of all items to the specified state.
BOOL CCheckersCtrl::InsertItem (
int nItem,
BYTE bInitialState = 0,
DWORD dwData = 0,
LPCTSTR pszTip = LPSTR_TEXTCALLBACK,
BOOL bRedraw = TRUE
);
BOOL CCheckersCtrl::InsertItems (
int nItem,
int nCount = 1,
BYTE bInitialState = 0,
DWORD dwData = 0, LPCTSTR pszTip = LPSTR_TEXTCALLBACK,
BOOL bRedraw = TRUE
);
Inserts new items at the specified location. Like in CCheckersCtrl::SetItemCount
the
initial state, item data and tool tip text can be specified.
BOOL CCheckersCtrl::DeleteItem (int nItem, BOOL bRedraw = TRUE);
BOOL CCheckersCtrl::DeleteItems (int nItem, int nCount = 1,
BOOL bRedraw = TRUE);
Deletes items from the specified location.
BOOL CCheckersCtrl::DeleteAllItems ();
Deletes all items.
int CCheckersCtrl::FindItem (DWORD dwData) const;
Permits to find an item based on the associated application defined value. This method returns
the index of the found item. If no matching item is found, -1 is returned.
int CCheckersCtrl::HitTest (CPoint pt) const;
Returns the item index corresponding to the specified client coordinates.
If no matching item is found, -1 is returned.
BOOL CCheckersCtrl::EnsureVisible (int nItem, BOOL bPartialOK);
Makes sure that the specified item is visible. If needed the item is scrolled into view.
BOOL CCheckersCtrl::EnableToolTips (BOOL bEnable);
Permits to enable or disable the tool tip feature. If the feature is disabled, all
static tool tips are removed. When tool tips are enabled, all items will get dynamic
tool tips.
Advanced functions
CToolTipCtrl & CCheckersCtrl::GetToolTipCtrl ();
const CToolTipCtrl & CCheckersCtrl::GetToolTipCtrl () const;
Retrieves the internal ToolTip Control
Overridables
You can derive your own class from CCheckersCtrl
in order to implement custom
behavior for tool tips and mouse clicks. For this purpose CCheckersCtrl
offers
4 overridable methods.
virtual BOOL CCheckersCtrl::OnGetToolTipText (
int nItem,
BYTE bState,
DWORD dwParam,
TOOLTIPTEXT * pTTT
);
If you have specified items with dynamic tool tips (LPSTR_TEXTCALLBACK
), this
method is called when the text for a tool tip is requested. You get the item index nItem
,
its state bState
, the associated application value dwData
and a
pointer to a TOOLTIPTEXT
structure in which you can return the tool
tip text.
Take a look at the demo implementation:
BOOL CMyChecker::OnGetToolTipText (int nItem, BYTE bState,
DWORD dwParam, TOOLTIPTEXT *pTTT)
{
m_csBuffer.Format (
_T("Tooltip for Item %i\n\nStatus: %u\nParameter: %lu (0x%08x)"),
nItem,
(UINT) bState,
dwParam, dwParam
);
pTTT->lpszText = (LPTSTR) (LPCTSTR) m_csBuffer;
return TRUE;
}
virtual BOOL CCheckersCtrl::OnLeftClick (
BOOL bDoubleClick,
UINT nFlags,
CPoint point,
int nItem,
BYTE bState,
DWORD dwParam
);
virtual BOOL CCheckersCtrl::OnMiddleClick (
BOOL bDoubleClick,
UINT nFlags,
CPoint point,
int nItem,
BYTE bState,
DWORD dwParam
);
virtual BOOL CCheckersCtrl::OnRightClick (
BOOL bDoubleClick,
UINT nFlags,
CPoint point,
int nItem,
BYTE bState,
DWORD dwParam
);
These three overridables permit you to handle mouse clicks on the control. The nFlags
parameter indicates whether various virtual keys are down. This parameter can be any combination of
the following values:
MK_CONTROL
: Set if CTRL key is down.
MK_LBUTTON
: Set if left mouse button is down.
MK_MBUTTON
: Set if middle mouse button is down.
MK_SHIFT
: Set if SHIFT key is down
The point
parameter contains the client coordinates relative to the control on which
the mouse click occurred. Take a look at the implementation of the context menu in the demo
application:
BOOL CMyChecker::OnRightClick (BOOL bDoubleClick, UINT nFlags,
CPoint point, int nItem, BYTE bState, DWORD dwParam)
{
if ( bDoubleClick ) {
return TRUE;
}
CMenu menu;
if ( menu.LoadMenu (IDR_CONTEXT_MENU) ) {
CMenu *pPopUp = menu.GetSubMenu (0);
if ( pPopUp ) {
ClientToScreen (&point);
m_iLastClick = nItem;
pPopUp->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
point.x, point.y, GetParent ());
}
}
return TRUE;
}
Version History
Version 1.3
- Fixed Class Wizard Comments
- Fixed initialization
- Repaired mouse click behavior
Version 1.2
- Fixed refresh bug in
SetDefaultColors
- Added deferred redraw capability
- Adapted demo application
Version 1.1
- Improved documentation
- Added context menu to demo application
Version 1.0
Initial revision