Exercise 1: Experiment with the New Windows 7 Taskbar Features

In this exercise, you will experiment with the new Windows 7 taskbar features. You will extend a showcase application that demonstrates the use of the new taskbar functionality to provide a taskbar overlay icon, progress bar, jump list, and thumbnail previews. Most of the application’s user interface is already implemented; you will need to fill in only the missing parts that interact with the Windows 7 taskbar using Visual C++ MFC (Microsoft Foundation Class Library).

To begin this exercise, open the TaskbarDemo_Starter\TaskbarDemo.sln solution (under the Source folder) using Visual Studio 2010.

Figure 2

Taskbar Concepts solution structure in Visual Studio 2010

Spend a minute or two exploring the header, source and resource files. Take a look at the various dialogs and main form. Take a few moments to build and run the application as well.

Task 1—Using Taskbar Overlay Icons

  1. In this task, you will toggle an overlay icon on the application’s taskbar button when a user clicks an icon button.
  2. Note that in MFC, you can set an overlay icon by using CFrameWnd::SetTaskbarOverlayIcon(). To clear the Taskbar overlay icon, pass NULL (0) to SetTaskbarOverlayIcon(). .
  3. In the TaskbarDemo\SourceFiles sub tree, open OverlayIconTab.cpp and look for the message handler for the Info overlay icon, COverlayIconTab::OnOverlayIconInfo(). We’ll use this message handler to add the code necessary to set the same icon in the button as a Taskbar overlay icon.
  4. Add the following code to COverlayIconTab::OnOverlayIconInfo():CMainFrame* mainFrm = dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());

    if (mainFrm)
    mainFrm->SetTaskbarOverlayIcon(IDI_ICON_INFO,L"Info");
  5. Compile and run the application.
  6. Press the information button .
  7. Notice that the display on the taskbar has changed, from the original , and now contains an overlay of the information button superimposed on it (see Figure 3 below).

    Figure 3

    Taskbar overlay icon shown

  8. Continue adding the necessary code for the rest of the icon overlay message handlers:void COverlayIconTab::OnOverlayIconQuestion()
    {
    // TODO: Add code to set question overlay icon
    CMainFrame* mainFrm = dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());
    if (mainFrm)
    mainFrm->SetTaskbarOverlayIcon(IDI_ICON_QUESTION, L"Question");
    }

    void COverlayIconTab::OnOverlayIconNoVolume()
    {
    // TODO: Add code to set no-volume overlay icon
    CMainFrame* mainFrm = dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());
    if (mainFrm)
    mainFrm->SetTaskbarOverlayIcon(IDI_ICON_NO_VOLUME,L"No Volume");
    }

    void COverlayIconTab::OnOverlayIconNone()
    {
    // TODO: Add code to clear overlay icon
    CMainFrame* mainFrm = dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());
    if (mainFrm)
    mainFrm->SetTaskbarOverlayIcon((HICON)0, L"");
    }
  9. Build and run the demo to test the remaining icon overlays.

Task 2—Using Taskbar Progress Bars

In this task, you will set the state and value of the application’s taskbar progress bar when the user selects the progress state from a combo box or changes the value by using a slider. MFC provides a number of methods to update the Taskbar progress bar’s value and status:

CFrameWnd::SetProgressBarRange()

CFrameWnd::SetProgressBarPosition()

CFrameWnd::SetProgressBarState()

  1. In the TaskbarDemo\SourceFiles sub tree:
    1. Open the file ProgressBarTab.cpp, and
    2. Look for the slider control’s message handler, CProgressBarTab::OnHScroll()
    3. Add the following code to update the Taskbar’s progress bar after the comment to add code to handle the slide bar change:
    UpdateData();
    CMainFrame* mainFrm = dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());
    mainFrm->SetProgressBarPosition(m_ProgressSliderValue);
  2. Build and run the application, and then:

    1. Go to the Progress Bar tab.
    2. Move the slider, and notice the movement on the application’s Taskbar button. You should see an output similar to Figure 4 below:

    Figure 4

    Slider bar and taskbar button progress indicators

  3. Now, we want to update the status of the progress bar whenever the relevant combo box option is updated, so we add the necessary code to the CProgressBarTab::OnCbnSelchangeProgressStatusCombo() event handler:CMainFrame* mainFrm = dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());

    switch (m_ProgrssStatusCombo.GetCurSel())
    {
    case 0 :
    mainFrm->SetProgressBarState(TBPF_NORMAL);
    break;
    case 1 :
    mainFrm->SetProgressBarState(TBPF_ERROR);
    break;
    case 2 :
    mainFrm->SetProgressBarState(TBPF_PAUSED);
    break;
    case 3 :
    mainFrm->SetProgressBarState(TBPF_INDETERMINATE);
    break;
    case 4 :
    mainFrm->SetProgressBarState(TBPF_NOPROGRESS);
    break;
    default:
    mainFrm->SetProgressBarState(TBPF_NORMAL);
    }
  4. Build and run the application, and then:

    1. Navigate to the Progress Bar tab, and
    2. Select a different style from the Progress Status Combo and then
    3. Move the progress slider. The progress bar state will be changed to the appropriate style; namely, the taskbar’s progress bar is red when the Progress Status is set to Error, the taskbar’s progress bar is green when the Progress Status is set to Normal (check out the other styles too):

    Figure 5

    Red progress bar indicating error

  5. Finally, this last step is optional, but you might want to reset the status combo to ‘Normal’ whenever the progress is updated from No Progress or Intermediate. To fix this, add the following at the end of CProgressBarTab::OnHScroll():if (m_ProgressSliderValue > 0 && m_ProgrssStatusCombo.GetCurSel() >= 3) // No progress or intermediate
    {
    // Set to something else other than no progress
    m_ProgrssStatusCombo.SetCurSel(0); // Normal
    }

