65.9K
CodeProject 正在变化。 阅读更多。
Home

高级校验器控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.68/5 (8投票s)

2001 年 11 月 24 日

Zlib

6分钟阅读

viewsIcon

93533

downloadIcon

2366

一个高性能的类似“磁盘优化程序”的状态显示类

 [Sample 1 Image - 37K]
图1:使用普通对话框模板的示例

引言

在开发一个电信服务器监控应用程序期间,我遇到了需要显示大量线路和资源状态的需求。一种能让用户了解整体状态,同时又可以获取更详细状态信息的有趣方法是,使用一个通过彩色小方块来显示状态的控件。一些磁盘优化程序也使用这种技术,以便向用户显示操作的进度和状态。

在评估了一些格子控件之后,我决定开发自己的版本,因为我有一系列在评估过的实现中未能满足的需求。这些需求是:

  • 动态调整大小能力
  • 动态滚动条
  • 静态和动态工具提示
  • 实时工具提示更新
  • 支持 Unicode
  • 低内存占用
  • 低内存碎片
  • 对系统性能影响小

最终的成果是 CCheckersCtrl,一个派生自 CWnd 的类,既可以用作对话框、属性页和表单视图中的控件,也可以用作子窗口。

 [Sample 2 Image - 22K]
图2:带滚动条的控件

用法

如果您在对话框模板中使用格子控件,只需向对话框模板添加一个用户绘制按钮,并在类向导中将其与一个控件变量关联。您应该为该按钮激活以下样式:Visible、Tab Stop、Owner Draw、Client Edge。在类向导中,为该按钮分配一个控件变量。之后,您应该在对话框类中将该控件变量的类型从 CButton 更改为 CCheckersCtrl。这样就可以了。现在您可以开始使用它了。

在开始之前,让我解释一些基本概念:每个方块都被当作一个 项(Item) 来处理,就像 CListView 中的项一样。每个项通过一个从0(零)开始的索引号来标识,并保存三种信息:

  1. 项状态。这是一个 BYTE。状态以颜色显示。
  2. 一个可选的 DWORD 类型的项数据。
  3. 一个可选的工具提示文本,可以为项静态设置,也可以在需要显示时通过一个可重写的方法动态获取。

该控件存储一些关于项可视化的全局信息:

  1. 方块的最大和最小尺寸
  2. 一个用于表示每种可能状态的颜色数组

为了使用该控件,您不必指定所有这些东西,因为控件已经用合理的默认值进行了初始化:项的大小被设置为6到24像素的范围,颜色数组包含16种标准的Windows颜色。顺便说一下:如果您为一个项设置的状态值大于颜色数组中的最大元素索引,控件不会崩溃:颜色将通过以下公式确定:

COLORREF crUsedColor = m_crColorArray[bItemState % m_iNumColors];

如果您不希望方块自动调整大小,只需将项大小范围的最小值和最大值设置为相同的值即可。

CCheckersCtrl 的生命周期内,您可以按任意顺序重新配置、调整大小、添加项、删除项、设置值和属性。该控件能够处理所有这些操作。此版本的唯一限制是该控件不是线程安全的,所以请 不要 从多个线程中使用它。在将来的版本中,我将使其线程安全。

参考

这些方法的风格类似于标准的面向项的 MFC 控件,如 CListView,因此应该没有太多需要解释的地方。

BOOL CCheckersCtrl::SetSizeLimits (int iMinSize, int iMaxSize, 
                                    BOOL bRedraw = TRUE);

使用此函数可以定义方块可以自动调整大小的范围。如果您不希望方块自动调整大小,请为 iMinSizeiMaxSize 指定相同的值。

int CCheckersCtrl::GetMinSize () const;
int CCheckersCtrl::GetMaxSize () const;
BOOL CCheckersCtrl::IsAutoResize () const;

使用这些函数可以检索方块的大小范围。

int CCheckersCtrl::GetItemCount () const;

检索格子控件中的项数。

BOOL CCheckersCtrl::SetItemCount (
    int     iCheckers,
    BYTE    bInitialState = 0,
    DWORD   dwData = 0,
    LPCTSTR pszTip = LPSTR_TEXTCALLBACK,
    BOOL    bRedraw = TRUE
);

设置格子控件中的项数。如果项数大于现有项数,将使用指定的状态、项数据和工具提示文本创建新项。如果使用 LPSTR_TEXTCALLBACK,工具提示文本将在需要时通过调用可重写的方法 CCheckersCtrl::OnGetToolTipText 来请求。

BOOL CCheckersCtrl::SetColorsArray (COLORREF *pColors, 
                    int iNumColors, BOOL bRedraw = TRUE)

指定用于表示每种状态的颜色数组。由于状态是一个 BYTE,数组的最大大小不应超过256。

void CCheckersCtrl::SetDefaultColors (BOOL bRedraw = TRUE)

