|
|
#include "precomp.h"
#include "MultiStateToolbar.h"
CMultiStateToolbar::CMultiStateToolbar( void ) : m_cxButton( 0 ), m_cyButton( 0 ), m_cxBtnBitmaps( 0 ), m_cyBtnBitmaps( 0 ), m_himlTB(NULL), m_himlTBHot(NULL), m_himlTBDisabled(NULL) { DBGENTRY(CMultiStateToolbar::CMultiStateToolbar);
DBGEXIT(CMultiStateToolbar::CMultiStateToolbar); }
CMultiStateToolbar::~CMultiStateToolbar( void ) { DBGENTRY(CMultiStateToolbar::~CMultiStateToolbar);
_KillAllButtons();
if(m_himlTB) { ImageList_Destroy(m_himlTB); m_himlTB = NULL; }
if(m_himlTBHot) { ImageList_Destroy(m_himlTBHot); m_himlTBHot = NULL; }
if(m_himlTBDisabled) { ImageList_Destroy(m_himlTBDisabled); m_himlTBDisabled = NULL; }
if( ::IsWindow( m_hWnd ) ) { DestroyWindow(); }
m_hWnd = NULL;
DBGEXIT(CMultiStateToolbar::~CMultiStateToolbar); }
HRESULT CMultiStateToolbar::Create( HWND hWndParent, DWORD dwID, int cxButton, int cyButton, int cxBtnBitmaps, int cyBtnBitmaps ) { DBGENTRY(CMultiStateToolbar::Create); HRESULT hr = S_OK;
m_cxButton = cxButton; m_cyButton = cyButton; m_cxBtnBitmaps = cxBtnBitmaps; m_cyBtnBitmaps = cyBtnBitmaps;
DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_ALTDRAG | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE;
HWND hWndToolbar = CreateToolbarEx( hWndParent, dwStyle, dwID, 0, // nBitmaps
NULL, // instance
NULL, // NO bitmap ID!
NULL, // buttons
0, // number of buttons
m_cxButton, // button sizes
m_cyButton, m_cxBtnBitmaps, // bitmap sizes
m_cyBtnBitmaps, sizeof(TBBUTTON) );
if( hWndToolbar ) { DWORD dwStyle = ::SendMessage(hWndToolbar, TB_GETEXTENDEDSTYLE, 0, 0); dwStyle |= TBSTYLE_EX_DRAWDDARROWS; ::SendMessage(hWndToolbar, TB_SETEXTENDEDSTYLE, 0, (LPARAM) dwStyle);
SubclassWindow( hWndToolbar ); } else { hr = HRESULT_FROM_WIN32(GetLastError()); }
DBGEXIT_HR(CMultiStateToolbar::Create,hr); return hr; }
HRESULT CMultiStateToolbar::Show( BOOL bShow ) { DBGENTRY(CMultiStateToolbar::Show); HRESULT hr = S_OK;
ShowWindow( bShow ? SW_SHOW : SW_HIDE ); DBGEXIT_HR(CMultiStateToolbar::Show,hr); return hr; }
HRESULT CMultiStateToolbar::InsertItem( int cStates, LPCTSTR szTitle, ItemStateInfo* pItemStates, int* pIndex ) { DBGENTRY(CMultiStateToolbar::InsertItem); HRESULT hr = S_OK;
if( NULL == m_himlTB ) { hr = _CreateImageLists(); }
TBItemData* pNewItemData = new TBItemData; pNewItemData->CurrentState = 0; pNewItemData->cStates = cStates; pNewItemData->pStateData = new TBItemStateData[ pNewItemData->cStates ];
int cImageListItemsBeforeInsertion = ImageList_GetImageCount( m_himlTB );
// For each state
for( int iState = 0; iState < cStates; iState++ ) { // Insert the bitmaps
if( pItemStates[iState].hItemBitmap ) { if (-1 != ImageList_AddMasked(m_himlTB, pItemStates[iState].hItemBitmap, TOOLBAR_MASK_COLOR)) { SendMessage(TB_SETIMAGELIST, 0, (LPARAM) m_himlTB); } else { hr = E_FAIL; } }
if( SUCCEEDED( hr ) ) { if( pItemStates[iState].hItemHotBitmap ) { if (-1 != ImageList_AddMasked(m_himlTBHot, pItemStates[iState].hItemHotBitmap, TOOLBAR_MASK_COLOR)) { SendMessage(TB_SETHOTIMAGELIST, 0, (LPARAM) m_himlTBHot); } else { hr = E_FAIL; } } }
if( SUCCEEDED( hr ) ) { if( pItemStates[iState].hItemDisabledBitmap ) { if (-1 != ImageList_AddMasked(m_himlTBDisabled, pItemStates[iState].hItemDisabledBitmap, TOOLBAR_MASK_COLOR)) { SendMessage(TB_SETDISABLEDIMAGELIST, 0, (LPARAM) m_himlTBDisabled); } else { hr = E_FAIL; } } } // save the state data
pNewItemData->pStateData[iState].BitmapId = cImageListItemsBeforeInsertion + iState; pNewItemData->pStateData[iState].CommandId = pItemStates[iState].dwID; pNewItemData->pStateData[iState].TbStyle = pItemStates[iState].TbStyle; pNewItemData->pStateData[iState].StringId = SendMessage( TB_ADDSTRING, 0, reinterpret_cast<LPARAM>( szTitle ) );
}
int nButtons = SendMessage(TB_BUTTONCOUNT, 0, 0 );
// Insert the Item
TBBUTTON tbi; ClearStruct(&tbi); tbi.iBitmap = pNewItemData->pStateData[0].BitmapId; tbi.idCommand = pNewItemData->pStateData[0].CommandId; tbi.fsState = TBSTATE_ENABLED; tbi.fsStyle = pNewItemData->pStateData[0].TbStyle; tbi.dwData = reinterpret_cast<DWORD>(pNewItemData); tbi.iString = pNewItemData->pStateData[0].StringId; SendMessage(TB_INSERTBUTTON, nButtons, reinterpret_cast<LPARAM>(&tbi)); if( pIndex ) { *pIndex = nButtons; }
DBGEXIT_HR(CMultiStateToolbar::InsertItem,hr); return hr; }
HRESULT CMultiStateToolbar::InsertBlock( int nItems, CMultiStateToolbar::BlockData* pAryOfItemData, HINSTANCE hInstance, int idTBBitmap, int idTBBitmapHot, int idTBBitmapDisabled, int* pIndexFirst ) { DBGENTRY(CMultiStateToolbar::InsertBlock); HRESULT hr = S_OK; if( pAryOfItemData ) { if( NULL == m_himlTB ) { hr = _CreateImageLists(); }
if( SUCCEEDED( hr ) ) { HBITMAP hBmp = NULL; int cImageListItemsBeforeInsertion = ImageList_GetImageCount( m_himlTB );
// Load the Normal Toolbar Bitmap
hBmp = (HBITMAP) LoadImage(hInstance, MAKEINTRESOURCE(idTBBitmap), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE);
if( hBmp ) { if (-1 != ImageList_AddMasked(m_himlTB, hBmp, TOOLBAR_MASK_COLOR)) { SendMessage(TB_SETIMAGELIST, 0, (LPARAM) m_himlTB); } else { hr = E_FAIL; }
DeleteObject(hBmp); }
if( SUCCEEDED( hr ) ) { // Load the Hot Toolbar Bitmap
hBmp = (HBITMAP) LoadImage(hInstance, MAKEINTRESOURCE(idTBBitmapHot), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE);
if( hBmp ) { if (-1 != ImageList_AddMasked(m_himlTBHot, hBmp, TOOLBAR_MASK_COLOR)) { SendMessage(TB_SETHOTIMAGELIST, 0, (LPARAM) m_himlTBHot); } else { hr = E_FAIL; }
DeleteObject(hBmp); } }
if( SUCCEEDED( hr ) ) { // Load the Disabled Toolbar Bitmap
hBmp = (HBITMAP) LoadImage(hInstance, MAKEINTRESOURCE(idTBBitmapDisabled), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE);
if( hBmp ) { if (-1 != ImageList_AddMasked(m_himlTBDisabled, hBmp, TOOLBAR_MASK_COLOR)) { SendMessage(TB_SETDISABLEDIMAGELIST, 0, (LPARAM) m_himlTBDisabled); } else { hr = E_FAIL; }
DeleteObject(hBmp); } } int nButtons = SendMessage(TB_BUTTONCOUNT, 0, 0 );
if( pIndexFirst ) { *pIndexFirst = nButtons; }
// For each button to be inserted...
for( int iItem = 0; SUCCEEDED( hr ) && ( iItem < nItems ) ; iItem++ ) { TBItemData* pNewItemData = new TBItemData; pNewItemData->CurrentState = 0; pNewItemData->cStates = pAryOfItemData[iItem].cbStates; pNewItemData->pStateData = new TBItemStateData[ pNewItemData->cStates ]; int iStringID = SendMessage( TB_ADDSTRING, 0, reinterpret_cast<LPARAM>( pAryOfItemData[iItem].szTitle ) ); for( int iState = 0; iState < pAryOfItemData[iItem].cbStates; iState++ ) { pNewItemData->pStateData[iState].BitmapId = pAryOfItemData[iItem].pStateData[iState].dwBitmapIndex; pNewItemData->pStateData[iState].CommandId = pAryOfItemData[iItem].pStateData[iState].dwID; pNewItemData->pStateData[iState].TbStyle = pAryOfItemData[iItem].pStateData[iState].TbStyle; pNewItemData->pStateData[iState].StringId = iStringID; }
TBBUTTON tbi; ClearStruct(&tbi); tbi.iBitmap = cImageListItemsBeforeInsertion + pNewItemData->pStateData[0].BitmapId; tbi.idCommand = pNewItemData->pStateData[0].CommandId; tbi.fsState = TBSTATE_ENABLED; tbi.fsStyle = pNewItemData->pStateData[0].TbStyle; tbi.dwData = reinterpret_cast<DWORD>(pNewItemData); tbi.iString = pNewItemData->pStateData[0].StringId; if( SendMessage(TB_INSERTBUTTON, nButtons, reinterpret_cast<LPARAM>(&tbi)) ) { ++nButtons; } else { hr = HRESULT_FROM_WIN32(GetLastError()); } } } } else { hr = E_POINTER;
} DBGEXIT_HR(CMultiStateToolbar::InsertBlock,hr); return hr; }
HRESULT CMultiStateToolbar::EnableItem( DWORD dwCmd, BOOL bEnable /* = TRUE */) { DBGENTRY(CMultiStateToolbar::EnableItem); HRESULT hr = S_OK;
if( ::IsWindow( _GetToolbarWindow() ) ) { if( !SendMessage(TB_ENABLEBUTTON, dwCmd, bEnable ) ) { hr = E_FAIL; } } else { hr = E_FAIL; }
DBGEXIT_HR(CMultiStateToolbar::EnableItem,hr); return hr; }
HRESULT CMultiStateToolbar::SetItemState( int iIndex, int NewState ) { DBGENTRY(CMultiStateToolbar::SetItemState); HRESULT hr = S_OK;
if( ::IsWindow( _GetToolbarWindow() ) ) { TBBUTTON tbb; ClearStruct(&tbb); SendMessage( TB_GETBUTTON, iIndex, reinterpret_cast<LPARAM>(&tbb));
TBItemData* pItemData = reinterpret_cast<TBItemData*>(tbb.dwData); if( pItemData ) { if( NewState < pItemData->cStates ) { if( pItemData->CurrentState != NewState ) { // We have to change the state
TBBUTTONINFO tbbi; ClearStruct(&tbbi); tbbi.cbSize = sizeof( TBBUTTONINFO ); tbbi.dwMask = TBIF_IMAGE | TBIF_COMMAND | TBIF_STYLE; tbbi.idCommand = pItemData->pStateData[NewState].CommandId; tbbi.iImage = pItemData->pStateData[NewState].BitmapId; tbbi.fsStyle = pItemData->pStateData[NewState].TbStyle;
// NOTE: Changing the string stuff is not supported....
if( SendMessage( TB_SETBUTTONINFO, pItemData->pStateData[pItemData->CurrentState].CommandId, reinterpret_cast<LPARAM>(&tbbi) ) ) { pItemData->CurrentState = NewState; }
// force the image to be redrawn
RECT rc; SendMessage(TB_GETITEMRECT, iIndex, reinterpret_cast<LPARAM>(&rc)); InvalidateRect(&rc); InvalidateRect(NULL, TRUE);
} } else { hr = E_INVALIDARG; } } else { hr = E_FAIL; } }
DBGEXIT_HR(CMultiStateToolbar::SetItemState,hr); return hr; }
HRESULT CMultiStateToolbar::ShowLabels( BOOL bShowLabels) { DBGENTRY(CMultiStateToolbar::ShowLabels); HRESULT hr = S_OK;
if( !bShowLabels ) { SendMessage(TB_SETBUTTONSIZE, 0, MAKELPARAM( m_cxBtnBitmaps, m_cyBtnBitmaps ) ); } else { SendMessage(TB_SETBUTTONSIZE, 0, MAKELPARAM( m_cxButton, m_cyButton ) ); }
SendMessage(TB_SETMAXTEXTROWS, bShowLabels ? 1 : 0, 0);
DBGEXIT_HR(CMultiStateToolbar::ShowLabels,hr); return hr; }
HRESULT CMultiStateToolbar::Resize( RECT& rc ) { DBGENTRY(CMultiStateToolbar::Resize); HRESULT hr = S_OK;
if( !SetWindowPos( NULL, &rc, SWP_NOACTIVATE | SWP_NOZORDER) ) { hr = HRESULT_FROM_WIN32(GetLastError()); }
DBGEXIT_HR(CMultiStateToolbar::Resize,hr); return hr; }
HRESULT CMultiStateToolbar::GetWindow( HWND* phWnd ) { DBGENTRY(CMultiStateToolbar::GetWindow); HRESULT hr = S_OK; if( phWnd ) { ASSERT( NULL == *phWnd );
*phWnd = _GetToolbarWindow(); } else { hr = E_POINTER;
}
DBGEXIT_HR(CMultiStateToolbar::GetWindow,hr); return hr; }
LRESULT CMultiStateToolbar::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& lResult ) { DBGENTRY(CMultiStateToolbar::OnDestroy); _KillAllButtons();
DBGEXIT(CMultiStateToolbar::OnDestroy); return 0; }
LRESULT CMultiStateToolbar::OnNcDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& lResult ) {
// There is a bug in ATL that if you don't handle WM_NCDESTROY,
// ATL will call CallWindowProc will a NULL hWnd... this causes assertions
// on Debug Win95 and Bounds Checker reports an error as well..
DBGENTRY(CMultiStateToolbar::OnNcDestroy); DBGEXIT(CMultiStateToolbar::OnNcDestroy); return 0; }
void CMultiStateToolbar::_KillAllButtons( void ) { DBGENTRY(CMultiStateToolbar::_KillAllButtons);
if( ::IsWindow( _GetToolbarWindow() ) ) { int nButtons = SendMessage(TB_BUTTONCOUNT, 0, 0 ); for( int iButton = 0; iButton < nButtons; iButton++ ) { TBBUTTON tbb; ClearStruct(&tbb);
if( SendMessage( TB_GETBUTTON, 0, reinterpret_cast<LPARAM>(&tbb)) ) { TBItemData* pItemData = reinterpret_cast<TBItemData*>(tbb.dwData); if( pItemData ) { delete [] pItemData->pStateData; }
delete [] pItemData; }
SendMessage( TB_DELETEBUTTON, 0, 0 ); } }
DBGEXIT(CMultiStateToolbar::_KillAllButtons); }
HRESULT CMultiStateToolbar::_CreateImageLists( void ) { DBGENTRY(CMultiStateToolbar::_CreateImageLists); HRESULT hr = S_OK; m_himlTB = ImageList_Create( m_cxBtnBitmaps, m_cyBtnBitmaps, ILC_COLOR16 | ILC_MASK, 1, // Initial size
1 // Grow By
);
m_himlTBHot = ImageList_Create( m_cxBtnBitmaps, m_cyBtnBitmaps, ILC_COLOR16 | ILC_MASK, 1, // Initial size
1 // Grow By
);
m_himlTBDisabled = ImageList_Create( m_cxBtnBitmaps, m_cyBtnBitmaps, ILC_COLOR4 | ILC_MASK, 1, // Initial size
1 // Grow By
);
if(! ( m_himlTB && m_himlTBHot && m_himlTBDisabled ) ) { // One of the create calls failed
ASSERT( 0 ); // I think that this is the only reason ImageList_Create would fail...
hr = E_OUTOFMEMORY; }
DBGEXIT_HR(CMultiStateToolbar::_CreateImageLists,hr); return hr; }
|