通知和通知区域

通知区域是任务栏的一部分,它提供通知和状态的临时源。 它还可用于显示桌面上没有状态的系统和程序功能的图标,例如电池电量、音量控制和网络状态。 通知区域在历史上称为系统托盘或状态区域。

本主题包含以下各节:

通知和通知区域指南

有关使用通知和通知区域的最佳做法,请参阅 Windows 用户体验交互指南的通知通知区域部分。 目标是通过适当使用通知来提供用户权益,而不会让人恼火或分心。

通知区域不适用于必须立即执行的关键信息。 它也不用于快速程序或命令访问。 从 Windows 7 开始,大部分功能都是通过应用程序的任务栏按钮实现的。

Windows 7 允许用户在选择时禁止来自应用程序的所有通知,因此经过深思熟虑的通知设计并使用将允许用户继续显示这些通知。 通知是中断;确保它们值得。

Windows 7 引入了“静默时间”的概念。 静默时间定义为新用户首次登录其帐户后的第一小时或操作系统升级或干净安装之后的第一小时。 这一次被搁置,允许用户探索和熟悉新环境,而不会分散通知的干扰。 在此期间,不应发送或显示大多数通知。 例外情况包括用户期望在响应用户操作时看到的反馈,例如,当用户插入 USB 设备或打印文档时。 本主题稍后将讨论有关安静时间的 API 细节。

创建和显示通知

本主题的其余部分概述了向用户显示应用程序通知时要遵循的基本过程。

  1. 添加通知图标
  2. 定义 NOTIFYICONDATA 版本
  3. 定义通知外观和内容
  4. 检查用户状态
  5. 显示通知
  6. 删除图标

添加通知图标

若要显示通知,必须在通知区域中具有图标。 在某些情况下(如 Microsoft Communicator 或电池电量),该图标将已经存在。 但是,在其他很多情况下,只要需要显示通知,你才会向通知区域添加一个图标。 在任一情况下,这都是使用 Shell_NotifyIcon 函数完成的 Shell_NotifyIcon允许在通知区域中添加、修改或删除图标。

包含三个图标的通知区域

将图标添加到 Windows 7 上的通知区域时,默认情况下会将其添加到通知区域的溢出部分。 此区域包含处于活动状态但无法在通知区域中可见的通知区域图标。 只有用户可以将图标从溢出提升到通知区域,但在某些情况下,系统可以暂时将图标提升到通知区域作为简短预览(不到一分钟)。

注意

用户应该有他们希望在通知区域中看到的图标的最终说明。 在通知区域中安装非暂时性图标之前,应要求用户获得权限。 还应提供选项(通常为快捷菜单)从通知区域删除图标。

 

调用中发送的 NOTIFYICONDATA 结构Shell_NotifyIcon包含指定通知区域图标和通知本身的信息。 以下是特定于可以通过 NOTIFYICONDATA 设置的通知区域图标本身的项目。

  • 从中获取图标的资源。
  • 图标的唯一标识符。
  • 图标工具提示的样式。
  • 通知区域中图标的状态(隐藏、共享或两者)。
  • 与图标关联的应用程序窗口的句柄。
  • 一个回调消息标识符,该标识符允许图标与关联的应用程序窗口传达图标边界矩形和气球通知中发生的事件。 可以通过Shell_NotifyIconGetRect检索图标的边界矩形。

可以通过两种方式标识通知区域中的每个图标:

  • 图标在注册表中声明的 GUID。 这是 Windows 7 及更高版本上的首选方法。
  • 与通知区域图标关联的窗口的句柄,以及应用程序定义的图标标识符。 此方法在 Windows Vista 及更早版本上使用。

通知区域中的图标可以具有工具提示。 工具提示可以是标准工具提示(首选)或应用程序绘制的弹出 UI。 虽然不需要工具提示,但建议使用该工具提示。

通知区域图标应具有高 DPI 感知性。 应用程序应在其资源文件中同时提供 16x16 像素图标和 32x32 图标,然后使用 LoadIconMetric 确保正确加载和缩放正确的图标。

负责通知区域图标的应用程序应处理该图标的鼠标单击。 当用户右键单击图标时,它应显示普通快捷菜单。 但是,单击鼠标左键的结果因图标的功能而异。 它应显示用户期望在最适合该内容的形式中看到的内容,即弹出窗口、对话框或程序窗口本身。 例如,它可以显示状态图标的状态文本或音量控件的滑块。

单击结果的弹出窗口或对话框的位置应放置在通知区域中单击的坐标附近。 使用 CalculatePopupWindowPosition 确定其位置。

该图标可以添加到通知区域,而无需显示通知,只需定义特定于图标的 NOTIFYICONDATA 成员(如上所述)并调用Shell_NotifyIcon,如下所示:

NOTIFYICONDATA nid = {};
// Do NOT set the NIF_INFO flag.
...                    
Shell_NotifyIcon(NIM_ADD, &nid);

还可以将图标添加到通知区域,并在一次调用 Shell_NotifyIcon中显示通知。 为此,请继续阅读本主题中的说明。

定义 NOTIFYICONDATA 版本

随着 Windows 的推进, NOTIFYICONDATA 结构已扩展,以包含更多成员来定义更多功能。 常量用于声明要与通知区域图标一起使用的 NOTIFYICONDATA 版本,以允许向后兼容。 除非有令人信服的理由这样做,否则强烈建议使用 Windows Vista 中引入的NOTIFYICON_VERSION_4版本。 此版本提供完整的可用功能,包括通过已注册的 GUID、优越的回调机制和更好的辅助功能来识别通知区域图标的首选功能。

通过以下调用设置版本:

NOTIFYICONDATA nid = {};
... 
nid.uVersion = NOTIFYICON_VERSION_4;
// Add the icon
Shell_NotifyIcon(NIM_ADD, &nid);
// Set the version
Shell_NotifyIcon(NIM_SETVERSION, &nid);

请注意,对Shell_NotifyIcon的此调用不显示通知。

定义通知外观和内容

通知是特殊类型的气球工具提示控件。 它包含标题、正文文本和图标。 与窗口一样,它的右上角有一个 “关闭 ”按钮。 它还包含一个选项按钮,用于打开控制面板中的“通知区域图标”项,该按钮允许用户显示或隐藏图标或仅显示没有图标的通知。

通知气球的屏幕截图,指示电池电量较低

调用中发送的 NOTIFYICONDATA 结构Shell_NotifyIcon包含指定通知区域图标和通知气球本身的信息。 以下是特定于可通过 NOTIFYICONDATA 设置的通知的项。

  • 通知气球中显示的图标,由通知类型指定。 可以指定图标的大小以及自定义图标。
  • 通知标题。 此标题的英语长度应最多为 48 个字符(以适应本地化)。 标题是通知的第一行,通过字体大小、颜色和粗细来分开设置。
  • 通知正文中使用的文本。 此文本应最多为英语 200 个字符(以适应本地化)。
  • 如果无法立即显示通知,是否应放弃通知。
  • 通知的超时。 Windows Vista 及更高版本中忽略此设置,以支持系统范围的辅助功能超时设置。
  • 通知是否应遵循静默时间,通过 NIIF_RESPECT_QUIET_TIME 标志设置。

注意

IUserNotification 和 IUserNotification2 接口是用于Shell_NotifyIcon组件对象模型 (COM) 包装器。 但是,目前,它们不提供直接通过 Shell_NotifyIcon 提供的完整NOTIFYICON_VERSION_4功能,包括使用 GUID 标识通知区域图标。

 

检查用户状态

系统使用 SHQueryUserNotificationState 函数来检查用户是安静时间、远离计算机还是处于不中断状态(如演示文稿模式)。 系统是否显示通知取决于此状态。

注意

如果应用程序使用的是不使用 Shell_NotifyIconIUserNotification 或 IUserNotification2 的自定义通知方法,则它应始终显式调用 SHQueryUserNotificationState 来确定它是否应在该时间显示通知 UI。

 

当用户离开时发送的通知将排队等待显示,但由于你不知道用户何时返回或通知何时仍然有效,因此你可能会考虑稍后重新发送通知。

在安静时间发送的通知将被丢弃为未分配。 设计准则要求所有通知都将被忽略。 他们不应要求立即执行用户操作。 因此,没有通知如此重要,因此它应该覆盖安静时间。

显示通知

设置 NOTIFYICONDATA 版本并在 NOTIFYICONDATA 结构中定义通知后,调用Shell_NotifyIcon以显示图标。

  • 如果通知区域图标不存在,请调用 Shell_NotifyIcon 添加图标。 针对暂时和非暂时性图标执行此操作。

    NOTIFYICONDATA nid = {};
    ...                    
    Shell_NotifyIcon(NIM_ADD, &nid);
    
  • 如果通知区域图标已存在,请调用 Shell_NotifyIcon 修改图标。

    NOTIFYICONDATA nid = {};
    ...                    
    Shell_NotifyIcon(NIM_MODIFY, &nid);
    

以下代码演示了设置 NOTIFYICONDATA 数据并通过Shell_NotifyIcon发送数据的示例。 请注意,此示例通过 GUID 标识通知图标(在 Windows 7 中首选)。

// Declare NOTIFYICONDATA details. 
    // Error handling is omitted here for brevity. Do not omit it in your code.
    
    NOTIFYICONDATA nid = {};
    nid.cbSize = sizeof(nid);
    nid.hWnd = hWnd;
    nid.uFlags = NIF_ICON | NIF_TIP | NIF_GUID;
    
    // Note: This is an example GUID only and should not be used.
    // Normally, you should use a GUID-generating tool to provide the value to
    // assign to guidItem.
    static const GUID myGUID = 
    {0x23977b55, 0x10e0, 0x4041, {0xb8, 0x62, 0xb1, 0x95, 0x41, 0x96, 0x36, 0x69}};
    nid.guidItem = myGUID;
    
    // This text will be shown as the icon's tooltip.
    StringCchCopy(nid.szTip, ARRAYSIZE(nid.szTip), L"Test application");
    
    // Load the icon for high DPI.
    LoadIconMetric(hInst, MAKEINTRESOURCE(IDI_SMALL), LIM_SMALL, &(nid.hIcon));
    
    // Show the notification.
    Shell_NotifyIcon(NIM_ADD, &nid) ? S_OK : E_FAIL;

删除图标

若要删除图标(例如,仅将图标临时添加到广播通知),请调用 Shell_NotifyIcon,如下所示。 此调用中只需要标识图标的最小 NOTIFYICONDATA 结构。

NOTIFYICONDATA nid = {};
...                    
Shell_NotifyIcon(NIM_DELETE, &nid);

注意

卸载应用程序后,其通知区域图标仍可向用户显示为控制面板中最多七天的“通知区域图标”页中的选项。 但是,所做的任何更改都不起作用。

 

SDK 示例

有关使用 Shell_NotifyIcon的完整示例,请参阅 Windows 软件开发工具包 (SDK) 中的 NotificationIcon 示例。

Shell_NotifyIcon

Shell_NotifyIconGetRect

NOTIFYICONDATA

SHQueryUserNotificationState

IUserNotification

IUserNotification2

任务栏

任务栏扩展