Click here to Skip to main content
Click here to Skip to main content
Go to top

Windows 7: Adding toolbar buttons to taskbar button flyout

, 13 May 2010
Rate this:
Please Sign up or sign in to vote.
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 show a custom thumbnail image and toolbar buttons down the image to control the track.

Adding these buttons are 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 follows the same order they specified in the array.
  4. The buttons can’t be removed once it’s added, however we can hide/update the buttons.
  5. The image lists created to specify the bitmaps can be released after calling 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 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.

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 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 receving 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 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 comment 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, tooltpi 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 seperated 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 not handling the icons based on the DPI. It always use the icon size of default DPI (16pix).  You can maintain different bitmaps to handle this. This code in the sample is just 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 compiled under Visual Studio 2010

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Sarath C
Technical Lead
India India
Software Developer
Follow on   Twitter

Comments and Discussions

 
GeneralExcellent example Pinmember Randor 4-Jun-10 17:26 
GeneralRe: Excellent example PinmemberSarath.6-Jun-10 4:41 
Thanks Randor!
-Sarath.
Rate the answers and close your posts if it's answered

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140921.1 | Last Updated 13 May 2010
Article Copyright 2010 by Sarath C
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid