Resources: Common Controls

This example is composed of three files:

Source code(usercntrls.cpp)
//=============================================================================
//COMMON CONTROLS (RESOURCES) - Copyright © 2000,2005 Ken Fitlike
//=============================================================================
//API functions used: DestroyIcon,DialogBox,EndDialog,ExtractIcon,FreeLibrary,
//GetClientRect,GetDlgItem,ImageList_AddIcon,ImageList_Create,
//ImageList_Destroy,InitCommonControlsEx,IsWindowVisible,ListView_SetImageList,
//LoadImage,LoadLibrary,MAKEINTRESOURCE,MessageBox,MoveWindow,PostMessage,
//SendMessage,SetWindowLongPtr,ShowWindow,TreeView_SetImageList,WinMain,
//wsprintf.
//=============================================================================
//This demonstrates the creation of common controls on a modal dialog box. A
//tooltip control is not included because it cannot be created from a resource
//script.
//
//BCC55 - Link with comctl32.lib
//MINGW - Link with libcomctl32.a (-lcomctl32)
//MSVC  - Link with comctl32.lib
//=============================================================================
#include <windows.h>  //include all the basics
#include <tchar.h>    //string and other mapping macros

#if defined WIN32_LEAN_AND_MEAN
#include <shellapi.h>
#endif

#if defined __MINGW_H
#define _WIN32_IE 0x0400
#endif
#include <commctrl.h>

#include <string>
#include <vector>
#include "resources.h"

//define an unicode string type alias
typedef std::basic_string<TCHAR> ustring;
//=============================================================================
namespace
{
//default mask for comboboxex
const UINT CBX_ITEM_MASK=CBEIF_IMAGE|CBEIF_TEXT|CBEIF_SELECTEDIMAGE;
}
//=============================================================================
//message processing function declarations
INT_PTR CALLBACK DlgProc(HWND,UINT,WPARAM,LPARAM);
void OnCommand(const HWND,int,int,const HWND);
void OnDestroy(const HWND);
INT_PTR OnInitDlg(const HWND,LPARAM);
INT_PTR OnNotify(const HWND,NMHDR*);
void OnSize(const HWND,int,int,UINT);

//non-message function declarations
inline int ErrMsg(const ustring&);
int AddCbxItem(const HWND,const ustring&,int,int,INT_PTR index=-1,
               UINT mask=CBX_ITEM_MASK);
int AddTabPage(const HWND,const ustring&,int,int image_index=-1,
               UINT mask=TCIF_TEXT|TCIF_IMAGE);
void AddToolbarButton(const HWND,TBBUTTON&,int,const ustring&,
                      BYTE style=TBSTYLE_BUTTON,DWORD_PTR data=0,int cmd=-1,
                      BYTE state=TBSTATE_ENABLED);                           
bool InitComboboxex(const HWND);  
void InitHeader(const HWND);
bool InitListview(const HWND);
void InitProgressbar(const HWND);
void InitRebar(const HWND,const HWND,const HWND);
void InitStatusbar(const HWND);
void InitToolbar(const HWND);
//void InitTooltip(const HWND,const HWND);
void InitTrackbar(const HWND);
bool InitTreeview(const HWND);
void InitUpdown(const HWND,const HWND);
HTREEITEM InsertTreeviewItem(const HWND,const ustring& txt,
                             HTREEITEM htiParent);
//bool SetTreeviewImagelist(const HWND); 
int SetHeaderItem(const HWND,int,int,const ustring&,int);
bool StartAnimCntrl(const HWND);               
void StartCommonControls(DWORD);  
//=============================================================================
namespace
{
HIMAGELIST hCbxImagelist;               //Cbx: 'comboboxex'
HIMAGELIST hLVLargeIcons,hLVSmallIcons; //LV:  'listview'
HIMAGELIST hTVImages;                   //TV:  'treeview'
HINSTANCE  hShellLib;
}
//=============================================================================
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,int)
{
INT_PTR success=DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG1),0,DlgProc);

if (success==-1)
  {
  ErrMsg(_T("DialogBox failed."));
  }
