windows-nt/Source/XPSP1/NT/enduser/netmeeting/ui/conf/multistatetoolbar.cpp
2020-09-26 16:20:57 +08:00

588 lines
17 KiB
C++

#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;
}