Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Windows 7: Adding Toolbar Buttons to taskbar Button flyout

0.00/5 (No votes)
13 May 2010 2  
Adding toolbar buttons to taskbar button flyout

In the previous post, we’ve discussed about progressbar overlay on taskbar button. In this installment, we will see how to add the toolbar buttons to the flyout thumbnail Window. The best example is Windows Media Player. You can control the tracks using the flyout window on hovering the thumbnail button.

image

As you can see above, the thumbnail popping up is not really displaying the actual content of the window (which is by default). It shows a custom thumbnail image and toolbar buttons down the image to control the track.

Adding these buttons is quite easy.

There are few peculiarities for the buttons displayed as toolbar in thumbnail area.

  1. A maximum of 7 buttons can be added to thumbnail
  2. The size of the bitmaps specified for thumbnails is dependent on the current DPI. Usually, we use the 16×16 image for default DPI( 96 ). The bitmap size can be calculated easily by calling GetSystemMetrics(SM_CXSIZE) and GetSystemMetrics(SM_CYSIZE). This has to be taken care if the application is DPI aware.
  3. The buttons follow the same order they specified in the array.
  4. The buttons can’t be removed once they are added, however we can hide/update the buttons.
  5. The image lists created to specify the bitmaps can be released after adding it to the thumbnail area. The ITaskbarList3 interface can also be released if we’re finished processing.
  6. The most important thing is, every application must handle the “TaskbarButtonCreated” message before using the ITaskList3 interface functions. Otherwise, the application may face exceptions.  Especially, when the buttons and other overlays are initialized on application initialization.
  7. The button effect on disabling, enabling, hovering is controlled by shell itself. We don’t need to keep a separate image list for this.

Handling TaskbarButtonCreated Message in MFC Application

As I mentioned before, the first task is to handle the “TaskbarButtonCreated” message in the application for proper initialization of ITaskbarList3 interface.

The following code will help you to do this. You can initialize the variable globally or inside the constructor of the class.

UINT g_uTBBC = RegisterWindowMessage(L"TaskbarButtonCreated");

Once this parameter has been initialized, handle the message inside the message map of the dialog class. Note that you should not use ON_MESSAGE to handle the message. ON_REGISTERED_MESSAGE function must be used.

BEGIN_MESSAGE_MAP(CTaskBarSampleDlg, CDialogEx) ...
...
ON_REGISTERED_MESSAGE( g_uTBBC, CTaskBarSampleDlg::OnCreateThumbToolBar )
...
END_MESSAGE_MAP()

Proceed to initialize ITaskbarList3 after receiving notification in the message handler.

LRESULT CTaskBarSampleDlg::OnCreateThumbToolBar( WPARAM, LPARAM )
 { AddThumbarButtons(); return 0; }

Initializing and Adding Buttons

Now let’s see the initialization process. This can be accomplished in the following steps:

  • Initialize the ITaskbarList3 interface
  • Create Image list to specify as the bitmap buttons
  • Add image list to the interface
  • Prepare the button information as array
  • Add the buttons

I’ve added enough comments in the source, I hope it’s easy to understand.

void CTaskBarSampleDlg::AddThumbarButtons()
{
        // Initialize the pointer. You can also do this in the constructor.
    // Remember to release after use
    if( NULL == m_pTaskBarlist )
    {
        CoCreateInstance( CLSID_TaskbarList, NULL, CLSCTX_ALL,
                          IID_ITaskbarList3, (void**)&m_pTaskBarlist);
    }

    m_pTaskBarlist->HrInit();

    // We mention that, we're specifying bitmap, tooltip and other flags.
    // This is mask, only specified parameters will be taken from structure
    THUMBBUTTONMASK dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;

    // Create the images from a single bitmap which contains
    // buttons separated 16pix width. Like we handle toolbar buttons
    CImageList  ImageList;
    ImageList.Create( MAKEINTRESOURCE( IDB_BITMAP_PAUSE), 16, 2, RGB( 0xFF,0,0xFF));

    // Prepare the thumbar buttons
    THUMBBUTTON thbButtons[2];
    thbButtons[0].dwMask = dwMask;
    // This can be any integer required on handling button events
    thbButtons[0].iId = IDB_THB_BUTTON_START;
    thbButtons[0].iBitmap = 0;
    lstrcpy( thbButtons[0].szTip, TEXT("Start"));
    thbButtons[0].dwFlags = THBF_ENABLED | THBF_DISMISSONCLICK;

    thbButtons[1].dwMask = dwMask;
    thbButtons[1].iId = IDB_THB_BUTTON_PAUSE;
    thbButtons[1].iBitmap = 1;
    thbButtons[1].dwFlags = THBF_DISABLED | THBF_DISMISSONCLICK;
    lstrcpy( thbButtons[1].szTip, TEXT("Pause"));

    // Declare the image list that contains the button images.
    m_pTaskBarlist->ThumbBarSetImageList(m_hWnd, ImageList.GetSafeHandle());

    // Attach the toolbar to the thumbnail.
    m_pTaskBarlist->ThumbBarAddButtons(m_hWnd, ARRAYSIZE(thbButtons), thbButtons);

    // In this program we're using the interface later, so not releasing now.
    // It's Ok to release if finished using. We can create again when necessary
}

Handling the Events from Buttons

The events from buttons will be delivered as WM_COMMAND message for Window. As we’re using MFC, please override OnCommand function. The button ID can be extracted from wParam using LOWORD macro.

BOOL CTaskBarSampleDlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
    UINT CommandID = LOWORD( wParam );

        if( IDB_THB_BUTTON_START == CommandID )
            OnBnClickedButton1();
        else if( IDB_THB_BUTTON_PAUSE == CommandID )
            ResetProgress();
        else
            return CDialogEx::OnCommand(wParam, lParam);
}

Updating Buttons

We’ve received the button event, so it’s time to update the button. We can’t remove the buttons as I specified before, we can hide, disable, enable the state of the buttons. Other properties like bitmaps and tooltip can also be updated.

void CTaskBarSampleDlg::ResetProgress()
{
    // reset the progress state
    m_pTaskBarlist->SetProgressState( m_hWnd, TBPF_NOPROGRESS );

    THUMBBUTTONMASK dwMask = THB_FLAGS;

    THUMBBUTTON thbButtons[2];
    thbButtons[0].dwMask = dwMask;
    thbButtons[0].iId = IDB_THB_BUTTON_START;
    thbButtons[0].dwFlags = THBF_ENABLED | THBF_DISMISSONCLICK;

    thbButtons[1].dwMask = dwMask;
    thbButtons[1].iId = IDB_THB_BUTTON_PAUSE;
    thbButtons[1].dwFlags = THBF_DISABLED| THBF_DISMISSONCLICK;

    m_pTaskBarlist->ThumbBarUpdateButtons( m_hWnd, ARRAYSIZE(thbButtons), thbButtons );
}

Note that the code specified above doesn’t handle the icons based on the DPI. It always uses the icon size of default DPI (16pix). You can maintain different bitmaps to handle this. This code in the sample is just a mere demonstration of this API. It may not have a professional standard.

Final Output

image

To get the icons, you can locate this down in the Visual Studio Installation directory. Usually, it appears at

C:\Program Files\Microsoft Visual Studio 10.0\Common7\VS2010ImageLibrary\1033\VS2010ImageLibrary\VS2010ImageLibrary

Note: You’ve the sole responsibility of downloading executing the code. It works only with Windows 7 and is compiled under Visual Studio 2010.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here