Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

514 lines
19 KiB

/*******************************************************************************
*
* (C) COPYRIGHT MICROSOFT CORPORATION, 2000
*
* TITLE: CREATETB.CPP
*
* VERSION: 1.0
*
* AUTHOR: ShaunIv
*
* DATE: 12/22/2000
*
* DESCRIPTION: Toolbar helpers
*
*******************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include "createtb.h"
#include <windowsx.h>
#include <simstr.h>
#include <psutil.h>
#include <simrect.h>
namespace ToolbarHelper
{
//
// This is a replacement for CreateToolbarEx (in comctl32.dll) that uses CreateMappedBitmap
// so we can get the benefit of having buttons that work ok in high contrast mode.
//
HWND CreateToolbar(
HWND hwndParent,
DWORD dwStyle,
UINT_PTR nID,
CToolbarBitmapInfo &ToolbarBitmapInfo,
LPCTBBUTTON pButtons,
int nButtonCount,
int nButtonWidth,
int nButtonHeight,
int nBitmapWidth,
int nBitmapHeight,
UINT nButtonStructSize )
{
HWND hwndToolbar = CreateWindow( TOOLBARCLASSNAME, NULL, WS_CHILD | dwStyle, 0, 0, 100, 30, hwndParent, reinterpret_cast<HMENU>(nID), NULL, NULL );
if (hwndToolbar)
{
ToolbarBitmapInfo.Toolbar(hwndToolbar);
SendMessage( hwndToolbar, TB_BUTTONSTRUCTSIZE, nButtonStructSize, 0 );
if (nBitmapWidth && nBitmapHeight)
{
SendMessage( hwndToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(nBitmapWidth,nBitmapHeight) );
}
if (nButtonWidth && nButtonHeight)
{
SendMessage( hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(nButtonWidth,nButtonHeight) );
}
HBITMAP hBitmap = CreateMappedBitmap( ToolbarBitmapInfo.ToolbarInstance(), ToolbarBitmapInfo.BitmapResId(), 0, NULL, 0 );
if (hBitmap)
{
TBADDBITMAP TbAddBitmap = {0};
TbAddBitmap.hInst = NULL;
TbAddBitmap.nID = reinterpret_cast<UINT_PTR>(hBitmap);
if (-1 != SendMessage( hwndToolbar, TB_ADDBITMAP, ToolbarBitmapInfo.ButtonCount(), reinterpret_cast<LPARAM>(&TbAddBitmap) ) )
{
ToolbarBitmapInfo.Bitmap(hBitmap);
}
}
SendMessage( hwndToolbar, TB_ADDBUTTONS, nButtonCount, reinterpret_cast<LPARAM>(pButtons) );
}
return hwndToolbar;
}
HWND CreateToolbar(
HWND hWndParent,
HWND hWndPrevious,
HWND hWndAlign,
int Alignment,
UINT nToolbarId,
CToolbarBitmapInfo &ToolbarBitmapInfo,
CButtonDescriptor *pButtonDescriptors,
UINT nDescriptorCount )
{
HWND hWndToolbar = NULL;
//
// Make sure we have valid data
//
if (!hWndParent || !ToolbarBitmapInfo.ToolbarInstance() || !ToolbarBitmapInfo.BitmapResId() || !pButtonDescriptors || !nDescriptorCount)
{
return NULL;
}
//
// Load the bitmap, so we can figure out how many buttons are in the supplied bitmap,
// and their size. We assume that the buttons are the same height and width.
//
HBITMAP hBitmap = reinterpret_cast<HBITMAP>(LoadImage( ToolbarBitmapInfo.ToolbarInstance(), MAKEINTRESOURCE(ToolbarBitmapInfo.BitmapResId()), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR|LR_CREATEDIBSECTION ));
if (hBitmap)
{
//
// Get the size of the bitmap
//
SIZE sizeBitmap = {0};
PrintScanUtil::GetBitmapSize(hBitmap,sizeBitmap);
//
// If the sizes are valid, continue
//
if (sizeBitmap.cx && sizeBitmap.cy)
{
//
// Figure out the count and dimensions of the buttons
// Note the ridiculous size supplied for nButtonSizeX. This is a
// workaround for a BTNS_AUTOSIZE bug
//
int nToolbarButtonCount = sizeBitmap.cx / sizeBitmap.cy;
int nButtonBitmapSizeX = sizeBitmap.cy;
int nButtonBitmapSizeY = sizeBitmap.cy;
int nButtonSizeX = 1000;
int nButtonSizeY = sizeBitmap.cy;
//
// Figure out which buttons to actually add
//
CSimpleDynamicArray<TBBUTTON> aActualButtons;
for (UINT i=0;i<nDescriptorCount;i++)
{
//
// If there is no controlling variable, or if it is true, add the button
//
if (!pButtonDescriptors[i].pbControllingVariable || *(pButtonDescriptors[i].pbControllingVariable))
{
TBBUTTON ToolbarButton = {0};
ToolbarButton.iBitmap = pButtonDescriptors[i].iBitmap >= 0 ? pButtonDescriptors[i].iBitmap : I_IMAGENONE;
ToolbarButton.idCommand = pButtonDescriptors[i].idCommand;
ToolbarButton.fsState = pButtonDescriptors[i].fsState;
ToolbarButton.fsStyle = pButtonDescriptors[i].fsStyle | BTNS_AUTOSIZE;
aActualButtons.Append(ToolbarButton);
//
// Add the separator, if requested
//
if (pButtonDescriptors[i].bFollowingSeparator)
{
TBBUTTON ToolbarButtonSeparator = {0};
ToolbarButton.fsStyle = BTNS_SEP;
aActualButtons.Append(ToolbarButton);
}
}
}
//
// Make sure we have at least one button
//
ToolbarBitmapInfo.ButtonCount(nToolbarButtonCount);
if (aActualButtons.Size())
{
//
// Create the toolbar
//
hWndToolbar = CreateToolbar(
hWndParent,
WS_CHILD|WS_GROUP|WS_VISIBLE|TBSTYLE_FLAT|WS_TABSTOP|CCS_NODIVIDER|TBSTYLE_LIST|CCS_NORESIZE|TBSTYLE_TOOLTIPS,
nToolbarId,
ToolbarBitmapInfo,
aActualButtons.Array(),
aActualButtons.Size(),
nButtonSizeX,
nButtonSizeY,
nButtonBitmapSizeX,
nButtonBitmapSizeY,
sizeof(TBBUTTON) );
if (hWndToolbar)
{
//
// Set the font for the toolbar to be the same as the font for its parent
//
LRESULT lFontResult = SendMessage( hWndParent, WM_GETFONT, 0, 0 );
if (lFontResult)
{
SendMessage( hWndToolbar, WM_SETFONT, lFontResult, 0 );
}
//
// Loop through all of the actual buttons, to find their string resource ID
//
for (int i=0;i<aActualButtons.Size();i++)
{
//
// Look for the matching record, to find the string resource ID
//
for (UINT j=0;j<nDescriptorCount;j++)
{
//
// If this is the original record
//
if (aActualButtons[i].idCommand == pButtonDescriptors[j].idCommand)
{
//
// If this button has a resource ID
//
if (pButtonDescriptors[j].nStringResId)
{
//
// Load the string resource and check to make sure it has a length
//
CSimpleString strText( pButtonDescriptors[j].nStringResId, ToolbarBitmapInfo.ToolbarInstance() );
if (strText.Length())
{
//
// Add the text
//
TBBUTTONINFO ToolBarButtonInfo = {0};
ToolBarButtonInfo.cbSize = sizeof(ToolBarButtonInfo);
ToolBarButtonInfo.dwMask = TBIF_TEXT;
ToolBarButtonInfo.pszText = const_cast<LPTSTR>(strText.String());
SendMessage( hWndToolbar, TB_SETBUTTONINFO, pButtonDescriptors[j].idCommand, reinterpret_cast<LPARAM>(&ToolBarButtonInfo) );
}
}
//
// Exit the inner loop, since we've found a match
//
break;
}
}
}
//
// Tell the toolbar to resize itself
//
SendMessage( hWndToolbar, TB_AUTOSIZE, 0, 0 );
}
}
}
//
// Free the bitmap
//
DeleteBitmap(hBitmap);
}
//
// Resize and place the toolbar as needed
//
if (hWndToolbar && hWndAlign)
{
//
// Get the size of the toolbar
//
SIZE sizeToolbar = {0};
if (SendMessage( hWndToolbar, TB_GETMAXSIZE, 0, reinterpret_cast<LPARAM>(&sizeToolbar)))
{
//
// Get the size of the placement window
//
CSimpleRect rcFrameWnd = CSimpleRect( hWndAlign, CSimpleRect::WindowRect ).ScreenToClient(hWndParent);
//
// Determine how to align horizontally
//
int nOriginX = rcFrameWnd.left;
if (Alignment & AlignHCenter)
{
nOriginX = rcFrameWnd.left + (rcFrameWnd.Width() - sizeToolbar.cx) / 2;
}
else if (Alignment & AlignRight)
{
nOriginX = rcFrameWnd.right - sizeToolbar.cx;
}
int nOriginY = rcFrameWnd.top;
if (Alignment & AlignVCenter)
{
nOriginY = rcFrameWnd.top + (rcFrameWnd.Height() - sizeToolbar.cy) / 2;
}
else if (Alignment & AlignBottom)
{
nOriginY = rcFrameWnd.bottom - sizeToolbar.cy;
}
//
// Move and size the toolbar
//
SetWindowPos( hWndToolbar, NULL, nOriginX, nOriginY, sizeToolbar.cx, sizeToolbar.cy, SWP_NOZORDER|SWP_NOACTIVATE );
}
}
if (hWndToolbar && hWndPrevious)
{
SetWindowPos( hWndToolbar, hWndPrevious, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE );
}
return hWndToolbar;
}
void SetToolbarButtonState( HWND hWndToolbar, int nButtonId, int nState )
{
int nCurrentState = static_cast<int>(SendMessage(hWndToolbar,TB_GETSTATE,nButtonId,0));
if (nCurrentState != -1)
{
if (nCurrentState ^ nState)
{
SendMessage(hWndToolbar,TB_SETSTATE,nButtonId,MAKELONG(nState,0));
}
}
}
void EnableToolbarButton( HWND hWndToolbar, int nButtonId, bool bEnable )
{
WIA_PUSH_FUNCTION((TEXT("EnableToolbarButton")));
int nCurrentState = static_cast<int>(SendMessage(hWndToolbar,TB_GETSTATE,nButtonId,0));
if (nCurrentState != -1)
{
if (bEnable)
{
nCurrentState |= TBSTATE_ENABLED;
}
else
{
nCurrentState &= ~TBSTATE_ENABLED;
}
SetToolbarButtonState( hWndToolbar, nButtonId, nCurrentState );
}
//
// If there are no enabled buttons, remove the WS_TABSTOP bit. If there are,
// make sure we add it back in.
//
//
// Assume we don't need the WS_TABSTOP style
//
bool bTabStop = false;
//
// Loop through all of the buttons in the control
//
for (int i=0;i<SendMessage(hWndToolbar,TB_BUTTONCOUNT,0,0);++i)
{
//
// Get the button info for each button
//
TBBUTTON TbButton = {0};
if (SendMessage(hWndToolbar,TB_GETBUTTON,i,reinterpret_cast<LPARAM>(&TbButton)))
{
WIA_TRACE((TEXT("TbButton: %d, %d, %04X, %04X, %08X, %p"), TbButton.iBitmap, TbButton.idCommand, TbButton.fsState, TbButton.fsStyle, TbButton.dwData, TbButton.iString ));
//
// If this button is enabled, set bTabStop to true and pop out of the loop
if (!(TbButton.fsStyle & BTNS_SEP) && TbButton.fsState & TBSTATE_ENABLED)
{
bTabStop = true;
break;
}
}
}
//
// Get the current window style and save a copy, so we don't
// call SetWindowLong for no reason.
//
LONG nStyle = GetWindowLong( hWndToolbar, GWL_STYLE );
LONG nCurrent = nStyle;
//
// Calculate the new style
//
if (bTabStop)
{
nStyle |= WS_TABSTOP;
}
else
{
nStyle &= ~WS_TABSTOP;
}
//
// If the new style doesn't match the old one, set the style
//
if (nStyle != nCurrent)
{
SetWindowLong( hWndToolbar, GWL_STYLE, nStyle );
}
}
bool GetAccelerator( LPCTSTR pszString, TCHAR &chAccel )
{
//
// & marks an accelerator
//
const TCHAR c_chAccelFlag = TEXT('&');
//
// Assume we won't find an accelerator
//
chAccel = 0;
//
// Loop through the string
//
LPCTSTR pszCurr = pszString;
while (pszString && *pszString)
{
//
// If this is the marker character
//
if (c_chAccelFlag == *pszCurr)
{
//
// Get the next character.
//
pszCurr = CharNext(pszCurr);
//
// Make sure this isn't a && situation. If it isn't, save the accelerator and break out.
//
if (c_chAccelFlag != *pszCurr)
{
chAccel = reinterpret_cast<TCHAR>(CharUpper(reinterpret_cast<LPTSTR>(*pszCurr)));
break;
}
}
//
// It is OK to call this even if we are on the end of the string already
//
pszCurr = CharNext(pszCurr);
}
return (0 != chAccel);
}
UINT GetButtonBarAccelerators( HWND hWndToolbar, ACCEL *pAccelerators, UINT nMaxCount )
{
WIA_PUSH_FUNCTION((TEXT("GetButtonBarAccelerators")));
//
// We can't exceed the maximum number of buttons
//
UINT nCurrAccel=0;
//
// Loop through all of the buttons in the control
//
for (LRESULT i=0;i<SendMessage(hWndToolbar,TB_BUTTONCOUNT,0,0) && nCurrAccel < nMaxCount;++i)
{
//
// Get the button info for each button, so we can get the ID
//
TBBUTTON TbButton = {0};
if (SendMessage(hWndToolbar,TB_GETBUTTON,i,reinterpret_cast<LPARAM>(&TbButton)))
{
WIA_TRACE((TEXT("TbButton: %d, %d, %04X, %04X, %08X, %p"), TbButton.iBitmap, TbButton.idCommand, TbButton.fsState, TbButton.fsStyle, TbButton.dwData, TbButton.iString ));
//
// Ignore separators
//
if (!(TbButton.fsStyle & BTNS_SEP))
{
//
// Get the button text.
//
TCHAR szButtonText[MAX_PATH]={0};
if (-1 != SendMessage(hWndToolbar,TB_GETBUTTONTEXT,TbButton.idCommand,reinterpret_cast<LPARAM>(szButtonText)))
{
//
// Get the accelerator (if any)
//
TCHAR chAccel = 0;
if (GetAccelerator( szButtonText, chAccel ))
{
//
// Create an ACCEL record
//
pAccelerators[nCurrAccel].cmd = static_cast<WORD>(TbButton.idCommand);
pAccelerators[nCurrAccel].fVirt = FALT|FVIRTKEY;
pAccelerators[nCurrAccel].key = chAccel;
//
// One more accelerator
//
nCurrAccel++;
}
}
}
}
}
#if defined(DBG)
for (UINT i=0;i<nCurrAccel;i++)
{
WIA_TRACE((TEXT("pAccelerators[%d].fVirt = 0x%02X, 0x%04X (%c), 0x%04X"), i, pAccelerators[i].fVirt, pAccelerators[i].key, pAccelerators[i].key, pAccelerators[i].cmd ));
}
#endif
return nCurrAccel;
}
void CheckToolbarButton( HWND hWndToolbar, int nButtonId, bool bChecked )
{
int nCurrentState = static_cast<int>(SendMessage(hWndToolbar,TB_GETSTATE,nButtonId,0));
if (nCurrentState != -1)
{
if (bChecked)
{
nCurrentState |= TBSTATE_CHECKED;
}
else
{
nCurrentState &= ~TBSTATE_CHECKED;
}
SetToolbarButtonState( hWndToolbar, nButtonId, nCurrentState );
}
}
}