将用于表示每种状态的颜色数组重置为16种标准的Windows颜色。

BOOL CCheckersCtrl::SetItemData (int nItem, DWORD dwData);
DWORD CCheckersCtrl::GetItemData (int nItem) const;

这些函数允许您将应用程序定义的值与每个项关联并进行检索。

BOOL CCheckersCtrl::SetItemState (int nItem, BYTE bState, 
                                BOOL bRedraw = TRUE);
BYTE CCheckersCtrl::GetItemState (int nItem) const;

这些函数允许您获取或修改单个项的状态。更改会立即反映出来。

BOOL CCheckersCtrl::SetItemStateArray (BYTE *baState, 
                int cbSize = -1, BOOL bRedraw = TRUE);
BOOL CCheckersCtrl::GetItemStateArray (BYTE *baState, 
                                    int cbSize) const;

这些函数允许您获取或修改所有项的状态。更改会立即反映出来。

BOOL CCheckersCtrl::SetItemToolTip (int nItem, 
                LPCTSTR pszTip = LPSTR_TEXTCALLBACK);
BOOL CCheckersCtrl::GetItemToolTip (int nItem, 
                CString& str) const

这些函数允许您获取或修改项的工具提示文本。更改会立即反映出来。

BOOL CCheckersCtrl::Create (DWORD dwStyle, const RECT& rect, 
                        CWnd* pParentWnd, UINT nID);

使用此函数将格子控件创建为子窗口。该函数的用法与任何其他通用控件一样。格子控件没有特定的样式。

BOOL CCheckersCtrl::ResetState (BYTE bState = 0, BOOL bRedraw = TRUE);

将所有项的状态重置为指定的状态。

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
);

在指定位置插入新项。与 CCheckersCtrl::SetItemCount 中一样,可以指定初始状态、项数据和工具提示文本。

BOOL CCheckersCtrl::DeleteItem (int nItem, BOOL bRedraw = TRUE);
BOOL CCheckersCtrl::DeleteItems (int nItem, int nCount = 1, 
                                BOOL bRedraw = TRUE);

从指定位置删除项。

BOOL CCheckersCtrl::DeleteAllItems ();

删除所有项。

int CCheckersCtrl::FindItem (DWORD dwData) const;

允许根据关联的应用程序定义值查找项。此方法返回找到的项的索引。如果未找到匹配的项,则返回-1。

int CCheckersCtrl::HitTest (CPoint pt) const;

返回与指定客户区坐标对应的项索引。如果未找到匹配的项,则返回-1。

BOOL CCheckersCtrl::EnsureVisible (int nItem, BOOL bPartialOK);

确保指定的项是可见的。如果需要,该项将被滚动到视图中。

BOOL CCheckersCtrl::EnableToolTips (BOOL bEnable);

允许启用或禁用工具提示功能。如果禁用该功能,所有静态工具提示将被移除。当启用工具提示时,所有项将获得动态工具提示。

高级函数

CToolTipCtrl & CCheckersCtrl::GetToolTipCtrl ();
const CToolTipCtrl & CCheckersCtrl::GetToolTipCtrl () const;

检索内部的工具提示控件

可重写函数

您可以从 CCheckersCtrl 派生自己的类,以实现工具提示和鼠标点击的自定义行为。为此,CCheckersCtrl 提供了4个可重写的方法。

virtual BOOL CCheckersCtrl::OnGetToolTipText (
    int             nItem,
    BYTE            bState,
    DWORD           dwParam,
    TOOLTIPTEXT *   pTTT
);

如果您为项指定了动态工具提示(LPSTR_TEXTCALLBACK),则在请求工具提示文本时会调用此方法。您将获得项索引 nItem、其状态 bState、关联的应用程序值 dwData 以及一个指向 TOOLTIPTEXT 结构的指针,您可以在其中返回工具提示文本。请查看演示程序中的实现:

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
);

这三个可重写的方法允许您处理控件上的鼠标点击事件。nFlags 参数指示各种虚拟键是否被按下。此参数可以是以下值的任意组合:

  • MK_CONTROL:如果CTRL键被按下,则设置。
  • MK_LBUTTON:如果鼠标左键被按下,则设置。
  • MK_MBUTTON:如果鼠标中键被按下,则设置。
  • MK_SHIFT:如果SHIFT键被按下,则设置。

point 参数包含发生鼠标点击时相对于控件的客户区坐标。请查看演示应用程序中上下文菜单的实现:

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;
}

版本历史

版本 1.3

  • 修正了类向导注释
  • 修正了初始化问题
  • 修复了鼠标点击行为

版本 1.2

  • 修正了 SetDefaultColors 中的刷新错误
  • 添加了延迟重绘功能
  • 调整了演示应用程序

版本 1.1

  • 改进了文档
  • 为演示应用程序添加了上下文菜单

版本 1.0

初始修订版

© . All rights reserved.