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

控件消息栏

starIconstarIconstarIconstarIconstarIcon

5.00/5 (45投票s)

2008年10月8日

CPOL

10分钟阅读

viewsIcon

94992

downloadIcon

3430

在几乎任何现有 Windows 控件中添加消息栏的代码。

引言

我最近需要在一个列表中添加一条消息,当某些通常会显示在列表中的项目由于访问权限而被排除时。我想要一个可以轻松添加到控件中的消息栏,其外观类似于大多数网络浏览器中弹出窗口和其他内容被阻止时看到的消息栏。

我的操作方法

我想要在列表视图控件的顶部显示消息,但我不想为了在控件上方放置一个兄弟控件而调整控件的大小,所以我决定通过拦截控件中的 WM_NCCALCSIZE 消息并在主客户端区域上方的非客户端区域留出足够的空间来绘制消息。我还希望为用户提供一种关闭消息的方法,所以我需要在消息栏区域内响应 WM_NCLBUTTONDOWN 等消息。

由于不想将自己限制为只能在列表视图控件中使用消息栏,我研究了如何使其足够通用以轻松添加到任何控件。我的第一次尝试是创建一个类,我将从中共同继承一些 MFC 类,从而为我的任何控件类添加消息栏支持。这主要缺点是我需要为每个想要拥有消息栏的控件提供一个从标准 MFC 类派生的类。因此,我想要一种允许我简单地将功能添加到任何现有控件的方法。

通过子类化向控件添加功能很简单,但当控件已经子类化时,不可能第二次子类化控件。研究这个问题让我读到了 Ralph Varjabedian 关于 双重子类化 的文章,该文章允许先前子类化的控件再次子类化,这正是我所需要的。

一旦控件被(双重)子类化以提供消息栏功能,消息栏代码就能够拦截窗口消息,从而修改控件的非客户端区域以提供消息栏的空间。此外,消息栏可以拦截鼠标消息,以便程序可以响应消息栏上的点击以显示菜单或执行任何其他操作。

某些控件会自行使用非客户端区域,这可能会干扰消息栏的计算区域。最常见的例子是列表视图控件,它使用非客户端区域来放置列标题。幸运的是,列表控件在计算标题大小和位置时会发送一条消息,因此消息栏会拦截此消息以调整标题控件使用的区域,从而使其保持自己的空间。

如何使用

使用 CCtrlMessageBar 类很简单。按照以下步骤将其添加到现有项目

  1. 将源文件(CtrlMessageBar.cppCtrlMessageBar.h)放入您希望使用的目录后,将文件添加到您的 Visual Studio 项目中。
  2. 确保您有一个要添加消息栏的控件。我假设这是一个列表控件,变量名为 m_list
  3. 在您的对话框类中添加一个 CCtrlMessageBar 变量。我假设它叫做 m_barList
  4. 如果您还没有,请在您的对话框类中添加一个 WM_INITDIALOG 的处理程序,并向其中添加以下代码以添加消息栏并设置其文本
  5. m_barList.Attach(m_list);
    m_barlist.SetText(_T("This is my message bar text"))
  6. 您可以通过附加图像列表并设置要使用的图像索引来为栏设置图像
  7. CImageList imlMessageBar;
    ...
    
    m_barList.SetImageList(imlMessageBar);
    m_barList.SetImage(3);

这就是您开始所需要做的一切。有关更高级的选项,请参阅下面的功能或成员函数文档,或演示应用程序。

特点

控件中包含的一些您可能会觉得有用的功能如下

栏可以有图像

如上例所示,您可以选择为消息栏设置图像列表,然后指定该图像列表中的图像以显示在栏的左上角。

文本可以设置为换行

通过调用 SetWrapText 方法,可以将过长无法适应栏矩形的文本设置为换行,从而增加栏的高度以适应文本。如果未启用换行,则文本会以省略号截断。

如果文本被截断,则在工具提示中显示栏文本

如果文本过长无法适应消息栏,并且您没有设置换行,则文本会以省略号 (...) 向右截断,在这种情况下,将鼠标悬停在栏上会以工具提示显示整个文本。这可以在文本可能过长但您不希望增加栏的高度的情况下使用。

栏背景和文本可以设置为任何颜色

默认情况下,栏使用系统工具提示背景颜色作为其背景,使用系统工具提示文本颜色作为文本。这些以及高亮颜色(见下文)可以通过向 SetColours 方法指定新颜色来覆盖。将任何颜色指定为 CLR_DEFAULT 会使其使用默认颜色。

栏可以设置为在鼠标悬停时“点亮”

您可以通过调用 SetHighlightOnMouseOver 方法,使栏在用户将鼠标移到其上方时“点亮”。高亮背景和文本颜色默认为系统高亮颜色,但可以通过调用 SetColours 方法(见上文)进行设置。

可以将栏设置为调整其父级以腾出空间

通常,将栏附加到控件会调整控件的客户端区域以腾出空间,同时保持控件的窗口大小不变。虽然这对于大多数控件来说可能很理想,但有时需要相反的情况,例如,将栏添加到对话框的顶部。通过使用 TRUE 调用 SetResize 方法,栏将调整窗口大小以使栏适应,同时保持窗口客户端区域的大小不变。

可以调用自定义菜单

默认情况下,单击或右键单击消息栏会显示一个菜单,为用户提供一个选项,即隐藏栏。通过指定回调函数,您可以拦截此行为并提供自己的菜单,或执行任何其他操作,或允许默认行为。演示应用程序中包含一个此类回调函数的示例,在子类化编辑控件的 CMBEdit 类中(但请注意,不需要子类化控件即可提供回调函数)。

参考

函数

