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

XBreadCrumbBar - 使用超链接和 HTML 绘制面包屑导航

starIconstarIconstarIconstarIconstarIcon

5.00/5 (21投票s)

2007年8月7日

CPOL

6分钟阅读

viewsIcon

65379

downloadIcon

840

XBreadCrumbBar 是一个无窗口、非 MFC 的类,它允许您以 HTML 文本格式显示面包屑导航,并支持 Web 链接和 APP: 链接。

引言

根据维基百科

面包屑或面包屑导航是用户界面中使用的一种导航技术。它的目的是让用户能够跟踪他们在程序或文档中的位置。这个术语来源于童话故事“汉赛尔和格蕾太尔”中留下的面包屑痕迹。

这是面包屑在网络上常用的方式

screenshot

当然,谷歌也使用面包屑

screenshot

面包屑的使用在网络上越来越普遍,并且也开始出现在 PC 应用程序中。Vista Windows Explorer 使用面包屑来显示您在文件系统中的位置。

screenshot

面包屑导航似乎特别适合任何类型的分层系统,并且有两个目的:首先,显示您在分层结构中的位置;其次,允许您以随机访问的方式导航到分层结构中的前一个点——换句话说,您不必一直按“后退”按钮,只需单击第二个链接即可立即转到面包屑导航中的第二个位置。

虽然对面包屑导航的大多数研究都集中在网站上(请参阅参考文献),但在导航网站和导航非琐碎 PC 应用程序之间存在许多相似之处,特别是那些处理分层数据的应用程序——例如,人力资源系统、汽车零件订购系统以及用于呈现和选择课程表的软件。用户界面专家 Jakob Nielsen 有一篇关于面包屑的有趣博客。如果您将他博客中的“网站”一词替换为“PC 应用程序”,它仍然完全有意义。

面包屑导航似乎适合我最近参与的一个大型库存系统,并且在向客户展示时,他很喜欢这个想法。这导致了 XBreadCrumbBar 的创建,它基于XHtmlDraw。这在面包屑导航的视觉显示方面提供了额外的灵活性,并且还内置了对 Web 链接APP: 链接的支持(有关更多详细信息,请参阅我的XHtmlDraw文章)。

XBreadCrumbBar 功能

首先,让我向您展示演示应用程序

screenshot

以下是主要功能

  1. 无链接的面包屑显示静态面包屑导航,没有链接。文本使用粗体字体显示,分隔符也是如此。
  2. Web 链接的面包屑显示了链接的颜色,这些颜色是从我喜欢的图书网站复制过来的。最后一个面包屑颜色不同,且不是链接。请注意,面包屑是粗体的,而分隔符不是。
  3. APP: 链接的面包屑显示每个链接不同的颜色,鼠标悬停在第一个链接上。点击链接时,您会看到

    screenshot

XBreadCrumbBar 实现

CXBreadCrumbBar 类派生自 CXHtmlDraw(可在本文中找到描述),并嵌入了链接处理类 CXHtmlDrawLink(也在CXHtmlDraw 文章中进行了描述)。

以下是 CXBreadCrumbBar 类的一些函数

函数 描述
int Draw(HWND hWnd, BOOL bUnderlineUrl, int index = -1) 将 XBreadCrumbBar 绘制到 hWnd。如果 index = -1,则绘制所有面包屑,否则仅绘制指定索引的面包屑。
int Draw(HDC hdc, BOOL bUnderlineUrl, int index = -1) 将 XBreadCrumbBar 绘制到 hdc。如果 index = -1,则绘制所有面包屑,否则仅绘制指定索引的面包屑。
BOOL GetBoldSeparator() 获取分隔符的粗体标志状态
int GetCount() 检索面包屑的数量
XHTMLDRAWSTRUCT * GetDrawStruct(int index) 检索由索引指定面包屑的绘制结构
size_t GetCrumb(int index, BOOL bStripHtml, LPTSTR pszCrumb, size_t size) 检索由索引指定面包屑的字符串。如果 pszCrumb 为 NULL,则仅返回面包屑的长度(以 TCHAR 为单位)。
int GetCrumb(LPCTSTR lpszCrumb, BOOL bStripHtml) 检索字符串与 lpszCrumb 匹配的面包屑的索引
CXHtmlDrawLink * GetLinks() 检索指向 CXHtmlDrawLink 对象的指针,该对象用于 Web 和 APP: 链接
int GetCrumbs(TCHAR *** crumbs) 检索指向面包屑字符串指针数组的指针
TCHAR * GetSeparator() 检索指向分隔符字符串的指针
CXBreadCrumbBar& InitDrawStruct(XHTMLDRAWSTRUCT * pXHDS, BOOL bBoldSeparator = TRUE) 初始化绘制结构
int IsAnchorUnderlined() 返回被下划线标记的面包屑的索引号,否则返回 -1
int IsOverAnchor(HWND hWnd) 返回鼠标悬停其上的面包屑的索引号,否则返回 -1
BOOL RelayClick(HWND hWnd) 将单击事件转发给 CXBreadCrumbBar
void RelayMouseMove(HWND hWnd) 将鼠标移动转发给 CXBreadCrumbBar
CXBreadCrumbBar& SetAppCommands(XHTMLDRAW_APP_COMMAND * paAppCommands, int nAppCommands) 设置 APP: 命令的表
CXBreadCrumbBar& SetBoldSeparator(BOOL bBold) 设置分隔符粗体标志:如果为 TRUE,则分隔符在面包屑为粗体时也为粗体;如果为 FALSE,则即使面包屑为粗体,分隔符也不会为粗体。
CXBreadCrumbBar& SetCrumbs(const TCHAR * crumbs[], int count) 从字符串数组设置面包屑字符串
CXBreadCrumbBar& SetCrumbs(LPCTSTR crumbs, TCHAR sepchar) 从字符分隔的字符串设置面包屑字符串,其中字符由 sepchar 指定
CXBreadCrumbBar& SetSeparator(LPCTSTR lpszSep) 设置分隔符字符串

如何使用

请按照以下步骤将 XBreadCrumbBar 集成到您的应用程序中

步骤 1:添加 XBreadCrumbBar 文件

将以下文件添加到您的项目中

  • XBreadCrumbBar.cpp
  • XBreadCrumbBar.h
  • XHtmlDraw.cpp
  • XHtmlDraw.h
  • XHtmlDrawLink.cpp
  • XHtmlDrawLink.h
  • XNamedColors.cpp
  • XNamedColors.h
  • XString.cpp
  • XString.h
注意:对于所有上述 .cpp 文件,您必须在 Visual Studio 中选择不使用预编译头文件

步骤 2:定义持久的 CXBreadCrumbBar 对象

在演示应用程序中,在 XBreadCrumbBarTestDlg.h 中定义了三个 CXBreadCrumbBarM 对象

    CXBreadCrumbBar m_ccb[3];

步骤 3:初始化 XHTMLDRAWSTRUCT 结构

XHTMLDRAWSTRUCT 结构包含 XBreadCrumbBar 的格式化信息和屏幕位置。这是演示应用程序中的初始化函数

//=================================================================
void CXBreadCrumbBarTestDlg::InitDrawStruct(int index)
//=================================================================
{
    ASSERT((index >=0) && (index < 3));

    LOGFONT lf;
    memset(&lf, 0, sizeof(LOGFONT));
    CFont *pFont = GetFont();    // get font for the dialog
    if (pFont)
        pFont->GetLogFont(&lf);

    CWnd *pWnd = GetDlgItem(g_uStatic[index]);
    ASSERT(pWnd);

    CRect rect;
    pWnd->GetWindowRect(&rect);
    ScreenToClient(&rect);
    rect.DeflateRect(5, 5);
    rect.top += 10;

    CXBreadCrumbBar::XHTMLDRAWSTRUCT ds;

    ds.crText           = m_rgbText;
    ds.nID              = index;
    if (index == 0)
        ds.crText = RGB(119,121,118);
    if (index == 1)
        ds.crBackground = GetSysColor(COLOR_BTNFACE);
    else
        ds.crBackground = m_rgbBackground;
    ds.rect             = rect;
    if (index != 2)
        ds.bBold        = TRUE;
    else
        ds.bBold        = FALSE;
    ds.bLogFont         = TRUE;
    if (index == 0)
        _tcscpy(lf.lfFaceName, _T("Arial"));
    memcpy(&ds.lf, &lf, sizeof(LOGFONT));

    if (index == 0)
        m_ccb[index].SetSeparator(_T(" > "));

    // must set crumbs before calling CXBreadCrumbBar::InitDrawStruct

    switch (index)
    {
        default:
        case 0: 
            // all crumbs in one string, separated by '~'
            m_ccb[index].SetCrumbs(SAMPLE_1, _T('~'));    
            break;

        case 1: 
            // array of 4 strings
            m_ccb[index].SetCrumbs(SAMPLE_2, 4);    
            break;

        case 2: 
            // array of 5 strings
            m_ccb[index].SetCrumbs(SAMPLE_3, 5);    
            break;
    }

    // don't use bold separators in second bread crumb bar
    m_ccb[index].InitDrawStruct(&ds, (index == 1) ? FALSE : TRUE);
}

