通知和通知区域

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

本主题包含以下各节:

通知和通知区域指南

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

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

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

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

创建和显示通知

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

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

添加通知图标

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

包含三个图标的通知区域

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

注意

用户应该对想要在其通知区域中看到的图标拥有最终决定权。 在通知区域中安装非暂时性图标之前,应要求用户提供权限。 通常,应为其提供选项 (,尽管其快捷菜单) 从通知区域中删除图标。

 

调用 Shell_NotifyIcon 时发送的 NOTIFYICONDATA 结构包含指定通知区域图标和通知本身的信息。 下面是特定于通知区域图标本身的项,可通过 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 的此调用不显示通知。

定义通知外观和内容

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

指示电池电量不足的通知气球的屏幕截图

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

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

注意

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

 

检查用户状态

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

注意

如果应用程序使用的自定义通知方法不使用 Shell_NotifyIconIUserNotificationIUserNotification2,则它应始终显式调用 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

任务栏

任务栏扩展