任务栏

Windows接口包括一个名为任务栏的特殊应用程序桌面工具栏。 可以使用任务栏在打开的窗口和启动新应用程序之间切换等任务。

注意

有关从 Windows 7 开始对任务栏所做的更改的信息,请参阅任务栏扩展

 

本主题包含以下各节:

关于任务栏

任务栏包括以下内容:

  • "开始"菜单菜单
  • 快速启动栏 (Windows Vista 及更早版本仅)
  • 任务栏按钮
  • 工具栏 (可选)
  • 通知区域

"开始"菜单菜单包含可以访问程序、文档和设置的命令。 这些命令包括所有程序文档控制面板游戏帮助和支持关闭搜索程序和文件

Windows早期版本中的"开始"菜单包含“查找运行”等项,这些功能包含在 Windows Vista 及更高版本中的搜索程序和文件中

快速启动栏在早于 Windows 7 的 Windows 版本中提供,其中包含应用程序的快捷方式。 Windows提供默认条目,例如Windows Internet Explorer,用户可以添加他们选择的任何进一步快捷方式。 此区域中的图标响应一键。 在 Windows 7 及更高版本中,此功能包含在任务栏按钮中。

每当应用程序创建未拥有窗口(即没有父窗口且具有适当扩展样式位的窗口)时,Shell 将按钮放在任务栏上, (请参阅“ 管理任务栏按钮”,下方) 。 若要切换到窗口,用户单击其窗口按钮。 截至 Windows 7,此功能已大大扩展。 有关详细信息,请参阅 任务栏扩展

