NGenericToolBar.cpp
资源名称:VCMenu.zip [点击查看]
上传用户:whjcdz88
上传日期:2007-01-02
资源大小:350k
文件大小:28k
源码类别:
工具条
开发平台:
Visual C++
- // NGenericToolBar.cpp: implementation of the CNGenericToolBar class.
- //
- /*
- Copyright (C) 1998 Tony Hoyle (tmh@netfusion.co.uk)
- This program is free software; you can redistribute it and/or modify it under the terms
- of the GNU General Public License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along with this program;
- if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "NGenericToolBar.h"
- #include "NGenericMenu.h"
- #include "afxpriv.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- IMPLEMENT_DYNAMIC(CNGenericToolBar,CToolBar)
- BEGIN_MESSAGE_MAP(CNGenericToolBar,CToolBar)
- //{{AFX_MSG_MAP(CNGenericToolBar)
- ON_WM_CONTEXTMENU()
- ON_WM_DESTROY()
- ON_WM_PAINT()
- ON_WM_NCCALCSIZE()
- ON_WM_NCPAINT()
- ON_WM_NCHITTEST()
- ON_WM_WINDOWPOSCHANGING()
- //}}AFX_MSG_MAP
- ON_COMMAND(IDM_BUTTONSONLY,OnButtonsOnly)
- ON_COMMAND(IDM_BUTTONSANDTEXT,OnTextAndButtons)
- ON_COMMAND(IDM_TEXTONLY,OnTextOnly)
- ON_COMMAND(IDM_RECALCSIZE,OnRecalcSize)
- END_MESSAGE_MAP()
- CArray<CNGenericToolBar*,CNGenericToolBar*> CNGenericToolBar::m_ToolbarList;
- BOOL CNGenericToolBar::m_bButtons=FALSE;
- BOOL CNGenericToolBar::m_bText=FALSE;
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CNGenericToolBar::CNGenericToolBar()
- {
- m_bHasText=FALSE;
- m_bHasBitmaps=TRUE;
- m_bForceText=FALSE;
- m_bSysMenuIcon=FALSE;
- m_dwGenericToolBarStyle = 0x0000;
- }
- CNGenericToolBar::~CNGenericToolBar()
- {
- }
- void CNGenericToolBar::OnRecalcSize()
- {
- SettingChange();
- RecalcSize();
- GetParentFrame()->DelayRecalcLayout();
- }
- void CNGenericToolBar::SettingChange()
- {
- TBBUTTON tb;
- for(int n=0; n<GetCount(); n++)
- {
- SendMessage(TB_GETBUTTON,n,(LPARAM)&tb);
- tb.iString=m_bText?m_TextIds[n]:-1;
- _SetButton(n,&tb);
- }
- SendMessage(TB_SETMAXTEXTROWS,m_bText||m_bForceText?4:0);
- SendMessage(TB_SETBITMAPSIZE,0,m_bButtons&&m_bHasBitmaps?MAKELONG(16,15):0);
- SendMessage(TB_AUTOSIZE);
- }
- BOOL CNGenericToolBar::RecalcSize()
- {
- CRect rect;
- int cx=0,cy=0;
- SendMessage(TB_AUTOSIZE);
- for(int n=0; n<GetToolBarCtrl().GetButtonCount(); n++)
- {
- GetItemRect(n,&rect);
- if(rect.Width()>cx) cx=rect.Width();
- if(rect.Height()>cy) cy=rect.Height();
- }
- m_sizeButton.cx=cx;
- m_sizeButton.cy=cy-2;
- m_bDelayedButtonLayout=TRUE;
- ::InvalidateRect(*this,NULL,FALSE);
- return TRUE;
- }
- BOOL CNGenericToolBar::CreateEx(CWnd* pParentWnd, DWORD dwExStyle, DWORD dwStyle, UINT nID, LPCTSTR szTitle)
- {
- if(!CToolBar::Create(pParentWnd,dwStyle,nID)) return FALSE;
- if(szTitle) SetWindowText(szTitle);
- m_pParent=pParentWnd;
- ModifyStyle(0,dwExStyle);
- m_pop.CreatePopupMenu();
- m_pop.AppendMenu(MF_STRING,IDM_BUTTONSONLY,"&Buttons");
- m_pop.AppendMenu(MF_STRING,IDM_BUTTONSANDTEXT,"Buttons &and Text");
- m_pop.AppendMenu(MF_STRING,IDM_TEXTONLY,"&Text");
- m_ToolbarList.Add(this);
- return TRUE;
- }
- BOOL CNGenericToolBar::LoadToolBar(LPCTSTR lpszResourceName)
- {
- if(!CToolBar::LoadToolBar(lpszResourceName)) return FALSE;
- CString tmp;
- LPCTSTR p,q;
- SendMessage(TB_SETMAXTEXTROWS,4);
- m_accelList.SetSize(0);
- for(int n=0; n<GetCount(); n++)
- {
- if(GetItemID(n)!=-1)
- {
- tmp.LoadString(GetItemID(n));
- p=tmp;
- while(*p && *p!='n')
- p++;
- if(*p)
- {
- p++;
- while(*p && *p!='n')
- p++;
- }
- if(*p)
- {
- for(q=p; *q; q++)
- {
- if(*q=='&')
- {
- int s=m_accelList.GetSize();
- m_accelList.SetSize(s+1);
- m_accelList[s].nKey=toupper(*(q+1));
- m_accelList[s].nId=GetItemID(n);
- break;
- }
- }
- SetButtonText(n,p+1);
- m_bHasText=TRUE;
- m_bText=TRUE;
- }
- else
- {
- if(m_bHasText) SetButtonText(n," ");
- }
- }
- }
- TBBUTTON tb;
- m_TextIds.SetSize(0);
- for(n=0; n<GetCount(); n++)
- {
- SendMessage(TB_GETBUTTON,n,(LPARAM)&tb);
- m_TextIds.Add(tb.iString);
- tb.iString=m_bText?m_TextIds[n]:-1;
- }
- m_bButtons = TRUE;
- OnRecalcSize();
- return TRUE;
- }
- BOOL CNGenericToolBar::SetButtonText(int nIndex, LPCTSTR lpszText)
- {
- if(!CToolBar::SetButtonText(nIndex,lpszText)) return FALSE;
- return RecalcSize();
- }
- void CNGenericToolBar::OnContextMenu(CWnd* pWnd, CPoint point)
- {
- m_pop.CheckMenuItem(IDM_BUTTONSONLY,m_bButtons&&!m_bText?MF_CHECKED:MF_UNCHECKED);
- m_pop.CheckMenuItem(IDM_BUTTONSANDTEXT,m_bButtons&&m_bText?MF_CHECKED:MF_UNCHECKED);
- m_pop.CheckMenuItem(IDM_TEXTONLY,!m_bButtons&&m_bText?MF_CHECKED:MF_UNCHECKED);
- m_pop.EnableMenuItem(IDM_BUTTONSONLY,MF_ENABLED);
- m_pop.EnableMenuItem(IDM_BUTTONSANDTEXT,m_bHasText?MF_ENABLED:MF_GRAYED);
- m_pop.EnableMenuItem(IDM_TEXTONLY,m_bHasText?MF_ENABLED:MF_GRAYED);
- m_pop.TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,pWnd);
- }
- void CNGenericToolBar::OnButtonsOnly()
- {
- if(!m_bText && m_bButtons) return;
- m_bText=FALSE;
- m_bButtons=TRUE;
- SendToAllToolbars(WM_COMMAND,IDM_RECALCSIZE);
- }
- void CNGenericToolBar::OnTextOnly()
- {
- if(m_bText && !m_bButtons) return;
- m_bText=TRUE;
- m_bButtons=FALSE;
- SendToAllToolbars(WM_COMMAND,IDM_RECALCSIZE);
- }
- void CNGenericToolBar::OnTextAndButtons()
- {
- if(m_bText && m_bButtons) return;
- m_bText=TRUE;
- m_bButtons=TRUE;
- SendToAllToolbars(WM_COMMAND,IDM_RECALCSIZE);
- }
- void CNGenericToolBar::OnDestroy()
- {
- CToolBar::OnDestroy();
- for(int n=0; n<m_ToolbarList.GetSize(); n++)
- if(m_ToolbarList[n]==this)
- {
- m_ToolbarList.RemoveAt(n);
- break;
- }
- }
- void CNGenericToolBar::SendToAllToolbars(UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- for(int n=0; n<m_ToolbarList.GetSize(); n++)
- m_ToolbarList[n]->SendMessage(uMsg,wParam,lParam);
- }
- void CNGenericToolBar::SetVisualState(BOOL bButtons, BOOL bText)
- {
- if(!bText && !bButtons) bButtons=TRUE;
- m_bText=bText;
- m_bButtons=bButtons;
- SendToAllToolbars(WM_COMMAND,IDM_RECALCSIZE);
- }
- BOOL CNGenericToolBar::GetVisualState(BOOL bText)
- {
- if(bText) return m_bText;
- else return m_bButtons;
- }
- // Borrowed from MFC
- void CNGenericToolBar::_SetButton(int nIndex, TBBUTTON* pButton)
- {
- // get original button state
- TBBUTTON button;
- VERIFY(DefWindowProc(TB_GETBUTTON, nIndex, (LPARAM)&button));
- // prepare for old/new button comparsion
- button.bReserved[0] = 0;
- button.bReserved[1] = 0;
- // TBSTATE_ENABLED == TBBS_DISABLED so invert it
- pButton->fsState ^= TBSTATE_ENABLED;
- pButton->bReserved[0] = 0;
- pButton->bReserved[1] = 0;
- // nothing to do if they are the same
- if (memcmp(pButton, &button, sizeof(TBBUTTON)) != 0)
- {
- // don't redraw everything while setting the button
- DWORD dwStyle = GetStyle();
- ModifyStyle(WS_VISIBLE, 0);
- VERIFY(DefWindowProc(TB_DELETEBUTTON, nIndex, 0));
- VERIFY(DefWindowProc(TB_INSERTBUTTON, nIndex, (LPARAM)pButton));
- ModifyStyle(0, dwStyle & WS_VISIBLE);
- // invalidate appropriate parts
- if (((pButton->fsStyle ^ button.fsStyle) & TBSTYLE_SEP) ||
- ((pButton->fsStyle & TBSTYLE_SEP) && pButton->iBitmap != button.iBitmap))
- {
- // changing a separator
- Invalidate(FALSE);
- }
- else
- {
- // invalidate just the button
- CRect rect;
- SendMessage(TB_AUTOSIZE);
- if (DefWindowProc(TB_GETITEMRECT, nIndex, (LPARAM)&rect))
- InvalidateRect(rect, FALSE); // don't erase background
- }
- }
- }
- // Calculate the non-client area - adjusting for grippers
- void CNGenericToolBar::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
- {
- CToolBar::OnNcCalcSize(bCalcValidRects,lpncsp);
- // adjust non-client area for gripper at left or top
- if (m_dwStyle & CBRS_FLOATING)
- { // no grippers
- }
- else if (m_dwStyle & CBRS_ORIENT_HORZ)
- {
- // move 2 pixels right to make room
- lpncsp->rgrc[0].left += 2;
- lpncsp->rgrc[0].right += 2;
- lpncsp->rgrc[0].top += 2;
- lpncsp->rgrc[0].bottom += 2;
- }
- else
- { // move 4 pixels downto make room
- lpncsp->rgrc[0].top += 4;
- lpncsp->rgrc[0].bottom += 4;
- }
- }
- // Draw the gripper at left or top
- void CNGenericToolBar::DrawGripper(CWindowDC *pDC, CRect& rectWindow)
- {
- // get the gripper rect (1 pixel smaller than toolbar)
- CRect gripper = rectWindow;
- gripper.DeflateRect(1,1);
- if (m_dwStyle & CBRS_FLOATING)
- { // no grippers
- }
- else if (m_dwStyle & CBRS_ORIENT_HORZ)
- { // gripper at left
- gripper.right = gripper.left+3;
- pDC->Draw3dRect(gripper,::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DSHADOW));
- gripper.OffsetRect(+4,0);
- pDC->Draw3dRect(gripper,::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DSHADOW));
- rectWindow.left += 8;
- } else
- { // gripper at top
- gripper.bottom = gripper.top+3;
- pDC->Draw3dRect(gripper,::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DSHADOW));
- gripper.OffsetRect(0,+4);
- pDC->Draw3dRect(gripper,::GetSysColor(COLOR_3DHIGHLIGHT),::GetSysColor(COLOR_3DSHADOW));
- rectWindow.top += 8;
- }
- }
- void CNGenericToolBar::DrawSysMenuIcon(CWindowDC* pDC, CRect& rectWindow)
- {
- if(!m_bSysMenuIcon) return; // Do nothing if this isn't needed
- if(m_dwStyle&CBRS_ORIENT_HORZ)
- {
- DrawIconEx(*pDC,rectWindow.left+2,rectWindow.top+6,m_hSysMenuIcon,16,16,0,NULL,DI_NORMAL);
- m_rectSysMenu.SetRect(rectWindow.left+2,rectWindow.top+6,rectWindow.left+2+16,rectWindow.top+6+16);
- rectWindow.left+=16;
- }
- else
- {
- DrawIconEx(*pDC,rectWindow.left+12,rectWindow.top+2,m_hSysMenuIcon,16,16,0,NULL,DI_NORMAL);
- m_rectSysMenu.SetRect(rectWindow.left+12,rectWindow.top+2,rectWindow.left+12+16,rectWindow.top+2+16);
- rectWindow.top+=16;
- }
- }
- // Erase the non-client area (borders) - copied from MFC implementation
- void CNGenericToolBar::EraseNonClient(BOOL bRaised)
- {
- // get window DC that is clipped to the non-client area
- CWindowDC dc(this);
- CRect rectClient;
- GetClientRect(rectClient);
- CRect rectWindow;
- GetWindowRect(rectWindow);
- ScreenToClient(rectWindow);
- rectClient.OffsetRect(-rectWindow.left, -rectWindow.top);
- dc.ExcludeClipRect(rectClient); // draw borders in non-client area
- rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);
- DrawBorders(&dc, rectWindow); // erase parts not drawn
- dc.IntersectClipRect(rectWindow);
- SendMessage(WM_ERASEBKGND, (WPARAM)dc.m_hDC);
- DrawGripper(&dc, rectWindow); // <-- my addition to draw gripper}
- DrawSysMenuIcon(&dc, rectWindow); // Draw icon for system menu, if needed
- }
- BOOL CNGenericToolBar::TranslateMenuChar(UINT nChar)
- {
- for(int n=0; n<m_accelList.GetSize(); n++)
- {
- if(m_accelList[n].nKey==(UINT)toupper(nChar))
- {
- m_pParent->PostMessage(WM_COMMAND,m_accelList[n].nId);
- return TRUE;
- }
- }
- return FALSE;
- }
- BOOL CNGenericToolBar::KeyboardFilter(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- return FALSE;
- }
- void CNGenericToolBar::DrawBorders(CDC* pDC, CRect& rect)
- {
- ASSERT_VALID(this);
- ASSERT_VALID(pDC);
- DWORD dwStyle = m_dwStyle;
- if (!(dwStyle & CBRS_BORDER_ANY))
- return;
- // prepare for dark lines
- ASSERT(rect.top == 0 && rect.left == 0);
- COLORREF clr=GetSysColor(COLOR_3DSHADOW);
- if(dwStyle&CBRS_BORDER_RIGHT)
- pDC->FillSolidRect(rect.right-1,0,rect.right,rect.bottom,clr); //right
- if(dwStyle&CBRS_BORDER_BOTTOM)
- pDC->FillSolidRect(0,rect.bottom-1,rect.right,rect.bottom,clr); //bottom
- clr=GetSysColor(COLOR_3DHIGHLIGHT);
- if(dwStyle&CBRS_BORDER_TOP)
- pDC->FillSolidRect(0,0,rect.right,1,clr); //top
- if(dwStyle&CBRS_BORDER_LEFT)
- pDC->FillSolidRect(0,0,1,rect.bottom,clr); //left
- if(dwStyle&CBRS_BORDER_TOP)
- rect.top++;
- if(dwStyle&CBRS_BORDER_RIGHT)
- rect.right--;
- if(dwStyle&CBRS_BORDER_BOTTOM)
- rect.bottom--;
- if(dwStyle&CBRS_BORDER_LEFT)
- rect.left++;
- }
- // Because buttons are transparent, we need to repaint the background
- void CNGenericToolBar::RepaintBackground()
- {
- // get parent window (there should be one)
- CWnd* pParent = GetParent();
- if (pParent)
- {
- // get rect for this toolbar
- CRect rw; GetWindowRect(&rw);
- // convert rect to parent coords
- CRect rc = rw; pParent->ScreenToClient(&rc);
- // invalidate this part of parent
- pParent->InvalidateRect(&rc);
- // now do all the other toolbars (etc) that belong to the parent
- for (CWnd* pSibling = pParent->GetWindow(GW_CHILD); pSibling; pSibling = pSibling->GetNextWindow(GW_HWNDNEXT))
- {
- // but do not draw ourselves
- if (pSibling == this) continue;
- // convert rect to siblings coords
- CRect rc = rw; pSibling->ScreenToClient(&rc);
- // invalidate this part of sibling
- pSibling->InvalidateRect(&rc);
- }
- }
- }
- // Revised by Zhenxin Li.
- // I remove these two functions, then the separators are drawn correctly.
- // I don't know why.
- // Draw the separators in the client area
- void CNGenericToolBar::DrawSeparators()
- {
- // get a dc for the client area
- // CClientDC dc(this);
- // draw the separators on it
- // DrawSeparators(&dc);
- }
- // Draw the separators
- void CNGenericToolBar::DrawSeparators(CClientDC* pDC)
- {
- /* // horizontal vs vertical
- bool ishorz = (m_dwStyle & CBRS_ORIENT_HORZ) != 0;
- // get number of buttons
- int nIndexMax = (int)DefWindowProc(TB_BUTTONCOUNT, 0, 0);
- int nIndex;
- // try each button
- for (nIndex = 0; nIndex < nIndexMax; nIndex++)
- {
- UINT dwStyle = GetButtonStyle(nIndex);
- UINT wStyle = LOWORD(dwStyle);
- // if it is a separator
- if (wStyle == TBBS_SEPARATOR)
- {
- // get it's rectangle and width
- CRect rect;
- GetItemRect(nIndex,rect);
- // if small enough to be a true separator
- int w = rect.Width();
- if (w <= 8)
- {
- if (ishorz)
- {
- // draw the separator bar in the middle
- CRect rectbar = rect;
- int x = (rectbar.left+rectbar.right)/2;
- rectbar.left = x-1; rectbar.right = x+1;
- rectbar.top++;
- rectbar.bottom++;
- pDC->Draw3dRect(rectbar,::GetSysColor(COLOR_3DSHADOW),::GetSysColor(COLOR_3DHILIGHT));
- }
- else
- {
- // draw the separator bar in the middle
- CRect rectbar = rect;
- rectbar.left = rectbar.left - m_sizeButton.cx;
- rectbar.right = rectbar.left + m_sizeButton.cx;
- rectbar.top = rectbar.bottom+1;
- rectbar.bottom = rectbar.top+3;
- int y = (rectbar.top+rectbar.bottom)/2;
- rectbar.top = y-1; rectbar.bottom = y+1;
- pDC->Draw3dRect(rectbar,::GetSysColor(COLOR_3DSHADOW),::GetSysColor(COLOR_3DHILIGHT));
- }
- }
- }
- }*/
- }
- // Because buttons are transparent, we need to repaint background if style changes
- void CNGenericToolBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
- {
- static CUIntArray styles;
- // get the number of buttons
- int nIndexMax = (int)DefWindowProc(TB_BUTTONCOUNT, 0, 0);
- int nIndex;
- // save styles
- for (nIndex = 0; nIndex < nIndexMax; nIndex++)
- {
- UINT dwStyle = GetButtonStyle(nIndex);
- styles.SetAtGrow(nIndex,dwStyle);
- }
- // do base class processing
- CToolBar::OnUpdateCmdUI(pTarget,bDisableIfNoHndler);
- // make checked button appear pushed in
- for (nIndex = 0; nIndex < nIndexMax; nIndex++)
- {
- UINT dwStyle = GetButtonStyle(nIndex);
- if (dwStyle & TBBS_DISABLED)
- {
- // don't touch if disabled (avoids flicker)
- } else if (dwStyle & TBBS_CHECKBOX)
- {
- UINT dwStyleWas = dwStyle;
- // if checked, make it pressed, else not pressed
- if (dwStyle & TBBS_CHECKED)
- {
- dwStyle |= TBBS_PRESSED;
- } else if (!(styles[nIndex]&TBBS_CHECKED) && (styles[nIndex]&TBBS_PRESSED))
- {
- dwStyle |= TBBS_PRESSED;
- } else
- {
- dwStyle &= ~TBBS_PRESSED;
- }
- // set new style if changed
- if (dwStyleWas != dwStyle) SetButtonStyle(nIndex,dwStyle);
- }
- }
- // check for changes to style (buttons presssed/released)
- for (nIndex = 0; nIndex < nIndexMax; nIndex++)
- {
- UINT dwStyle = GetButtonStyle(nIndex);
- if (styles[nIndex] != dwStyle)
- {
- // repaint whole toolbar (not just this button)
- Invalidate();
- // no need to check any more
- break;
- }
- }
- }
- // Because buttons are transparent, we need to repaint background on size or move
- void CNGenericToolBar::OnWindowPosChanging(LPWINDOWPOS lpwp)
- {
- // default processing
- CToolBar::OnWindowPosChanging(lpwp);
- RepaintBackground();
- }
- // Paint the toolbar
- void CNGenericToolBar::OnPaint()
- {
- // standard toolbar
- CToolBar::OnPaint();
- // erase the background
- EraseNonClient(FALSE);
- // plus separators
- DrawSeparators();
- }
- // Paint the non-client area - copied from MFC implementatios
- void CNGenericToolBar::OnNcPaint()
- {
- // EraseNonClient(); don't do it here
- }
- UINT CNGenericToolBar::OnNcHitTest(CPoint point)
- {
- CPoint pt(point);
- CRect wRect;
- GetWindowRect(wRect);
- pt.x-=wRect.left;
- pt.y-=wRect.top;
- // If SysMenu icon is visible, hittest it specially
- if(m_bSysMenuIcon && m_rectSysMenu.PtInRect(pt))
- {
- OnOverSysMenu();
- return HTSYSMENU;
- }
- return CToolBar::OnNcHitTest(point);
- }
- BOOL CNGenericToolBar::GenericToolBarModifyStyle(DWORD dwRemove, DWORD dwAdd)
- {
- DWORD dwStyle = m_dwGenericToolBarStyle;
- DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
- if (dwStyle == dwNewStyle)
- return FALSE;
- m_dwGenericToolBarStyle = dwNewStyle;
- return TRUE;
- }
- CSize CNGenericToolBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
- {
- DWORD dwMode = bStretch ? LM_STRETCH : 0;
- dwMode |= bHorz ? LM_HORZ : 0;
- CSize s = CalcLayout(dwMode);
- // Revised by Zhenxin Li.
- // Make room for gripper.
- if (m_dwStyle&CBRS_ORIENT_HORZ)
- s.cx += 2;
- else
- s.cy += 4;
- return s;
- }
- // Revised by Zhenxin Li.
- // Borrow from MFC source. Make a little change.
- void CNGenericToolBar::_GetButton(int nIndex, TBBUTTON* pButton) const
- {
- CNGenericToolBar* pBar = (CNGenericToolBar*)this;
- VERIFY(pBar->DefWindowProc(TB_GETBUTTON, nIndex, (LPARAM)pButton));
- // TBSTATE_ENABLED == TBBS_DISABLED so invert it
- pButton->fsState ^= TBSTATE_ENABLED;
- }
- #ifdef _MAC
- #define CX_OVERLAP 1
- #else
- #define CX_OVERLAP 0
- #endif
- struct _AFX_CONTROLPOS
- {
- int nIndex, nID;
- CRect rectOldPos;
- };
- // Revised by Zhenxin Li.
- // Borrow from MFC source. Recalculate each button's m_sizeButton value.
- int CNGenericToolBar::WrapToolBar(TBBUTTON* pData, int nCount, int nWidth)
- {
- ASSERT(pData != NULL && nCount > 0);
- int nResult = 0;
- int x = 0;
- CSize m_sizeButton = CToolBar::m_sizeButton;
- m_sizeButton.cy += 2;
- BOOL bMenuClass = IsKindOf(RUNTIME_CLASS(CNGenericMenu));
- for (int i = 0; i < nCount; i++)
- {
- pData[i].fsState &= ~TBSTATE_WRAP;
- if (pData[i].fsState & TBSTATE_HIDDEN)
- continue;
- if (bMenuClass)
- {
- CRect r;
- DefWindowProc(TB_GETITEMRECT, i, (LPARAM)&r);
- m_sizeButton = CSize(r.right-r.left, r.bottom-r.top);
- }
- int dx, dxNext;
- if (pData[i].fsStyle & TBSTYLE_SEP)
- {
- dx = pData[i].iBitmap;
- dxNext = dx;
- }
- else
- {
- dx = m_sizeButton.cx;
- dxNext = dx - CX_OVERLAP;
- }
- if (x + dx > nWidth)
- {
- BOOL bFound = FALSE;
- for (int j = i; j >= 0 && !(pData[j].fsState & TBSTATE_WRAP); j--)
- {
- // Find last separator that isn't hidden
- // a separator that has a command ID is not
- // a separator, but a custom control.
- if ((pData[j].fsStyle & TBSTYLE_SEP) &&
- (pData[j].idCommand == 0) &&
- !(pData[j].fsState & TBSTATE_HIDDEN))
- {
- bFound = TRUE; i = j; x = 0;
- pData[j].fsState |= TBSTATE_WRAP;
- nResult++;
- break;
- }
- }
- if (!bFound)
- {
- for (int j = i - 1; j >= 0 && !(pData[j].fsState & TBSTATE_WRAP); j--)
- {
- // Never wrap anything that is hidden,
- // or any custom controls
- if ((pData[j].fsState & TBSTATE_HIDDEN) ||
- ((pData[j].fsStyle & TBSTYLE_SEP) &&
- (pData[j].idCommand != 0)))
- continue;
- bFound = TRUE; i = j; x = 0;
- pData[j].fsState |= TBSTATE_WRAP;
- nResult++;
- break;
- }
- if (!bFound)
- x += dxNext;
- }
- }
- else
- x += dxNext;
- }
- return nResult + 1;
- }
- // Revised by Zhenxin Li.
- // Must borrow from MFC source, because this function is not virtual.
- // If not borrow, the new CalcSize function won't be called.
- void CNGenericToolBar::SizeToolBar(TBBUTTON* pData, int nCount, int nLength, BOOL bVert)
- {
- ASSERT(pData != NULL && nCount > 0);
- if (!bVert)
- {
- int nMin, nMax, nTarget, nCurrent, nMid;
- // Wrap ToolBar as specified
- nMax = nLength;
- nTarget = WrapToolBar(pData, nCount, nMax);
- // Wrap ToolBar vertically
- nMin = 0;
- nCurrent = WrapToolBar(pData, nCount, nMin);
- if (nCurrent != nTarget)
- {
- while (nMin < nMax)
- {
- nMid = (nMin + nMax) / 2;
- nCurrent = WrapToolBar(pData, nCount, nMid);
- if (nCurrent == nTarget)
- nMax = nMid;
- else
- {
- if (nMin == nMid)
- {
- WrapToolBar(pData, nCount, nMax);
- break;
- }
- nMin = nMid;
- }
- }
- }
- CSize size = CalcSize(pData, nCount);
- WrapToolBar(pData, nCount, size.cx);
- }
- else
- {
- CSize sizeMax, sizeMin, sizeMid;
- // Wrap ToolBar vertically
- WrapToolBar(pData, nCount, 0);
- sizeMin = CalcSize(pData, nCount);
- // Wrap ToolBar horizontally
- WrapToolBar(pData, nCount, 32767);
- sizeMax = CalcSize(pData, nCount);
- while (sizeMin.cx < sizeMax.cx)
- {
- sizeMid.cx = (sizeMin.cx + sizeMax.cx) / 2;
- WrapToolBar(pData, nCount, sizeMid.cx);
- sizeMid = CalcSize(pData, nCount);
- if (nLength < sizeMid.cy)
- {
- if (sizeMin == sizeMid)
- {
- WrapToolBar(pData, nCount, sizeMax.cx);
- return;
- }
- sizeMin = sizeMid;
- }
- else if (nLength > sizeMid.cy)
- sizeMax = sizeMid;
- else
- return;
- }
- }
- }
- CSize CNGenericToolBar::CalcSize(TBBUTTON* pData, int nCount)
- {
- ASSERT(pData != NULL && nCount > 0);
- CPoint cur(0,0);
- CSize sizeResult(0,0);
- CSize m_sizeButton = CToolBar::m_sizeButton;
- m_sizeButton.cy += 2;
- BOOL bMenuClass = IsKindOf(RUNTIME_CLASS(CNGenericMenu));
- for (int i = 0; i < nCount; i++)
- {
- if (pData[i].fsState & TBSTATE_HIDDEN)
- continue;
- if (bMenuClass)
- {
- CRect r;
- DefWindowProc(TB_GETITEMRECT, i, (LPARAM)&r);
- m_sizeButton = CSize(r.right-r.left, r.bottom-r.top);
- }
- if (pData[i].fsStyle & TBSTYLE_SEP)
- {
- // A separator represents either a height or width
- if (pData[i].fsState & TBSTATE_WRAP)
- // Revised by Zhenxin Li
- // Add 3 points for separator in flat toolbar.
- sizeResult.cy = max(cur.y + m_sizeButton.cy + pData[i].iBitmap * 2 / 3, sizeResult.cy) + 3;
- else
- sizeResult.cx = max(cur.x + pData[i].iBitmap, sizeResult.cx);
- }
- else
- {
- sizeResult.cx = max(cur.x + m_sizeButton.cx, sizeResult.cx);
- sizeResult.cy = max(cur.y + m_sizeButton.cy, sizeResult.cy);
- }
- if (pData[i].fsStyle & TBSTYLE_SEP)
- cur.x += pData[i].iBitmap;
- else
- cur.x += m_sizeButton.cx - CX_OVERLAP;
- if (pData[i].fsState & TBSTATE_WRAP)
- {
- cur.x = 0;
- cur.y += m_sizeButton.cy;
- if (pData[i].fsStyle & TBSTYLE_SEP)
- // Revised by Zhenxin Li
- // Like above, add 3 points for separator in flat toolbar.
- cur.y += pData[i].iBitmap * 2 / 3 + 3;
- }
- }
- return sizeResult;
- }
- CSize CNGenericToolBar::CalcLayout(DWORD dwMode, int nLength)
- {
- ASSERT_VALID(this);
- ASSERT(::IsWindow(m_hWnd));
- if (dwMode & LM_HORZDOCK)
- ASSERT(dwMode & LM_HORZ);
- int nCount;
- TBBUTTON* pData;
- CSize sizeResult(0,0);
- // Load Buttons
- {
- nCount = DefWindowProc(TB_BUTTONCOUNT, 0, 0);
- if (nCount != 0)
- {
- int i;
- pData = new TBBUTTON[nCount];
- for (i = 0; i < nCount; i++)
- _GetButton(i, &pData[i]);
- }
- }
- if (nCount > 0)
- {
- if (!(m_dwStyle & CBRS_SIZE_FIXED))
- {
- BOOL bDynamic = m_dwStyle & CBRS_SIZE_DYNAMIC;
- if (bDynamic && (dwMode & LM_MRUWIDTH))
- SizeToolBar(pData, nCount, m_nMRUWidth);
- else if (bDynamic && (dwMode & LM_HORZDOCK))
- SizeToolBar(pData, nCount, 32767);
- else if (bDynamic && (dwMode & LM_VERTDOCK))
- SizeToolBar(pData, nCount, 0);
- else if (bDynamic && (nLength != -1))
- {
- CRect rect; rect.SetRectEmpty();
- CalcInsideRect(rect, (dwMode & LM_HORZ));
- BOOL bVert = (dwMode & LM_LENGTHY);
- int nLen = nLength + (bVert ? rect.Height() : rect.Width());
- SizeToolBar(pData, nCount, nLen, bVert);
- }
- else if (bDynamic && (m_dwStyle & CBRS_FLOATING))
- SizeToolBar(pData, nCount, m_nMRUWidth);
- else
- SizeToolBar(pData, nCount, (dwMode & LM_HORZ) ? 32767 : 0);
- }
- sizeResult = CalcSize(pData, nCount);
- if (dwMode & LM_COMMIT)
- {
- _AFX_CONTROLPOS* pControl = NULL;
- int nControlCount = 0;
- BOOL bIsDelayed = m_bDelayedButtonLayout;
- m_bDelayedButtonLayout = FALSE;
- for(int i = 0; i < nCount; i++)
- if ((pData[i].fsStyle & TBSTYLE_SEP) && (pData[i].idCommand != 0))
- nControlCount++;
- if (nControlCount > 0)
- {
- pControl = new _AFX_CONTROLPOS[nControlCount];
- nControlCount = 0;
- for(int i = 0; i < nCount; i++)
- {
- if ((pData[i].fsStyle & TBSTYLE_SEP) && (pData[i].idCommand != 0))
- {
- pControl[nControlCount].nIndex = i;
- pControl[nControlCount].nID = pData[i].idCommand;
- CRect rect;
- GetItemRect(i, &rect);
- ClientToScreen(&rect);
- pControl[nControlCount].rectOldPos = rect;
- nControlCount++;
- }
- }
- }
- if ((m_dwStyle & CBRS_FLOATING) && (m_dwStyle & CBRS_SIZE_DYNAMIC))
- m_nMRUWidth = sizeResult.cx;
- for (i = 0; i < nCount; i++)
- _SetButton(i, &pData[i]);
- if (nControlCount > 0)
- {
- for (int i = 0; i < nControlCount; i++)
- {
- CWnd* pWnd = GetDlgItem(pControl[i].nID);
- if (pWnd != NULL)
- {
- CRect rect;
- pWnd->GetWindowRect(&rect);
- CPoint pt = rect.TopLeft() - pControl[i].rectOldPos.TopLeft();
- GetItemRect(pControl[i].nIndex, &rect);
- pt = rect.TopLeft() + pt;
- pWnd->SetWindowPos(NULL, pt.x, pt.y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
- }
- }
- delete[] pControl;
- }
- m_bDelayedButtonLayout = bIsDelayed;
- }
- delete[] pData;
- }
- //BLOCK: Adjust Margins
- {
- CRect rect; rect.SetRectEmpty();
- CalcInsideRect(rect, (dwMode & LM_HORZ));
- sizeResult.cy -= rect.Height();
- sizeResult.cx -= rect.Width();
- CSize size = CControlBar::CalcFixedLayout((dwMode & LM_STRETCH), (dwMode & LM_HORZ));
- sizeResult.cx = max(sizeResult.cx, size.cx);
- sizeResult.cy = max(sizeResult.cy, size.cy);
- }
- return sizeResult;
- }
- CSize CNGenericToolBar::CalcDynamicLayout(int nLength, DWORD dwMode)
- {
- CSize s;
- if ((nLength == -1) && !(dwMode & LM_MRUWIDTH) && !(dwMode & LM_COMMIT) &&
- ((dwMode & LM_HORZDOCK) || (dwMode & LM_VERTDOCK)))
- s = CalcFixedLayout(dwMode & LM_STRETCH, dwMode & LM_HORZDOCK);
- else
- s = CalcLayout(dwMode, nLength);
- return s;
- }