////////////////////////////////////////////////////////////////////////// // Toolbar.cpp: Toolbar and rebar control classes. // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved. // ////////////////////////////////////////////////////////////////////////// #include "wincontrol.h" #include "toolbar.h" //-------------------------------------------------------------------------------------- // Toolbar constructor. //-------------------------------------------------------------------------------------- Toolbar::Toolbar() { m_hImageListNormal = NULL; m_hImageListHot = NULL; m_hImageListDisabled = NULL; } Toolbar::Button::Button(int bitmap, int command) { ZeroMemory(this, sizeof(TBBUTTON)); iBitmap = bitmap; idCommand = command; fsState = TBSTATE_ENABLED; fsStyle = BTNS_BUTTON; } //-------------------------------------------------------------------------------------- // Toolbar destructor. //-------------------------------------------------------------------------------------- Toolbar::~Toolbar() { // Delete the image lists if (m_hImageListNormal) { DeleteObject(m_hImageListNormal); } if (m_hImageListHot) { DeleteObject(m_hImageListHot); } if (m_hImageListDisabled) { DeleteObject(m_hImageListDisabled); } } //-------------------------------------------------------------------------------------- // Toolbar::Create // Description: Creates an instance of the toolbar class. //-------------------------------------------------------------------------------------- HRESULT Toolbar::Create(HINSTANCE hInstance, HWND hParent, DWORD_PTR id, DWORD dwStyle) { dwStyle |= WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER; m_hwnd = CreateWindowEx(0, TOOLBARCLASSNAME, (LPTSTR) NULL, dwStyle, 0, 0, 0, 0, hParent, (HMENU)id, hInstance, NULL); if (m_hwnd == 0) { return __HRESULT_FROM_WIN32(GetLastError()); } SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0); return S_OK; } //-------------------------------------------------------------------------------------- // Toolbar::AddButton // Description: Add a button to the toolbar. //-------------------------------------------------------------------------------------- HRESULT Toolbar::AddButton(const Toolbar::Button& button) { assert(m_hwnd != NULL); if (SendMessage(TB_ADDBUTTONS, 1, (LPARAM)&button)) { return S_OK; } else { return __HRESULT_FROM_WIN32(GetLastError()); } } //-------------------------------------------------------------------------------------- // Toolbar::Check // Description: Checks or unchecks a button in the toolbar. //-------------------------------------------------------------------------------------- HRESULT Toolbar::Check(int id, BOOL fCheck) { assert(m_hwnd != NULL); if (SendMessage(TB_CHECKBUTTON, id, fCheck)) { return S_OK; } else { return __HRESULT_FROM_WIN32(GetLastError()); } } //-------------------------------------------------------------------------------------- // Toolbar::Enable // Description: Enables or disables a button in the toolbar. //-------------------------------------------------------------------------------------- HRESULT Toolbar::Enable(int id, BOOL fEnable) { assert(m_hwnd != NULL); if (SendMessage(TB_ENABLEBUTTON, id, fEnable)) { return S_OK; } else { return __HRESULT_FROM_WIN32(GetLastError()); } } //-------------------------------------------------------------------------------------- // Toolbar::SetButtonImage // Description: Sets the bitmap for a button in the toolbar. // // bitmap: Image index (in the image list) //-------------------------------------------------------------------------------------- HRESULT Toolbar::SetButtonImage(int id, int bitmap) { assert(m_hwnd != NULL); TBBUTTONINFO tbbi; ZeroMemory(&tbbi, sizeof(tbbi)); tbbi.cbSize = sizeof(tbbi); tbbi.dwMask = TBIF_IMAGE; tbbi.iImage = bitmap; if (SendMessage(TB_SETBUTTONINFO, id, (LPARAM)&tbbi)) { return S_OK; } else { return __HRESULT_FROM_WIN32(GetLastError()); } } /////////////////////////////////////////////////////////////////////// // Name: ShowToolTip // Desc: Show a tool tip for a toolbar button. // // Call this method when the app receives a TTN_GETDISPINFO notification. // The method loads a string resource with the same resource ID as the // button ID. // // hInstance: Handle to the application instance // pDispInfo: Pointer to the NMTTDISPINFO struct from the WM_NOTFIY // message. // /////////////////////////////////////////////////////////////////////// HRESULT Toolbar::ShowToolTip(NMTTDISPINFO *pDispInfo) { const int cchBuffer = 80; // size of the buffer in the NMTTDISPINFO struct. // Check if the NMTTDISPINFO structure contains a button ID. // (It might contain nothing, or an HWND.) if (pDispInfo->hdr.idFrom != 0 && !(pDispInfo->uFlags & TTF_IDISHWND)) { // Tell the tooltip control to load a string with the same resource ID. pDispInfo->hinst = GetInstance(); pDispInfo->lpszText = (LPTSTR)pDispInfo->hdr.idFrom; // This flag means "store the string yourself, and stop asking me" pDispInfo->uFlags = TTF_DI_SETITEM; } return S_OK; } //-------------------------------------------------------------------------------------- // Toolbar::SetImageList // Description: Sets an image list for the toolbar. // // state: Which button state this image list will apply to. // nBitmapID: Resource ID of the bitmap that contains the images. // buttonSize: Size of each button image. // numButtons: Number of button images // mask: Color mask //-------------------------------------------------------------------------------------- HRESULT Toolbar::SetImageList( ButtonState state, UINT nBitmapID, const Size& buttonSize, DWORD numButtons, COLORREF mask ) { HRESULT hr = S_OK; HBITMAP hBitmap = NULL; HIMAGELIST hImageListTmp; int iImageList; // Create the image list hImageListTmp = ImageList_Create( buttonSize.cx, buttonSize.cy, ILC_COLOR24 | ILC_MASK, numButtons, 0); if (hImageListTmp == NULL) { hr = __HRESULT_FROM_WIN32(GetLastError()); } // Load the bitmap for the image list. if (SUCCEEDED(hr)) { hBitmap = LoadBitmap(GetInstance(), MAKEINTRESOURCE(nBitmapID)); if (hBitmap == NULL) { hr = __HRESULT_FROM_WIN32(GetLastError()); } } // Add masked bitmap to image list if (SUCCEEDED(hr)) { iImageList = ImageList_AddMasked(hImageListTmp, hBitmap, mask); if (iImageList == -1) // Failure code is -1 { hr = __HRESULT_FROM_WIN32(GetLastError()); } } // Set the image list on the toolbar and store the image list handle. if (SUCCEEDED(hr)) { switch (state) { case Normal: m_hImageListNormal = hImageListTmp; SendMessage(TB_SETIMAGELIST, 0, (LPARAM)hImageListTmp); break; case Hot: m_hImageListNormal = hImageListTmp; SendMessage(TB_SETHOTIMAGELIST, 0, (LPARAM)hImageListTmp); break; case Disabled: m_hImageListNormal = hImageListTmp; SendMessage(TB_SETDISABLEDIMAGELIST, 0, (LPARAM)hImageListTmp); break; default: hr = E_INVALIDARG; DeleteObject(hImageListTmp); } } if (hBitmap) { DeleteObject(hBitmap); } return hr; } ///////////////// //-------------------------------------------------------------------------------------- // Rebar constructor. //-------------------------------------------------------------------------------------- Rebar::Rebar() { } //-------------------------------------------------------------------------------------- // Rebar::Create // Description: Creates an instance of the rebar class. //-------------------------------------------------------------------------------------- HRESULT Rebar::Create(HINSTANCE hInstance, HWND hParent, DWORD_PTR id, DWORD dwStyle) { dwStyle |= WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_AUTOSIZE | RBS_BANDBORDERS | CCS_NODIVIDER; m_hwnd = CreateWindowEx(0, REBARCLASSNAME, (LPTSTR) NULL, dwStyle, 0, 0, 0, 0, hParent, (HMENU)id, hInstance, NULL); if (m_hwnd == 0) { return __HRESULT_FROM_WIN32(GetLastError()); } REBARINFO rbi; rbi.cbSize = sizeof(REBARINFO); rbi.fMask = 0; SendMessage(RB_SETBARINFO, 0, (LPARAM)&rbi); return S_OK; } //-------------------------------------------------------------------------------------- // Rebar::AddBand // Description: Add a new band to the rebar control. //-------------------------------------------------------------------------------------- HRESULT Rebar::AddBand(HWND hBand, UINT id) { assert(hBand != NULL); assert(m_hwnd != NULL); BOOL bIsToolbar = FALSE; int nBtnCount = 0; const DWORD STRING_LEN = 32; WCHAR szClassName[STRING_LEN]; if (0 == GetClassName(hBand, szClassName, STRING_LEN)) { return __HRESULT_FROM_WIN32(GetLastError()); } // Note: per MSDN, string returned by GetClassName is always null terminated (but may be truncated) if (wcscmp(szClassName, TOOLBARCLASSNAME) == 0) { bIsToolbar = TRUE; } if (bIsToolbar) { // Get number of buttons on the toolbar nBtnCount = (int)::SendMessage(hBand, TB_BUTTONCOUNT, 0, 0); } // Set band info structure REBARBANDINFO rbBand; ZeroMemory(&rbBand, sizeof(rbBand)); rbBand.cbSize = REBARBANDINFO_V6_SIZE; rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE | RBBIM_IDEALSIZE; rbBand.fStyle = RBBS_CHILDEDGE ; if (nBtnCount > 0) { // add chevron style for toolbar with buttons rbBand.fStyle |= RBBS_USECHEVRON; } rbBand.hwndChild = hBand; rbBand.wID = id; // Calculate the size of the band BOOL bRet = FALSE; RECT rcTmp = { 0, 0, 0, 0 }; if (nBtnCount > 0) { bRet = (BOOL)::SendMessage(hBand, TB_GETITEMRECT, nBtnCount - 1, (LPARAM)&rcTmp); rbBand.cx = nBtnCount * (rcTmp.right - rcTmp.left); // length of band rbBand.cyMinChild = rcTmp.bottom - rcTmp.top; // minimum height rbBand.cxMinChild = rbBand.cx; // minimum width } else // no buttons, either not a toolbar or really has no buttons { bRet = ::GetWindowRect(hBand, &rcTmp); rbBand.cx = rcTmp.right - rcTmp.left; rbBand.cxMinChild = rbBand.cx; rbBand.cyMinChild = rcTmp.bottom - rcTmp.top; } rbBand.cxIdeal = rbBand.cx; // ?? Not sure this is right // Add the band LRESULT lRes = SendMessage(RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand); if(lRes == 0) { return E_FAIL; } DWORD dwExStyle = (DWORD)::SendMessage(hBand, TB_GETEXTENDEDSTYLE, 0, 0L); ::SendMessage(hBand, TB_SETEXTENDEDSTYLE, 0, dwExStyle | TBSTYLE_EX_HIDECLIPPEDBUTTONS); return S_OK; } //-------------------------------------------------------------------------------------- // Rebar::ShowBand // Description: Show or hide a band in the rebar. //-------------------------------------------------------------------------------------- HRESULT Rebar::ShowBand(UINT id, BOOL bShow) { UINT position; HRESULT hr = BandIdToIndex(id, &position); if (FAILED(hr)) { return hr; } BOOL result = (BOOL)SendMessage(RB_SHOWBAND, position, bShow); if (result) { return S_OK; } else { return E_FAIL; } } //-------------------------------------------------------------------------------------- // Rebar::BandIdToIndex // Description: Convert a band ID into an index. //-------------------------------------------------------------------------------------- HRESULT Rebar::BandIdToIndex(UINT id, UINT *pIndex) { assert(m_hwnd != NULL); assert(pIndex != NULL); LRESULT result = SendMessage(RB_IDTOINDEX, id, 0); if (result == -1) { return E_FAIL; } else { *pIndex = (UINT)result; return S_OK; } }