Task 3—Using Taskbar Jump Lists

In this task, you will add the functionality to support adding known categories, custom categories, destinations, and tasks to the application’s jump list. To support this, MFC provides a new class, CJumpList, that allows manipulating the categories and entries on the Taskbar application’s JumpList.

  1. In the TaskbarDemo\SourceFiles sub tree, open the file JumpListTab.cpp and look for the implementation of CJumpListTab::UpdateRegistration(). This method executes another process to register needed file associations. The file association registration does not need to be in another process; however it was placed in another process to keep this tutorial application simple and focused.
    Note:
    We need to register the file associations because an application must be a registered file type handler for an item of that type to appear in its Jump List. It does not, however, need to be the default handler for that file type.
  2. Add the necessary code to update the registry and unregister jpg file associations in the corresponding message handlers:void CJumpListTab::OnRegisterFileType()
    {
    // TODO: Register file associations
    UpdateRegistration(TRUE);
    }

    void CJumpListTab::OnUnregisterFileType()
    {
    // TODO: Unregister file associations
    UpdateRegistration(FALSE);
    }
  3. The next steps will be used to add the necessary code to add the various Jump List items. Here’s a description for each:

    Figure 6

    Jump List item descriptions

  4. To append a known category to the Jump List, add this code to the CJumpListTab::OnAddKnownCategory() event handler:int curSel = m_knownCategoryCombo.GetCurSel();

    if (curSel < 0)
    {
    AfxMessageBox(L"Must select a known category above");
    return;
    }

    if (curSel == 0)
    {
    if (m_jumpList.AddKnownCategory(KDC_FREQUENT))
    m_JumpList_Display_Items.AddString(L"Known Category: Frequent");
    else
    AfxMessageBox(L"Failed to add Frequent Known Category");
    }
    else if (curSel == 1)
    {
    if (m_jumpList.AddKnownCategory(KDC_RECENT))
    m_JumpList_Display_Items.AddString(L"Known Category: Recent");
    else
    AfxMessageBox(L"Failed to add Recent Known Category");
    }
  5. To add a Destination in the Jump List, add this code in the CJumpListTab::OnAddDestination() event handler:UpdateData(); // Sync variables to UI controls

    if (m_destinationPath.IsEmpty() || m_destinationCategory.IsEmpty())
    {
    AfxMessageBox(L"Both Destination categeory and path must be added.");
    return;
    }

    if (!m_jumpList.AddDestination(m_destinationCategory, m_destinationPath))
    {
    AfxMessageBox(L"Failed to add destination.");
    }
    else
    {
    CString text = L"Destination: " + m_destinationPath;
    m_JumpList_Display_Items.AddString(text);
    }
  6. To add a new task in the Jump List, add this code in the CJumpListTab::OnAddTask() event handler:UpdateData(); // Sync variables to UI controls

    if (m_taskPath.IsEmpty() || m_taskTitle.IsEmpty())
    {
    AfxMessageBox(L"Both Task Path and Title must be added.");
    return;
    }

    if (!m_jumpList.AddTask(m_taskPath, m_taskArgs, m_taskTitle, m_taskIconPath, m_taskIconIndex))
    {
    AfxMessageBox(L"Failed to add Task.");
    }
    else
    {
    CString text = L"Task: " + m_taskTitle ;
    m_JumpList_Display_Items.AddString(text);
    }
  7. To allow the removal of all entries from the Jump List, add the following code to the CJumpListTab::OnClearAll() event handler:m_jumpList.ClearAll();
    m_JumpList_Display_Items.ResetContent();
  8. To commit changes made to the Jump List, add the following code to the CJumpListTab::OnCommit() event handler:if (m_jumpList.CommitList())
    {
    m_JumpList_Display_Items.ResetContent();
    // Start another list
    m_jumpList.InitializeList();
    }
    else
    {
    AfxMessageBox(L"Failed to commit jump list.");
    }
    Note:
    All updates to a JumpList must take place in between calls to CJumpList::InitializeList() and CJumpList::CommitList(), otherwise, additions will fail.
  9. Build and run the application.
  10. In the Jump List tab, register the jpeg file association by pressing the Register .jpg file association button.
    Note:
    This registration process will need to run elevated, so UAC will prompt you for elevated privileges.
  11. In the Jump List tab, start adding items into the Jump List, making sure to click the “Commit” button at the end so added items can appear on the Jump List. Examples of items to be added:

    1. Add both Recent and Frequent Known Categories (select Frequent from the Known Category drop-down and then click Add Known Category ==>)
    2. Add a Destination by filling in Category = “Custom Category” (no quotes) and Path = C:\Users\Public\Pictures\Sample Pictures\Desert.jpg, and then clicking Add Destination ==>.
    3. Add a Task by filling in Title=”Bing” (no quotes) and Path/Url=http://www.bing.com (Icon is optional), and then clicking Add task ==>.
    4. Click Commit.
    5. Right-click on the application’s taskbar button and you’ll observe output that will look similar to the following:

    Figure 7

    Sample Jump List