return 0;
}
//=============================================================================
INT_PTR CALLBACK DlgProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch (uMsg)
  {
  case WM_COMMAND:
    {
    OnCommand(hwnd,LOWORD(wParam),HIWORD(wParam),
              reinterpret_cast<HWND>(lParam));
    return 0;
    }
  case WM_DESTROY:
    OnDestroy(hwnd);
    return 0;
  case WM_INITDIALOG:
    {
    return OnInitDlg(hwnd,lParam);
    }
  case WM_NOTIFY:
    {
    return OnNotify(hwnd,reinterpret_cast<NMHDR*>(lParam));
    }
  case WM_SIZE:
    {
    OnSize(hwnd,LOWORD(lParam),HIWORD(lParam),static_cast<UINT>(wParam));
    return 0;
    }
  default:
    return FALSE;  //let system deal with msg
  }
}
//=============================================================================
void OnCommand(const HWND hwnd,int id,int notifycode,const HWND hCntrl)
{
//handles WM_COMMAND message of the modal dialogbox
switch (id)
  {
  case IDOK:        //RETURN key pressed or 'ok' button selected
  case IDCANCEL:    //ESC key pressed or 'cancel' button selected
    EndDialog(hwnd,id);
  }
}
//=============================================================================
void OnDestroy(const HWND hwnd)
{
FreeLibrary(hShellLib);
ImageList_Destroy(hCbxImagelist);
ImageList_Destroy(hLVLargeIcons);
ImageList_Destroy(hLVSmallIcons);
ImageList_Destroy(hTVImages);
}
//=============================================================================
INT_PTR OnInitDlg(const HWND hwnd,LPARAM lParam)
{
//handles WM_INITDIALOG message
StartCommonControls(ICC_ANIMATE_CLASS|ICC_USEREX_CLASSES|ICC_DATE_CLASSES|
                    ICC_WIN95_CLASSES|ICC_INTERNET_CLASSES|
                    ICC_LISTVIEW_CLASSES|ICC_COOL_CLASSES|ICC_BAR_CLASSES|
                    ICC_TAB_CLASSES|ICC_PROGRESS_CLASS|ICC_TREEVIEW_CLASSES);

//get a handle to shell32.dll which contains resources to be used with a number 
//of common controls in this example
hShellLib=LoadLibrary(_T("shell32.dll"));
if (!hShellLib)
  {
  ErrMsg(_T("Failed to load shell32.dll.\nQuitting now."));
  EndDialog(hwnd,-1); //not much point in continuing
  return 0;
  }

StartAnimCntrl(GetDlgItem(hwnd,IDC_ANIMATION));
InitComboboxex(GetDlgItem(hwnd,IDC_COMBOBOXEX));
ShowWindow(GetDlgItem(hwnd,IDC_DATE_AND_TIME_PICKER),SW_HIDE);
InitHeader(GetDlgItem(hwnd,IDC_HEADER));
ShowWindow(GetDlgItem(hwnd,IDC_IPADDRESS),SW_HIDE);
InitListview(GetDlgItem(hwnd,IDC_LISTVIEW));
ShowWindow(GetDlgItem(hwnd,IDC_MONTHCALENDAR),SW_HIDE);
InitProgressbar(GetDlgItem(hwnd,IDC_PROGRESSBAR));
//toolbar must be initialised before rebar as toolbar will be added to rebar
InitToolbar(GetDlgItem(hwnd,IDC_TOOLBAR));  
InitRebar(GetDlgItem(hwnd,IDC_REBAR),GetDlgItem(hwnd,IDC_TOOLBAR),
          GetDlgItem(hwnd,IDC_COMBOBOXEX));  
InitStatusbar(GetDlgItem(hwnd,IDC_STATUSBAR));  
InitTrackbar(GetDlgItem(hwnd,IDC_TRACKBAR));
InitTreeview(GetDlgItem(hwnd,IDC_TREEVIEW));
InitUpdown(GetDlgItem(hwnd,IDC_UPDOWN),GetDlgItem(hwnd,IDC_EDIT_BUDDY));

HWND hTab=GetDlgItem(hwnd,IDC_TAB);
AddTabPage(hTab,_T("Animation"),0,0);
AddTabPage(hTab,_T("Date & Time Picker"),1,0);
AddTabPage(hTab,_T("Header"),2,0);
AddTabPage(hTab,_T("IP Address"),3,0);
AddTabPage(hTab,_T("Listview"),4,0);
AddTabPage(hTab,_T("Month Calendar"),5,0);
AddTabPage(hTab,_T("Progressbar"),6,0);
AddTabPage(hTab,_T("Trackbar"),7,0);
AddTabPage(hTab,_T("Treeview"),8,0);
AddTabPage(hTab,_T("Up-down"),9,0);

//send a dummy WM_SIZE to resize the controls to fit parent dialog's client 
//area
RECT rc;
GetClientRect(hwnd,&rc);
OnSize(hwnd,rc.right-rc.left,rc.bottom-rc.top,0);
return TRUE;
}
//=============================================================================
INT_PTR OnNotify(const HWND hwnd,NMHDR *nmhdr)
{
//handles WM_NOTIFY message. When the selection changes in the tab control, a
//TCN_SELCHANGE notification is sent to the parent and handled here to
//ensure the control corresponding to that tab page is made visible and the
//previously visible control is hidden
if (nmhdr->code==TCN_SELCHANGE)
  {
  static const int ids[]={IDC_ANIMATION,IDC_DATE_AND_TIME_PICKER,IDC_HEADER,
                          IDC_IPADDRESS,IDC_LISTVIEW,IDC_MONTHCALENDAR,
                          IDC_PROGRESSBAR,IDC_TRACKBAR,IDC_TREEVIEW,
                          IDC_UPDOWN};
  static const unsigned upper_limit=sizeof(ids)/sizeof(ids[0]);  
  
  unsigned static int last_selected;
  unsigned int selected=SendMessage(nmhdr->hwndFrom,TCM_GETCURSEL,0,0);
  
  if (selected >= 0 && selected < upper_limit)
    {
    ShowWindow(GetDlgItem(hwnd,ids[selected]),SW_SHOW);
    if (ids[selected]==IDC_UPDOWN)
      {
      //make sure the edit control associated with the updown is visible
      ShowWindow(GetDlgItem(hwnd,IDC_EDIT_BUDDY),SW_SHOW);
      }
    }
  if (last_selected >= 0 && last_selected < upper_limit)
    {
    ShowWindow(GetDlgItem(hwnd,ids[last_selected]),SW_HIDE);
    if (ids[last_selected]==IDC_UPDOWN)
      {
      //make sure the edit control associated with the updown is hidden
      ShowWindow(GetDlgItem(hwnd,IDC_EDIT_BUDDY),SW_HIDE);
      }
    }
  last_selected=selected;
  }
//when the rebar is manipulated, simulated a WM_SIZE to ensure that the 
//relative positions of rebar and tab control are maintained
if (nmhdr->code==RBN_HEIGHTCHANGE)
  {
  RECT rc;
  GetClientRect(hwnd,&rc);
  OnSize(hwnd,rc.right-rc.left,rc.bottom-rc.top,SIZE_RESTORED);
  }
return 0;
}
//=============================================================================
void OnSize(const HWND hwnd,int cx,int cy,UINT flags)
{
//handles WM_SIZE message
//resize rebar common control so that it is always the width of the parent
HWND hRebar=GetDlgItem(hwnd,IDC_REBAR);
SendMessage(hRebar,WM_SIZE,0,0);

//partition the statusbar here to keep the ratio of the sizes of its parts 
//constant.Each part is set by specifing the coordinates of the right edge of 
//each part. -1 signifies the rightmost part of the parent.
int nHalf=cx/2;
int nParts[]={nHalf,nHalf+nHalf/3,nHalf+nHalf*2/3,-1};
HWND hStatusbar=GetDlgItem(hwnd,IDC_STATUSBAR);
SendMessage(hStatusbar,SB_SETPARTS,4,reinterpret_cast<LPARAM>(&nParts));
//resize statusbar so it's always same width as parent's client area
SendMessage(hStatusbar,WM_SIZE,0,0);

//resize tab control, adjusting postion to accomodate rebar and statusbar 
//controls
RECT rcRebar={0},rcStatbar={0};
GetClientRect(hRebar,&rcRebar);
GetClientRect(hStatusbar,&rcStatbar);
HWND hTab=GetDlgItem(hwnd,IDC_TAB);
MoveWindow(hTab,2,rcRebar.bottom-rcRebar.top,cx-2,
           cy-rcStatbar.bottom-rcStatbar.top,TRUE);

//resize listview
HWND hListview=GetDlgItem(hwnd,IDC_LISTVIEW);
if (IsWindowVisible(hListview) || flags==0)
  {
  RECT rcTab={0};
  SendMessage(hTab,TCM_GETITEMRECT,4,(LPARAM)&rcTab);
  int lvtop=(rcTab.bottom-rcTab.top)+(rcRebar.bottom-rcRebar.top)+8;
  MoveWindow(hListview,4,
             lvtop,
             cx-8,
             cy-lvtop-(rcStatbar.bottom-rcStatbar.top)-4,TRUE);
  //arrange contents of listview along top of control
  SendMessage(hListview,LVM_ARRANGE,LVA_ALIGNTOP,0);
  }
}
//=============================================================================
int AddCbxItem(const HWND hCbx,const ustring& txt,int img_index,
               int selimg_index,INT_PTR index,UINT mask)
{
//insert in item into the comboboxex,'hCbx' with zero-based index of 
//'index'(default value is -1 which adds item to end of list),
//text of 'txt', image index of 'img_index', selected image index of 
//'selimg_index' and mask which defines which of these parameters are actually
//used.

//copy the text into a temporary array (vector) so it's in a suitable form
//for the pszText member of the COMBOBOXEXITEM struct to use. This avoids using
//const_cast on 'txt.c_str()' or variations applied directly to the string that
//break its constant nature.
std::vector<TCHAR> tmp(txt.begin(),txt.end());
tmp.push_back(_T('\0'));

COMBOBOXEXITEM cbei={0};

cbei.mask=mask;
cbei.iItem=index;
cbei.pszText=&tmp[0];
cbei.iImage=img_index;
cbei.iSelectedImage=selimg_index;

return static_cast<int>(SendMessage(hCbx,CBEM_INSERTITEM,0,
                                    reinterpret_cast<LPARAM>(&cbei)));
}
//=============================================================================
int AddTabPage(const HWND hTc,const ustring& txt,int item_index,
               int image_index,UINT mask)
{
//insert a tab page. 'mask' defaults to TCIF_TEXT|TCIF_IMAGE. image_index has
//a default value of -1 (no image);

//copy the text into a temporary array (vector) so it's in a suitable form
//for the pszText member of the TCITEM struct to use. This avoids using
//const_cast on 'txt.c_str()' or variations applied directly to the string that
//break its constant nature.
std::vector<TCHAR> tmp(txt.begin(),txt.end());
tmp.push_back(_T('\0'));

TCITEM tabPage={0};

tabPage.mask=mask;
tabPage.pszText=&tmp[0];
tabPage.cchTextMax=static_cast<int>(txt.length());
tabPage.iImage=image_index;
return static_cast<int>(SendMessage(hTc,TCM_INSERTITEM,item_index,
                        reinterpret_cast<LPARAM>(&tabPage)));
}
//=============================================================================
void AddToolbarButton(const HWND hTb,TBBUTTON& tbb,int bmp,const ustring& txt,
                      BYTE style,DWORD_PTR data,int cmd,BYTE state)
{
tbb.iBitmap=bmp;
tbb.idCommand=cmd;
tbb.fsState=state;
tbb.fsStyle=style;
tbb.dwData=data;
tbb.iString=SendMessage(hTb,TB_ADDSTRING,0,
                        reinterpret_cast<LPARAM>(txt.c_str()));
}
//=============================================================================
inline int ErrMsg(const ustring& s)
{
return MessageBox(0,s.c_str(),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION);
}
//=============================================================================
bool InitComboboxex(const HWND hCbx)
{
//create an image list and fill the comboboxex control with items that use the
//images in the list.
//create imagelist to hold icons for use by ComboBoxEx common control
LPCTSTR lpszResID[]={IDI_APPLICATION,IDI_INFORMATION,IDI_QUESTION};
hCbxImagelist=ImageList_Create(16,16,ILC_MASK|ILC_COLOR32,
                               sizeof(lpszResID)/sizeof(lpszResID[0]),0);
                               
if (!hCbxImagelist)
  {
  ErrMsg(_T("Failed to create imagelist for comboboxex"));
  return false;
  }
  
UINT i;
HICON hIcon;
for (i=0;i<sizeof(lpszResID)/sizeof(lpszResID[0]);++i)
  {
  hIcon=reinterpret_cast<HICON>(LoadImage(0,lpszResID[i],IMAGE_ICON,0,0,
                                          LR_SHARED));
  ImageList_AddIcon(hCbxImagelist,hIcon);
  }

//associate the imagelist with the ComboBoxEx common control
SendMessage(hCbx,CBEM_SETIMAGELIST,0,reinterpret_cast<LPARAM>(hCbxImagelist));

//add some items to the ComboBoxEx common control
AddCbxItem(hCbx,_T("First Item"),0,0);
AddCbxItem(hCbx,_T("Second Item"),1,1);
AddCbxItem(hCbx,_T("Third Item"),2,2);

return true;
}
//=============================================================================
void InitHeader(const HWND hHeader)
{
//set up header control with four equally sized items
RECT rc={0};
GetClientRect(hHeader,&rc);

//setup and add some items to header common control; set width, format and 
//text(centred) of item
SetHeaderItem(hHeader,0,rc.right/4,_T("First Part"),HDF_CENTER);
SetHeaderItem(hHeader,1,rc.right/4,_T("Second Part"),HDF_CENTER);
SetHeaderItem(hHeader,2,rc.right/4,_T("Third Part"),HDF_CENTER);
SetHeaderItem(hHeader,3,rc.right/4,_T("Fourth Part"),HDF_CENTER);

//hide the control
ShowWindow(hHeader,SW_HIDE);
}
//=============================================================================
bool InitListview(const HWND hListview)
{
//set up and attach image lists to list view common control
//create the image lists
hLVLargeIcons=ImageList_Create(GetSystemMetrics(SM_CXICON),
                               GetSystemMetrics(SM_CYICON),
                               ILC_COLOR32|ILC_MASK,1,1); 
hLVSmallIcons=ImageList_Create(GetSystemMetrics(SM_CXSMICON),
                               GetSystemMetrics(SM_CYSMICON),
                               ILC_COLOR32|ILC_MASK,1,1);

if (!hLVLargeIcons || !hLVSmallIcons)
  {
  ErrMsg(_T("Listview imagelist creation failed"));
  return false;
  }
  
//add icons to imagelists. The icons are loaded from "shell32.dll". 
//ExtractIcon is used firstly to get the total number of icon groups and 
//secondly to load one of each group individually.
int nNumIcons=static_cast<int>(reinterpret_cast<INT_PTR>(ExtractIcon(0,
                _T("shell32.dll"),static_cast<UINT>(-1))));

HICON hIcon;
LVITEM lvi={0};

lvi.mask=LVIF_TEXT|LVIF_IMAGE;
int i;
for (i=0;i<nNumIcons;++i)
  {
  hIcon=ExtractIcon(0,_T("shell32.dll"),i);
  ImageList_AddIcon(hLVLargeIcons,hIcon); 
  ImageList_AddIcon(hLVSmallIcons,hIcon); 
  DestroyIcon(hIcon); 
  }
//attach image lists to list view common control
ListView_SetImageList(hListview,hLVLargeIcons,LVSIL_NORMAL); 
ListView_SetImageList(hListview,hLVSmallIcons,LVSIL_SMALL);

//add some items to the the list view common control
        
//flags to determine what information is to be set
TCHAR chBuffer[16];   
for (i=0;i<nNumIcons;++i)
  {
  lvi.iItem=i;                     //the zero-based item index 
  wsprintf(chBuffer,_T("%d"),i);   //convert item index int to string
  lvi.pszText=chBuffer;            //item label
  lvi.cchTextMax=lstrlen(chBuffer);//length of item label
  lvi.iImage=i;                    //image list index
  SendMessage(hListview,LVM_INSERTITEM,0,reinterpret_cast<LPARAM>(&lvi));
  }
  
//hide the control
ShowWindow(hListview,SW_HIDE);

return true;
}
//=============================================================================
void InitProgressbar(const HWND hProgressbar)
{
//set the progress bar position to half-way
SendMessage(hProgressbar,PBM_SETPOS,50,0);

//hide the control
ShowWindow(hProgressbar,SW_HIDE);
}
//=============================================================================
void InitRebar(const HWND hRebar,const HWND hToolbar,const HWND hCbx)
{
//add rebar bands

//The rebar control has been succesfully created so attach two bands, each with
//a single standard control (comboboxex and toolbar).
REBARINFO ri={0};
//no imagelist to attach to rebar
ri.cbSize=sizeof(REBARINFO); 
SendMessage(hRebar,RB_SETBARINFO,0,reinterpret_cast<LPARAM>(&ri));

//setup REBARBANDINFO with details common to both bands such as text colour
//or background bitmap. Note that the text colour can only be set for rebars
//not using winxp styles (ie. no manifest).
REBARBANDINFO rbi={0};
rbi.cbSize=sizeof(REBARBANDINFO);
rbi.fMask=RBBIM_TEXT|RBBIM_STYLE|RBBIM_CHILD|RBBIM_CHILDSIZE;
rbi.fStyle=RBBS_CHILDEDGE|RBBS_GRIPPERALWAYS|RBBS_BREAK;

//set unique REBARBANDINFO values for the toolbar control rebar band
//SetParent(hToolbar,hRebar);
RECT rc={0};
GetClientRect(hToolbar,&rc);    //get dimensions of toolbar control
rbi.lpText=_T("Rebar Band#1: Toolbar");
rbi.hwndChild=hToolbar;
rbi.cxMinChild=0;
rbi.cyMinChild=rc.bottom-rc.top+8;
//Attach toolbar band to rebar common control
SendMessage(hRebar,RB_INSERTBAND,static_cast<WPARAM>(-1),
            reinterpret_cast<LPARAM>(&rbi));
            
//set unique REBARBANDINFO values for the comboboxex control rebar band
//SetParent(hCbx,hRebar);
GetClientRect(hCbx,&rc);    //get dimensions of comboboxex control
rbi.lpText=_T("Rebar Band#2: Comboboxex");
rbi.hwndChild=hCbx;
rbi.cxMinChild=0;
rbi.cyMinChild=rc.bottom-rc.top+8;
//Attach comboboxex band to rebar common control
SendMessage(hRebar,RB_INSERTBAND,static_cast<WPARAM>(-1),
            reinterpret_cast<LPARAM>(&rbi));
}
//=============================================================================
void InitStatusbar(const HWND hStatusbar)
{
//set up statusbar parts
RECT rc;
GetClientRect(GetParent(hStatusbar),&rc);
int nHalf=(rc.right-rc.left)/2;
int nParts[4]={nHalf,nHalf+nHalf/3,nHalf+nHalf*2/3,-1};
SendMessage(hStatusbar,SB_SETPARTS,4,reinterpret_cast<LPARAM>(&nParts));

//now put some text into each part of the status bar common control and setup 
//each part
SendMessage(hStatusbar,SB_SETTEXT,0,
            reinterpret_cast<LPARAM>(_T("Status Bar: 1st Part")));
//draw next 3 parts with a raised edge. 
//Note the syntax: 'status bar part index'|'drawing flag' for the WPARAM of 
//SB_SETTEXT msg.
SendMessage(hStatusbar,SB_SETTEXT,1|SBT_POPOUT,
            reinterpret_cast<LPARAM>(_T("2nd Part")));
SendMessage(hStatusbar,SB_SETTEXT,2|SBT_POPOUT,
            reinterpret_cast<LPARAM>(_T("3rd Part")));
SendMessage(hStatusbar,SB_SETTEXT,3|SBT_POPOUT,
            reinterpret_cast<LPARAM>(_T("4th Part")));
}
//=============================================================================
void InitToolbar(const HWND hToolbar)
{
//add toolbar buttons etc.
TBADDBITMAP tbAddBmp={0};
const int NUMBER_OF_BUTTONS=12;
std::vector<TBBUTTON> tbb(NUMBER_OF_BUTTONS);

//setup and add buttons
SendMessage(hToolbar,TB_BUTTONSTRUCTSIZE,
            static_cast<WPARAM>(sizeof(TBBUTTON)),0);
//add images
tbAddBmp.hInst=HINST_COMMCTRL;
tbAddBmp.nID=IDB_STD_SMALL_COLOR;
SendMessage(hToolbar,TB_ADDBITMAP,0,reinterpret_cast<WPARAM>(&tbAddBmp));

//add buttons
AddToolbarButton(hToolbar,tbb[0],STD_FILENEW,_T("New"));            
AddToolbarButton(hToolbar,tbb[1],STD_FILEOPEN,_T("Open"));
AddToolbarButton(hToolbar,tbb[2],STD_FILESAVE,_T("Save"));           
AddToolbarButton(hToolbar,tbb[4],STD_PRINT,_T("Print"));
AddToolbarButton(hToolbar,tbb[5],0,_T(""),TBSTYLE_SEP);  //separator
AddToolbarButton(hToolbar,tbb[6],STD_DELETE,_T("Delete"));
AddToolbarButton(hToolbar,tbb[7],STD_COPY,_T("Copy"));
AddToolbarButton(hToolbar,tbb[8],STD_CUT,_T("Cut"));
AddToolbarButton(hToolbar,tbb[9],STD_PASTE,_T("Paste"));                           
AddToolbarButton(hToolbar,tbb[10],0,_T(""),TBSTYLE_SEP); //separator
AddToolbarButton(hToolbar,tbb[11],STD_HELP,_T("Help"));                            
        
SendMessage(hToolbar,TB_ADDBUTTONS,tbb.size(),
            reinterpret_cast<LPARAM>(&tbb[0]));
}
//=============================================================================
void InitTrackbar(const HWND hTrackbar)
{
//set the trackbar position
SendMessage(hTrackbar,TBM_SETRANGE,0,MAKELONG(0,20));

//hide the control
ShowWindow(hTrackbar,SW_HIDE);
}
//=============================================================================
bool InitTreeview(const HWND hTreeview)
{
//set up and attach image lists to tree view common control
hTVImages=ImageList_Create(GetSystemMetrics(SM_CXSMICON),
                           GetSystemMetrics(SM_CYSMICON),
                           ILC_COLOR32|ILC_MASK,1,1);
if (hTVImages==0)
  {
  ErrMsg(_T("Failed to create image list."));
  return false;
  }   

int i;
for (i=4;i<6;++i)
  {
  //Because the icons are loaded from system resources  ie they are shared, 
  //it is not necessary to free the image resources with 'DestroyIcon'.
  HICON hIcon=reinterpret_cast<HICON>(LoadImage(hShellLib,
                               MAKEINTRESOURCE(i),
                               IMAGE_ICON,
                               0,0,
                               LR_SHARED));
  ImageList_AddIcon(hTVImages,hIcon); 
  }

//attach image lists to tree view common control
TreeView_SetImageList(hTreeview,hTVImages,TVSIL_NORMAL);

//add some items to the the tree view common control
HTREEITEM hPrev=InsertTreeviewItem(hTreeview,_T("First"),TVI_ROOT);

//sub items of first item
hPrev=InsertTreeviewItem(hTreeview,_T("Level01"),hPrev);  
//sub item of 'level01' item
hPrev=InsertTreeviewItem(hTreeview,_T("Level02"),hPrev); 
//sub item of 'level02' item 
hPrev=InsertTreeviewItem(hTreeview,_T("Level03"),hPrev);  

//insert second item at same level (root) as first item
hPrev=InsertTreeviewItem(hTreeview,_T("Second"),TVI_ROOT);  

//insert third item at same level (root) as first item
hPrev=InsertTreeviewItem(hTreeview,_T("Third"),TVI_ROOT);

//insert fourth item at same level (root) as first item
hPrev=InsertTreeviewItem(hTreeview,_T("Fourth"),TVI_ROOT);

//hide the control
ShowWindow(hTreeview,SW_HIDE);

return true;
}
//=============================================================================
void InitUpdown(const HWND hUpdown,const HWND hEdit)
{
//explicitly attach the updown common control to its 'buddy' edit control
SendMessage(hUpdown,UDM_SETBUDDY,reinterpret_cast<WPARAM>(hEdit),0);

//hide the control
ShowWindow(hUpdown,SW_HIDE);
ShowWindow(hEdit,SW_HIDE);
}
//=============================================================================
HTREEITEM InsertTreeviewItem(const HWND hTv,const ustring& txt,
                             HTREEITEM htiParent)
{
TVITEM tvi={0};

tvi.mask=TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;

//copy the text into a temporary array (vector) so it's in a suitable form
//for the pszText member of the TVITEM struct to use. This avoids using
//const_cast on 'txt.c_str()' or variations applied directly to the string that
//break its constant nature.
std::vector<TCHAR> tmp(txt.begin(),txt.end());
tmp.push_back(_T('\0'));

tvi.pszText=&tmp[0];
tvi.cchTextMax=static_cast<int>(txt.length());  //length of item label
tvi.iImage=0;  //non-selected image index

TVINSERTSTRUCT tvis={0};

tvi.iSelectedImage=1;   //selected image index
tvis.item=tvi; 
tvis.hInsertAfter=0;
tvis.hParent=htiParent; //parent item of item to be inserted

return reinterpret_cast<HTREEITEM>(SendMessage(hTv,TVM_INSERTITEM,0,
                                   reinterpret_cast<LPARAM>(&tvis)));
}
//=============================================================================
int SetHeaderItem(const HWND hHeader,int index,int width,const ustring& txt,
                  int fmt)
{
//add an item to the header control, returns the index of the added item if
//successful, -1 if unsuccessful.

//copy the text into a temporary array (vector) so it's in a suitable form
//for the pszText member of the HDITEM struct to use. This avoids using
//const_cast on 'txt.c_str()' or variations applied directly to the string that
//break its constant nature.
std::vector<TCHAR> tmp(txt.begin(),txt.end());
tmp.push_back(_T('\0'));

HDITEM hdi={0};

hdi.mask=HDI_WIDTH|HDI_FORMAT|HDI_TEXT;  
hdi.cxy=width;                      
hdi.fmt=fmt;
hdi.pszText=&tmp[0];
hdi.cchTextMax=lstrlen(hdi.pszText); 

return static_cast<int>(SendMessage(hHeader,HDM_INSERTITEM,index,
                                    reinterpret_cast<LPARAM>(&hdi))); 
}
//=============================================================================
bool StartAnimCntrl(const HWND hwndAnimate)
{
//attach and play an avi clip in the animation common control. 
//override the control's instance with that of the source of the avi clip
SetWindowLongPtr(hwndAnimate,GWL_HINSTANCE,
                 reinterpret_cast<LONG_PTR>(hShellLib));
                 
if (SendMessage(hwndAnimate,ACM_OPEN,static_cast<WPARAM>(0),
                reinterpret_cast<LPARAM>(MAKEINTRESOURCE(160)))==0)
  {
  ErrMsg(_T("Failed to load avi resource\nfor animation common control"));
  return false;
  }

SendMessage(hwndAnimate,ACM_PLAY,static_cast<WPARAM>(-1),MAKELONG(0,-1));

return true;
}
//=============================================================================
void StartCommonControls(DWORD flags)
{
//load the common controls dll, specifying the type of control(s) required 
INITCOMMONCONTROLSEX iccx;
iccx.dwSize=sizeof(INITCOMMONCONTROLSEX);
iccx.dwICC=flags;
InitCommonControlsEx(&iccx);
}
//=============================================================================
Resource Definitions(resources.h)
//=============================================================================
//Resource script constants for Common Controls example.
//=============================================================================
#define IDD_DIALOG1                200

#define IDC_ANIMATION              301
#define IDC_COMBOBOXEX             302
#define IDC_DATE_AND_TIME_PICKER   303
#define IDC_HEADER                 304
#define IDC_IPADDRESS              305
#define IDC_LISTVIEW               306
#define IDC_MONTHCALENDAR          307
#define IDC_PROGRESSBAR            308
#define IDC_REBAR                  309
#define IDC_STATUSBAR              310
#define IDC_TAB                    311
#define IDC_TOOLBAR                312
#define IDC_TOOLTIP                313
#define IDC_TRACKBAR               314
#define IDC_TREEVIEW               315
#define IDC_UPDOWN                 316
#define IDC_EDIT_BUDDY             317
Resource Script(script.rc)
//=============================================================================
//COMMON CONTROLS - Copyright (c) 2003,2005 Ken Fitlike
//resource script
//
//The controls are created using the CONTROL resource definition statement.
//You can use the macro definitions for common control class names or the 
//actual class names as follows(see commctrl.h):
//  WC_TABCONTROL       "SysTabControl32"
//  ANIMATE_CLASS       "SysAnimate32"
//  WC_COMBOBOXEX       "ComboBoxEx32"
//  DATETIMEPICK_CLASS  "SysDateTimePick32"
//  WC_HEADER           "SysHeader32"
//  WC_IPADDRESS        "SysIPAddress32"
//  WC_LISTVIEW         "SysListView32"
//  MONTHCAL_CLASS      "SysMonthCal32"
//  PROGRESS_CLASS      "msctls_progress32"
//  REBARCLASSNAME      "ReBarWindow32"
//  STATUSCLASSNAME     "msctls_statusbar32"
//  TOOLBARCLASSNAME    "ToolbarWindow32"
//  TOOLTIPS_CLASS      "tooltips_class32"
//  TRACKBAR_CLASS      "msctls_trackbar32"
//  WC_TREEVIEW         "SysTreeView32"
//  UPDOWN_CLASS        "msctls_updown32"
//
//Distinct Tooltip controls cannot be created as part of a resource script.
//
//BCC55: requires commctrl.h to be #included for common control class name
//       definitions.
//MinGW: To use some of the common control styles, _WIN32_IE must be defined,
//       preferably for the resource compiler rather than in this file(see 
//       commctrl.h).
//MSVC:  requires commctrl.h to be #included for common control class name
//       definitions.
//=============================================================================
#if !defined __BORLANDC__

#if !defined _WIN32_IE
  #define _WIN32_IE 0x0400
#endif
  
#include <afxres.h>
#endif

#include <commctrl.h>
#include "resources.h"
//=============================================================================
//Resource languages: Codes for languages and sub-languages are declared in 
//winnt.h eg. for US english replace SUBLANG_ENGLISH_UK with SUBLANG_ENGLISH_US
//eg. for FRENCH replace LANG_ENGLISH with LANG_FRENCH and then replace 
//SUBLANG_ENGLISH_UK with either SUBLANG_FRENCH,SUBLANG_FRENCH_BELGIAN,
//SUBLANG_FRENCH_CANADIAN,SUBLANG_FRENCH_SWISS,SUBLANG_FRENCH_LUXEMBOURG,
//SUBLANG_FRENCH_MONACO depending on which national or regional variation of
//the language corresponds best with your requirements.
//
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK  
//=============================================================================
//Dialog
//=============================================================================
IDD_DIALOG1 DIALOGEX 0, 0, 400, 300
STYLE DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | 
      WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_CLIPCHILDREN
CAPTION "Resources: Common Controls"      
FONT 8, "MS Sans Serif"
  {
  CONTROL "", IDC_ANIMATION, ANIMATE_CLASS, WS_CHILD|ACS_TIMER|ACS_AUTOPLAY|
          ACS_TRANSPARENT, 110, 120, 10, 10
  CONTROL "", IDC_COMBOBOXEX, WC_COMBOBOXEX, WS_CHILD|WS_TABSTOP|
          CBS_DROPDOWN, 0, 24, 100, 100    
  CONTROL "", IDC_DATE_AND_TIME_PICKER, DATETIMEPICK_CLASS, WS_CHILD|
          WS_TABSTOP, 40, 70, 80, 16      
  CONTROL "", IDC_HEADER, WC_HEADER, WS_CHILD|WS_TABSTOP|HDS_BUTTONS, 
          40, 70, 300, 16  
  CONTROL "", IDC_IPADDRESS, WC_IPADDRESS, WS_CHILD|WS_TABSTOP, 40, 70, 120, 16 
  CONTROL "", IDC_LISTVIEW, WC_LISTVIEW, WS_CHILD|WS_TABSTOP|WS_CLIPSIBLINGS|
          LVS_ICON, 10, 50, 380, 270, WS_EX_CLIENTEDGE  
  CONTROL "", IDC_MONTHCALENDAR, MONTHCAL_CLASS, WS_CHILD|WS_TABSTOP, 
          10, 70, 380, 270     
  CONTROL "", IDC_PROGRESSBAR, PROGRESS_CLASS, WS_CHILD|WS_TABSTOP, 
          40, 70, 300, 24   
  CONTROL "", IDC_REBAR, REBARCLASSNAME, WS_CHILD|WS_TABSTOP|WS_CLIPSIBLINGS|
          WS_CLIPCHILDREN|RBS_VARHEIGHT|CCS_NODIVIDER|RBS_BANDBORDERS, 
          0, 0, 400, 32 
  CONTROL "", IDC_STATUSBAR, STATUSCLASSNAME, WS_CHILD|WS_TABSTOP|
          SBARS_SIZEGRIP, 0, 380, 400, 16   
  CONTROL "", IDC_TOOLBAR, TOOLBARCLASSNAME, WS_CHILD|WS_TABSTOP|TBSTYLE_FLAT|
          CCS_ADJUSTABLE|CCS_NODIVIDER|CCS_NOPARENTALIGN, 0, 0, 100, 0  
  CONTROL "", IDC_TRACKBAR, TRACKBAR_CLASS, WS_CHILD|WS_TABSTOP|TBS_AUTOTICKS, 
          10, 70, 200, 20  
  CONTROL "", IDC_TREEVIEW, WC_TREEVIEW, WS_CHILD|WS_TABSTOP|TVS_HASLINES|
          TVS_LINESATROOT|TVS_HASBUTTONS, 10, 70, 200, 200, WS_EX_CLIENTEDGE  
  CONTROL "", IDC_UPDOWN, UPDOWN_CLASS, WS_CHILD|WS_TABSTOP|UDS_ALIGNRIGHT|
          UDS_SETBUDDYINT|UDS_WRAP, 30, 70, 60, 16
  CONTROL "", IDC_EDIT_BUDDY, "EDIT", WS_CHILD|WS_TABSTOP, 30,70,60,16, 
          WS_EX_CLIENTEDGE          
  CONTROL "", IDC_TAB, WC_TABCONTROL, WS_CHILD|WS_TABSTOP|WS_CLIPSIBLINGS, 
          0, 30, 400, 250
  }
//=============================================================================