步骤 4:初始化 APP: 命令

APP: 超链接允许您显示超链接文本,当用户单击它时,该文本会将 Windows 消息发送到指定的窗口。要使用 APP: 超链接,您必须设置APP: 命令表——这是演示应用程序中使用的表

    CXHtmlDraw::XHTMLDRAW_APP_COMMAND AppCommands[] = 
    {
        { m_hWnd, WM_APP_COMMAND_1, 1, _T("WM_APP_COMMAND1") },
        { m_hWnd, WM_APP_COMMAND_2, 2, _T("WM_APP_COMMAND2") },
        { m_hWnd, WM_APP_COMMAND_3, 3, _T("WM_APP_COMMAND3") },
        { m_hWnd, WM_APP_COMMAND_4, 4, _T("WM_APP_COMMAND4") },
        { m_hWnd, WM_APP_COMMAND_5, 5, _T("WM_APP_COMMAND5") },
    };
该表有五项,但您可以根据需要添加任意数量的条目。每项有四个元素:第一个是要接收消息的窗口的 HWND;第二个是通过 SendMessage() 发送给窗口的数字消息编号;第三个是用户定义的数据,该数据将返回在 wParam 成员中;第四个是用于将表条目与 HTML 代码关联的字符串。

设置此表后,通过调用 SetAppCommands() 将其传递给 CXBreadCrumbBarM 对象。

    m_ccb[2].SetAppCommands(AppCommands, 
        sizeof(AppCommands)/sizeof(AppCommands[0]));

如果面包屑是动态变化的,您可以根据需要多次调用 SetAppCommands()

步骤 5:跟踪鼠标移动

由于 CXBreadCrumbBar 是无窗口的,您必须添加代码将鼠标移动转发给 CXBreadCrumbBar。这是演示应用程序中的 OnMouseMove() 函数

//=============================================================================
void CXBreadCrumbBarTestDlg::OnMouseMove(UINT nFlags, CPoint point) 
//=============================================================================
{
    for (int i = 0; i < 3; i++)
        m_ccb[i].RelayMouseMove(m_hWnd);

    CDialog::OnMouseMove(nFlags, point);
}

步骤 6:处理鼠标单击

同样,由于 CXBreadCrumbBar 是无窗口的,您必须添加代码将单击转发给 CXBreadCrumbBar。这是演示应用程序中的 OnLButtonUp() 函数

//=============================================================================
void CXBreadCrumbBarTestDlg::OnLButtonUp(UINT nFlags, CPoint point) 
//=============================================================================
{
    for (int i = 0; i < 3; i++)
    {
        if (m_ccb[i].RelayClick(m_hWnd))
            break;
    }

    CDialog::OnLButtonUp(nFlags, point);
}

参考文献

有关面包屑导航的信息链接

我用于演示应用程序的文章链接

修订历史

版本 1.0 - 2007 年 8 月 7 日

  • 首次公开发布

用法

本软件已发布至公共领域。您可以随意使用它,但不得出售此源代码。如果您修改或扩展它,请考虑将新代码发布到此处供大家共享。本软件按“原样”提供,不附带任何明示或暗示的保证。对于本软件可能造成的任何损害或业务损失,本人概不负责。

© . All rights reserved.