/******************************************************************************* * * (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 #include #include #include 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(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(hBitmap); if (-1 != SendMessage( hwndToolbar, TB_ADDBITMAP, ToolbarBitmapInfo.ButtonCount(), reinterpret_cast(&TbAddBitmap) ) ) { ToolbarBitmapInfo.Bitmap(hBitmap); } } SendMessage( hwndToolbar, TB_ADDBUTTONS, nButtonCount, reinterpret_cast(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(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 aActualButtons; for (UINT i=0;i= 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(strText.String()); SendMessage( hWndToolbar, TB_SETBUTTONINFO, pButtonDescriptors[j].idCommand, reinterpret_cast(&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(&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(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(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(&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(CharUpper(reinterpret_cast(*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(&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(szButtonText))) { // // Get the accelerator (if any) // TCHAR chAccel = 0; if (GetAccelerator( szButtonText, chAccel )) { // // Create an ACCEL record // pAccelerators[nCurrAccel].cmd = static_cast(TbButton.idCommand); pAccelerators[nCurrAccel].fVirt = FALT|FVIRTKEY; pAccelerators[nCurrAccel].key = chAccel; // // One more accelerator // nCurrAccel++; } } } } } #if defined(DBG) for (UINT i=0;i(SendMessage(hWndToolbar,TB_GETSTATE,nButtonId,0)); if (nCurrentState != -1) { if (bChecked) { nCurrentState |= TBSTATE_CHECKED; } else { nCurrentState &= ~TBSTATE_CHECKED; } SetToolbarButtonState( hWndToolbar, nButtonId, nCurrentState ); } } }