应用程序可以将图标放在通知区域中,以指示操作的状态或通知用户有关事件的信息。 例如,应用程序可能会将打印机图标放在通知区域中,以显示打印作业正在进行中。 但是,在 Windows 7 及更高版本中,通知区域之前提供的一些信息应通过应用程序的任务栏按钮提供。 如果任务栏水平) 或底部 (任务栏是垂直) ,则通知区域位于任务栏的右边缘 (。 有关详细信息,请参阅 通知和通知区域

如果选中该选项,通知区域还会显示当前时间。 此选项的找到方式如下:

  • Windows 7 及更高版本:通知区域图标控制面板应用程序 (还可以通过通知区域属性) 访问“通知区域图标”页面上的“时钟”下拉列表。
  • Windows Vista:任务栏的“通知区域”页中的“时钟”复选框,"开始"菜单菜单属性窗口。
  • Windows XP任务栏和"开始"菜单菜单属性窗口中的“显示时钟”复选框。

用户可以右键单击任务栏以显示快捷菜单。 快捷菜单包括用于级联窗口、堆栈窗口、并行显示窗口、显示桌面、启动任务管理器和设置任务栏属性的命令。 快捷菜单还提供从任务栏中添加或删除一组工具栏的选项。 可以通过在CATID_DeskBand类别下注册新工具栏到此菜单。 有关详细信息,请参阅 实现带状对象。 请注意,从 Windows 7 开始,任务栏和通知区域具有单独的快捷菜单。 这些快捷菜单共享某些选项,例如窗口排列,并添加其他选项。

任务栏显示选项

任务栏支持两个显示选项:自动隐藏,并且仅在 Windows Vista 及更早版本中,Always On top (任务栏始终处于此模式,Windows 7 及更高版本) 。 若要设置这些选项,用户必须打开任务栏快捷菜单,单击“ 属性”,然后选择或清除 “自动隐藏任务栏 ”复选框或 “将任务栏保留在其他窗口”复选框顶部 。 若要检索这些显示选项的状态,请使用 ABM_GETSTATE 消息。 如果希望在这些显示选项的状态发生更改时收到通知,请在窗口过程中处理 ABN_STATECHANGE 通知消息。 若要更改这些显示选项的状态,请使用 ABM_SETSTATE 消息。

工作区是任务栏未遮盖的屏幕部分。 若要检索工作区域的大小,请使用设置SPI_GETWORKAREA值调用 SystemParametersInfo 函数。 若要检索描述任务栏位置的矩形坐标,请使用 ABM_GETTASKBARPOS 消息。

可以通过使用 SetWindowPos 显式设置与屏幕大小相等的窗口矩形大小来覆盖任务栏。 对于 Windows 2000 系统或更高版本,窗口必须缺少WS_CAPTIONWS_THICKFRAME,否则窗口必须调整大小,使工作区覆盖整个屏幕。 同样对于这些系统而言,如果任务栏设置为Always On Top,则仅当应用程序是前台应用程序时,它才会保持隐藏状态。

向"开始"菜单菜单添加快捷方式

若要将项添加到 Microsoft Windows NT 4.0 上的“程序”子菜单、Windows 2000 及更高版本或Windows 95 或更高版本,请执行以下步骤。

  1. 使用 IShellLink 接口创建 shell 链接
  2. 使用 SHGetSpecialFolderLocation 获取 Programs 文件夹的 PIDL,传递 CSIDL_PROGRAMS
  3. 将 Shell 链接添加到“程序”文件夹。 还可以在“程序”文件夹中创建一个文件夹,并将链接添加到该文件夹。

管理任务栏按钮

每当应用程序创建不拥有的窗口时,Shell 会在任务栏上创建一个按钮。 若要确保窗口按钮放置在任务栏上,请使用 WS_EX_APPWINDOW 扩展样式创建一个未拥有的窗口。 若要防止将窗口按钮放置在任务栏上,请使用WS_EX_TOOLWINDOW扩展样式创建未拥有 窗口。 作为替代方法,可以创建隐藏窗口,并将此隐藏窗口设置为可见窗口的所有者。

仅当窗口的样式支持可见的任务栏按钮时,Shell 才会从任务栏中删除窗口的按钮。 如果要将窗口的样式动态更改为不支持可见任务栏按钮的窗口,必须首先通过调用具有SW_HIDE) ShowWindow 来隐藏窗口 (,更改窗口样式,然后显示窗口。

窗口按钮通常包含应用程序图标和标题。 但是,如果应用程序不包含系统菜单,则会在没有图标的情况下创建窗口按钮。

如果希望应用程序在窗口未处于活动状态时引起用户的注意,请使用 FlashWindow 函数告知用户消息正在等待。 此函数闪烁窗口按钮。 用户单击窗口按钮激活窗口后,应用程序可以显示消息。

修改任务栏的内容

版本 4.71 及更高版本的 Shell32.dll添加了修改任务栏内容的功能。 在应用程序中,现在可以添加、删除和激活任务栏按钮。 激活项目不会激活窗口;它显示任务栏上按下的项。

任务栏修改功能在组件对象模型 (COM) 对象 (CLSID_TaskbarList ) 中实现,该对象公开 ITaskbarList 接口 (IID_ITaskbarList) 。 必须调用 ITaskbarList::HrInit 方法来初始化对象。 然后,可以使用 ITaskbarList 接口的方法修改任务栏的内容。

在通知区域中添加、修改和删除图标

使用 Shell_NotifyIcon 函数从通知区域添加、修改或删除图标。 Shell_NotifyIcondwMessage 参数是任务栏的消息,指定要执行的操作。 pnid 参数是指向 NOTIFYICONDATA 结构的指针,用于标识图标并传递系统处理消息所需的任何其他信息。

可以使用通知区域图标执行以下操作。

  • 若要将图标添加到任务栏的通知区域,请使用 dwMessage 参数设置为NIM_ADD调用Shell_NotifyIconNOTIFYICONDATA 结构用于指定图标的句柄和标识符以及任何工具提示文本。 如果用户在任务栏属性中选择了 “显示时钟 ”复选框,系统会将图标置于时钟的左边。 否则,图标会显示在右侧或任务栏底部。 任何现有图标都移动到左侧,为新图标腾出空间。
  • 若要修改图标的信息,包括图标句柄、工具提示文本和回调消息标识符,请使用 dwMessage 设置为NIM_MODIFY调用Shell_NotifyIcon
  • 若要从通知区域删除图标,请使用 dwMessage 参数设置为NIM_DELETE调用Shell_NotifyIcon

完成用户界面操作后,通过将 dwMessage 设置为NIM_SETFOCUS调用Shell_NotifyIcon,将焦点返回到通知区域。 例如,当任务栏图标显示快捷菜单时,可以执行此操作,但用户通过按 ESCAPE 键取消它。

接收通知区域回调消息

应用程序通常将图标放在任务栏的通知区域中,用作状态指示器。 当用户执行鼠标操作时,可以提供其他信息,例如将鼠标指针移到图标上或单击图标。

系统通过发送与特定图标关联的应用程序定义的回调消息来通知鼠标和键盘事件。 这样,系统就可以在用户单击图标或按键选择应用程序时通知应用程序。

将图标添加到任务栏时,可以定义图标的回调消息。 回调消息标识符是在使用 NIM_ADD 传递的 NOTIFYICONDATA 结构的 uCallbackMessage 成员中指定的。 事件发生时,系统将回调消息发送到 由 hWnd 成员指定的窗口的窗口过程。 消息的 wParam 参数包含发生事件的任务栏图标的标识符。 lParam 参数保存与事件关联的鼠标或键盘消息。 例如,当鼠标指针移动到任务栏图标上时, lParam 包含 WM_MOUSEMOVE

可以按如下所示汇总各种鼠标事件的结果:

  • 当用户将鼠标指针移到图标上时,系统会显示 NOTIFYICONDATA 中指定的工具提示文本。
  • 当用户单击图标时,应用程序会收到 WM_LBUTTONDOWN 通知。
  • 当用户右键单击图标时,应用程序会收到 WM_RBUTTONDOWN 通知。
  • 当用户双击图标时,应用程序会收到 WM_LBUTTONDBLCLK 通知。

通常,单击图标会导致应用程序显示具有其他信息的窗口,右键单击显示快捷菜单,然后双击执行默认快捷菜单命令。

有关如何更改与通知区域图标关联的工具提示文本的示例,请参阅 状态栏图标的气球工具提示

与在 Windows NT 4.0、Windows 95 和 Windows 98 上找到的早期 Shell 版本不同,Shell 句柄 5.0 及更高版本Shell_NotifyIcon鼠标和键盘事件。 不同之处如下:

  • 如果用户使用键盘请求通知图标的快捷菜单,版本 5.0 Shell 会将关联的应用程序发送 WM_CONTEXTMENU 消息。 早期版本发送 WM_RBUTTONDOWNWM_RBUTTONUP 消息。
  • 如果用户选择键盘的通知图标并使用空格键或 ENTER 键激活该图标,则版本 5.0 Shell 会将关联的应用程序发送 NIN_KEYSELECT 通知。 早期版本发送 WM_RBUTTONDOWNWM_RBUTTONUP 消息。
  • 如果用户选择带有鼠标的通知图标并使用 ENTER 键激活该图标,则版本 5.0 Shell 会将关联的应用程序发送 NIN_SELECT 通知。 早期版本发送 WM_RBUTTONDOWNWM_RBUTTONUP 消息。
  • 如果用户将鼠标指针传递到与气球工具提示关联的图标上,则版本 6.0 Shell (Windows XP) 发送以下消息。
      • NIN_BALLOONSHOW - 当显示气球 (气球排队时发送) 。
      • NIN_BALLOONHIDE - 当气球消失时发送,例如,删除图标时。 如果因超时或鼠标单击而关闭气球,则不会发送此消息。
      • NIN_BALLOONTIMEOUT - 由于超时而关闭气球时发送。
      • NIN_BALLOONUSERCLICK - 由于鼠标单击而关闭气球时发送。

可以通过调用设置为 NIM_SETVERSIONdwMessage 的 dwMessage 调用 Shell_NotifyIcon,选择 Shell 的行为方式。 设置 NOTIFYICONDATA 结构的 uVersion 成员,以指示是想要版本 5.0 还是预版本 5.0 行为。

任务栏创建通知

使用 Microsoft Internet Explorer 4.0 及更高版本,Shell 会通知应用程序任务栏已创建。 创建任务栏后,它会向 TaskbarCreated 字符串注册消息,然后将此消息广播到所有顶级窗口。 当任务栏应用程序收到此消息时,它应假定它添加的任何任务栏图标已被删除并再次添加它们。 此功能通常仅适用于在 Shell 启动时已运行的服务。 以下示例演示了一种非常简化的方法来处理此情况。

在Windows 10,当主显示器的 DPI 发生更改时,任务栏还会广播此消息。

LRESULT CALLBACK WndProc(HWND hWnd, 
                         UINT uMessage, 
                         WPARAM wParam, 
                         LPARAM lParam)
{
    static UINT s_uTaskbarRestart;

    switch(uMessage)
    {
        case WM_CREATE:
            s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
            break;
        
        default:
            if(uMessage == s_uTaskbarRestart)
                AddTaskbarIcons();
            break;
    }

    return DefWindowProc(hWnd, uMessage, wParam, lParam);
}

使用任务栏

本部分包括演示如何向任务栏通知区域添加图标的示例,以及如何处理任务栏图标的回调消息。

在通知区域中添加和删除任务栏图标

通过填写 NOTIFYICONDATA 结构,然后将结构传递给Shell_NotifyIcon,将 dwMessage 设置为NIM_ADD,将图标添加到任务栏通知区域。 结构成员必须指定要添加图标的窗口的句柄,以及图标标识符和图标句柄。 还可以为图标指定工具提示文本。 如果需要接收图标的鼠标消息,请指定系统应用来将消息发送到窗口过程的回调消息的标识符。

以下示例中的函数演示如何将图标添加到任务栏。

// MyTaskBarAddIcon - adds an icon to the notification area. 
// Returns TRUE if successful, or FALSE otherwise. 
// hwnd - handle to the window to receive callback messages 
// uID - identifier of the icon 
// hicon - handle to the icon to add 
// lpszTip - tooltip text 

BOOL MyTaskBarAddIcon(HWND hwnd, UINT uID, HICON hicon, LPSTR lpszTip) 
{ 
    BOOL res; 
    NOTIFYICONDATA tnid; 
 
    tnid.cbSize = sizeof(NOTIFYICONDATA); 
    tnid.hWnd = hwnd; 
    tnid.uID = uID; 
    tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; 
    tnid.uCallbackMessage = MYWM_NOTIFYICON; 
    tnid.hIcon = hicon; 
    if (lpszTip) 
        hr = StringCbCopyN(tnid.szTip, sizeof(tnid.szTip), lpszTip, 
                           sizeof(tnid.szTip));
        // TODO: Add error handling for the HRESULT.
    else 
        tnid.szTip[0] = (TCHAR)'\0'; 
 
    res = Shell_NotifyIcon(NIM_ADD, &tnid); 
 
    if (hicon) 
        DestroyIcon(hicon); 
 
    return res; 
}

若要从任务栏通知区域删除图标,请填充 NOTIFYICONDATA 结构,并使用 dwMessage 设置为NIM_DELETE调用Shell_NotifyIcon。 删除任务栏图标时,仅指定结构的 cbSizehWnduID 成员。 例如:

// MyTaskBarDeleteIcon - deletes an icon from the notification area. 
// Returns TRUE if successful, or FALSE otherwise. 
// hwnd - handle to the window that added the icon. 
// uID - identifier of the icon to delete. 

BOOL MyTaskBarDeleteIcon(HWND hwnd, UINT uID) 
{ 
    BOOL res; 
    NOTIFYICONDATA tnid; 
 
    tnid.cbSize = sizeof(NOTIFYICONDATA); 
    tnid.hWnd = hwnd; 
    tnid.uID = uID; 
         
    res = Shell_NotifyIcon(NIM_DELETE, &tnid); 
    return res; 
}

接收鼠标事件

如果为任务栏图标指定回调消息,则每当图标的边界矩形中发生鼠标事件时,系统就会将消息发送到应用程序。 消息的 wParam 参数指定任务栏图标的标识符,消息的 lParam 参数指定系统在鼠标事件后生成的消息。

以下示例中的函数来自将电池和打印机图标添加到任务栏的应用程序。 应用程序在收到回调消息时调用函数。 该函数确定用户是否已单击其中一个图标,如果单击发生,则调用应用程序定义的函数以显示状态信息。

// On_MYWM_NOTIFYICON - processes callback messages for taskbar icons. 
// wParam - first message parameter of the callback message. 
// lParam - second message parameter of the callback message. 

void On_MYWM_NOTIFYICON(WPARAM wParam, LPARAM lParam) 
{ 
    UINT uID; 
    UINT uMouseMsg; 
 
    uID = (UINT) wParam; 
    uMouseMsg = (UINT) lParam; 
 
    if (uMouseMsg == WM_LBUTTONDOWN) 
    { 
        switch (uID) 
        { 
            case IDI_MYBATTERYICON: 
 
                // The user clicked the battery icon. Display the 
                // battery status. 
                ShowBatteryStatus(); 
                break; 
 
            case IDI_MYPRINTERICON: 
 
                // The user clicked the printer icon. Display the 
                // status of the print job. 
                ShowJobStatus(); 
                break; 
 
            default: 
                break; 
        } 
     } 

     return; 
 }