CCtrlMessageBar 类的公共成员函数如下

  • CCtrlMessageBar();
  • 标准空构造函数。

  • virtual ~CCtrlMessageBar();
  • 标准虚析构函数。

  • BOOL Attach(CWnd* pCtrl);
  • 用于将消息栏附加到由 pCtrl 指定的控件。成功返回 TRUE,否则返回 FALSE

  • BOOL Attach(CWnd& ctrl)
  • 用于将消息栏附加到由 ctrl 指定的控件。成功返回 TRUE,否则返回 FALSE

  • BOOL Attach(CWnd* pDlg, UINT nID);
  • 用于将消息栏附加到由 pDlg 指定的对话框上由 nID 指定的控件。成功返回 TRUE,否则返回 FALSE

  • CWnd* Detach();
  • 从控件中分离消息栏。返回消息已附加到的控件。

  • CWnd* GetCtrl() const
  • 返回消息栏所附加到的控件。

  • BOOL IsAttached() const
  • 返回消息栏当前是否已附加到控件。

  • void SetImageList(CImageList* piml);
  • 设置包含消息栏要使用的图像的图像列表。

  • virtual void SetText(LPCTSTR lpszText, UINT nImage = -1, BOOL bShow = TRUE);
  • 设置消息栏的当前文本,以及可选的图像索引。如果 nImage 为 -1,则不显示图像。bShow 参数确定是否立即显示消息栏。

  • virtual CString GetText() const;
  • 返回当前消息栏文本。

  • virtual void Show(BOOL bShow = TRUE);
  • 显示或隐藏消息栏。

  • virtual BOOL IsShown() const;
  • 返回消息栏当前是否显示。

  • void SetImage(UINT nImage, BOOL bShow = TRUE);
  • 指定图像列表中要在消息栏上显示的图像的索引。

  • UINT GetImage() const;
  • 返回消息栏上当前显示的图像的索引。

  • CRect GetRect(BOOL bDrawing = FALSE) const;
  • 返回消息栏在窗口坐标中的大小和位置。

  • CRect GetCloseButtonRect(CRect& rc) const;
  • 返回消息栏关闭按钮的大小和位置。

  • UINT GetMessageHeight() const;
  • 返回消息栏的高度,以像素为单位。

  • void SetCloseButton(BOOL bShow = TRUE);
  • 设置是否在消息栏上显示关闭按钮。

  • BOOL GetCloseButton() const
  • 返回消息栏上是否显示关闭按钮。

  • void SetWrapText(BOOL bWrap = TRUE)
  • 设置消息栏文本是否应换行(如果过长)以适应栏的宽度。如果文本不换行且过长,则文本将以省略号 (...) 截断。

  • BOOL GetWrapText() const
  • 返回文本是否会在过长时换行以适应栏的宽度。

  • void SetHighlightOnMouseOver(BOOL bHighlight = TRUE)
  • 设置当用户的鼠标移到其上方时,栏是否应“点亮”。

  • BOOL GetHighlightOnMouseOver() const
  • 返回控件是否设置为当用户的鼠标移到其上方时“点亮”。

  • void SetColours(COLORREF crBackgroundNormal = CLR_DEFAULT, COLORREF crTextNormal = CLR_DEFAULT, COLORREF crBackgroundHilite = CLR_DEFAULT, COLORREF crTextHilite = CLR_DEFAULT);
  • 设置用于消息栏各个方面的颜色。为任何颜色指定 CLR_DEFAULT 会导致栏使用其自己的默认颜色。

  • void GetColours(COLORREF& crBackgroundNormal, COLORREF& crTextNormal, COLORREF& crBackgroundHilite, COLORREF& crTextHilite) const;
  • 用于获取消息栏各个方面当前使用的颜色。

  • void SetResize(BOOL bResize = TRUE)
  • 指定托管消息栏的窗口是否应调整大小以适应消息栏。正常行为是缩小窗口的客户端区域以为消息栏腾出空间,同时保持窗口的大小和位置不变。此选项在向对话框或其他窗口添加消息栏时很有用,此时客户端区域不应调整大小,但整体窗口大小应增加。

  • BOOL GetResize() const
  • 返回消息栏的宿主窗口是否会调整大小以适应消息栏。

  • static CCtrlMessageBar* GetMessageBarCtrl(CWnd* pCtrl);
  • 返回指向当前附加到指定 Windows 控件的 CCtrlMessageBar 的指针。

  • void SetShowMenuCallback(PFNSHOWMENUCALLBACK pfnShowMenuCallback)
  • 设置一个回调函数以显示上下文菜单。有关详细信息,请参阅下面的 PFNSHOWMENUCALLBACK 类型文档。

Types

  • typedef BOOL (*PFNSHOWMENUCALLBACK)(CCtrlMessageBar* pBar, CWnd* pCtrl, UINT nHitTest, CPoint point);
  • 用于显示上下文菜单的回调函数的类型。当用户在消息栏上左键或右键单击时,会调用回调函数。

    pBar 参数是被点击的消息栏。pCtrl 参数是托管消息栏的控件。nHitTest 是命中测试代码,指定用户点击的位置,将是 HTMESSAGEBAR 表示栏的主体,或 HTMESSAGEBARCLOSE 表示关闭按钮。point 参数指定用户在点击时的鼠标位置,以窗口坐标表示。

    该函数可以显示并作用于上下文菜单,也可以选择简单地允许默认处理。返回 FALSE 以执行默认处理,否则返回 TRUE

致谢和参考

历史

版本 1.0 - 2008 年 10 月 23 日

  • 向文章文本添加了额外信息。

版本 1.0 - 2008 年 10 月 08 日

  • First version.
© . All rights reserved.