Toolbarex.cpp
上传用户:shuini
上传日期:2007-02-05
资源大小:103k
文件大小:59k
源码类别:

工具条

开发平台:

Visual C++

  1. // ToolBarEx.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "ToolBarEx.h"
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #undef THIS_FILE
  8. static char THIS_FILE[] = __FILE__;
  9. #endif
  10. /////////////////////////////////////////////////////////////////////////////
  11. // CToolBarEx
  12. IMPLEMENT_DYNCREATE( CToolBarEx,CToolBar);
  13. //Image sizes
  14. const CSize CToolBarEx::m_szImageSmall( 16, 15 );
  15. const CSize CToolBarEx::m_szImageLarge( 24, 24 );
  16. const TextOptions CToolBarEx:: m_eInitialTextOptions =  toNoTextLabels;
  17. const IconOptions CToolBarEx:: m_eInitialIconOptions =  ioSmallIcons;
  18.   
  19. int CToolBarEx::m_nBarNumber = 0;
  20. CCustomizeDialog*   CToolBarEx::m_pCustomizeDlg = NULL;
  21. HHOOK               CToolBarEx::m_hCBTHook      = NULL;
  22. #define STR_CUSTOMIZE  _T("&Customize...")
  23. // for determining version of COMCTL32.DLL
  24. #define VERSION_WIN4        MAKELONG(0, 4)
  25. #define VERSION_IE3         MAKELONG(70, 4)
  26. #define VERSION_IE4         MAKELONG(71, 4)
  27. #define VERSION_IE401       MAKELONG(72, 4)
  28. #define VERSION_IE5 MAKELONG(80, 5)
  29. #define VERSION_IE5_2000    MAKELONG(81, 5)
  30. struct AFX_DLLVERSIONINFO
  31. {
  32. DWORD cbSize;
  33. DWORD dwMajorVersion;                   // Major version
  34. DWORD dwMinorVersion;                   // Minor version
  35. DWORD dwBuildNumber;                    // Build number
  36. DWORD dwPlatformID;                     // DLLVER_PLATFORM_*
  37. };
  38. typedef HRESULT (CALLBACK* AFX_DLLGETVERSIONPROC)(AFX_DLLVERSIONINFO *);
  39. static int _ComCtlVersion = -1;
  40. static DWORD AFXAPI _GetComCtlVersion()
  41. {
  42. // return cached version if already determined...
  43. if (_ComCtlVersion != -1)
  44. return _ComCtlVersion;
  45. // otherwise determine comctl32.dll version via DllGetVersion
  46. HINSTANCE hInst = ::GetModuleHandleA("COMCTL32.DLL");
  47. ASSERT(hInst != NULL);
  48. AFX_DLLGETVERSIONPROC pfn;
  49. pfn = (AFX_DLLGETVERSIONPROC)GetProcAddress(hInst, "DllGetVersion");
  50. DWORD dwVersion = VERSION_WIN4;
  51. if (pfn != NULL)
  52. {
  53. AFX_DLLVERSIONINFO dvi;
  54. memset(&dvi, 0, sizeof(dvi));
  55. dvi.cbSize = sizeof(dvi);
  56. HRESULT hr = (*pfn)(&dvi);
  57. if (SUCCEEDED(hr))
  58. {
  59. ASSERT(dvi.dwMajorVersion <= 0xFFFF);
  60. ASSERT(dvi.dwMinorVersion <= 0xFFFF);
  61. dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion);
  62. }
  63. TRACE(_T("Using CommCtl32.dll Ver:%d.%d.%dn"),dvi.dwMajorVersion,dvi.dwMinorVersion,dvi.dwBuildNumber);
  64. }
  65. _ComCtlVersion = dwVersion;
  66. return dwVersion;
  67. }
  68. CToolBarEx::CToolBarEx()
  69. {
  70. m_pControls  = NULL;
  71. m_pDropButtons  = NULL; // list of drop-down buttons
  72. // m_bShowDropdownArrowWhenVertical = FALSE;
  73. m_bHideChildWndOnVertical=TRUE;
  74. m_clrBtnHilight=::GetSysColor(COLOR_BTNHILIGHT);
  75. m_clrBtnShadow=::GetSysColor(COLOR_BTNSHADOW);
  76. m_clrBtnFace  = ::GetSysColor(COLOR_BTNFACE);
  77. ++m_nBarNumber; //Increase the Bar number
  78. CWinApp  *pApp = AfxGetApp();
  79. ASSERT_VALID(pApp);
  80. m_strValueName.Format( _T("ToolBarEx%d"), m_nBarNumber );
  81. m_strSubKey.Format( _T("Software\%s\%s\Settings"),
  82. pApp->m_pszRegistryKey, pApp->m_pszProfileName );
  83.     m_eTextOptions = toNone;    // no options selected yet
  84.     m_eIconOptions = ioNone;    // no options selected yet
  85. m_nResButtons=0;
  86. }
  87. CToolBarEx::~CToolBarEx()
  88. {
  89. while (m_pDropButtons)
  90. {
  91. CDropDownButtonInfo* pnext = m_pDropButtons->pNext;
  92. delete m_pDropButtons;
  93. m_pDropButtons = pnext;
  94. }
  95. if( m_pControls ) 
  96. {
  97. for( POSITION pos = m_pControls->GetHeadPosition() ; pos ; ) 
  98. {
  99. delete m_pControls->GetNext(pos);
  100. }
  101. delete m_pControls;
  102. }
  103. }
  104. BEGIN_MESSAGE_MAP(CToolBarEx, CToolBar)
  105. //{{AFX_MSG_MAP(CToolBarEx)
  106. ON_WM_CREATE()
  107. ON_WM_PAINT()
  108. ON_WM_SYSCOLORCHANGE()
  109. ON_WM_CONTEXTMENU()
  110. ON_WM_NCPAINT()
  111. //}}AFX_MSG_MAP
  112. ON_NOTIFY_REFLECT_EX(TBN_DROPDOWN,  OnToolBarBtnDropDown)
  113. ON_NOTIFY_REFLECT(TBN_BEGINADJUST,  OnToolBarBeginAdjust)
  114. ON_NOTIFY_REFLECT(TBN_CUSTHELP,  OnToolBarCustomHelp)
  115. ON_NOTIFY_REFLECT(TBN_ENDADJUST,  OnToolBarEndAdjust)
  116. ON_NOTIFY_REFLECT(TBN_GETBUTTONINFO, OnToolBarGetButtonInfo)
  117. ON_NOTIFY_REFLECT(TBN_QUERYDELETE,  OnToolBarQueryDelete)
  118. ON_NOTIFY_REFLECT(TBN_QUERYINSERT,  OnToolBarQueryInsert)
  119. ON_NOTIFY_REFLECT(TBN_RESET,  OnToolBarReset)
  120. ON_NOTIFY_REFLECT(TBN_TOOLBARCHANGE, OnToolBarChange)
  121. ON_MESSAGE(TB_CUSTOMIZE, OnCustomize)
  122.     ON_NOTIFY_REFLECT( TBN_INITCUSTOMIZE, OnInitCustomize )
  123.  //   ON_NOTIFY_REFLECT( NM_CUSTOMDRAW , OnCustomDraw)
  124.     // Saving and restoring toolbar
  125.     ON_NOTIFY_REFLECT( TBN_SAVE, OnSave )
  126.     ON_NOTIFY_REFLECT( TBN_RESTORE, OnRestore )
  127. END_MESSAGE_MAP()
  128. /////////////////////////////////////////////////////////////////////////////
  129. // CToolBarEx message handlers
  130. //////////////////////////////////////////////////////////////////////
  131. // 1999 Kirk Stowell - Inserts a control into the toolbar at the given button id.
  132. //
  133. CWnd* CToolBarEx::InsertControl( CRuntimeClass* pClass, LPCTSTR lpszWindowName, CRect& rect, UINT nID, DWORD dwStyle )
  134. {
  135. CWnd *pCtrl = NULL;
  136. if( pClass->IsDerivedFrom( RUNTIME_CLASS( CComboBox ))) // CComboBox control.
  137. {
  138. pCtrl = new CComboBox;
  139. ASSERT_VALID( pCtrl );
  140. if(((CComboBox*)pCtrl)->Create( WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
  141. {
  142. delete pCtrl;
  143. return NULL;
  144. }
  145. }
  146. else if( pClass->IsDerivedFrom( RUNTIME_CLASS( CEdit ))) // CEdit control.
  147. {
  148. pCtrl = new CEdit;
  149. ASSERT_VALID( pCtrl );
  150. if(((CEdit*)pCtrl)->Create( WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
  151. {
  152. delete pCtrl;
  153. return NULL;
  154. }
  155. }
  156. else if( pClass->IsDerivedFrom( RUNTIME_CLASS( CButton ))) // CButton control.
  157. {
  158. pCtrl = new CButton;
  159. ASSERT_VALID( pCtrl );
  160. if(((CButton*)pCtrl)->Create( lpszWindowName, WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
  161. {
  162. delete pCtrl;
  163. return NULL;
  164. }
  165. }
  166. else if( pClass->IsDerivedFrom( RUNTIME_CLASS( CWnd ))) // CWnd object.
  167. {
  168. pCtrl = new CWnd;
  169. ASSERT_VALID( pCtrl );
  170. #ifdef _UNICODE
  171. TCHAR szClassName[ 256 ];
  172. MultiByteToWideChar( CP_ACP,
  173.  MB_PRECOMPOSED,
  174.  pClass->m_lpszClassName,
  175.  -1,
  176.  szClassName,
  177.  255 );
  178. if(((CWnd*)pCtrl)->Create( szClassName, lpszWindowName, WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
  179. {
  180. delete pCtrl;
  181. return NULL;
  182. }
  183. #else
  184. if(((CWnd*)pCtrl)->Create( pClass->m_lpszClassName, lpszWindowName, WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
  185. {
  186. delete pCtrl;
  187. return NULL;
  188. }
  189. #endif
  190. }
  191. else // An invalid object was passed in
  192. {
  193. ASSERT( FALSE );
  194. return NULL;
  195. }
  196. // if our object list has not been allocated, do it now...
  197. if( m_pControls == NULL )
  198. {
  199. m_pControls = new CObList();
  200. ASSERT( m_pControls );
  201. }
  202. // we have to remember this control, so we can delete it later
  203. m_pControls->AddTail( pCtrl );
  204. return InsertControl( pCtrl, rect, nID );
  205. }
  206. CWnd* CToolBarEx::InsertControl(CWnd* pCtrl, CRect & rect, UINT nID)
  207. {
  208. ASSERT_VALID( pCtrl );
  209. ASSERT(IsWindow(pCtrl->m_hWnd));
  210. // make sure the id is valid, and set the button 
  211. // style for a seperator.
  212. int nIndex = CommandToIndex( nID ) ;
  213. if (nIndex>-1)
  214. {
  215. ASSERT( nIndex >= 0 );
  216. SetButtonInfo( nIndex, nID, TBBS_SEPARATOR, rect.Width());
  217. // insert the control into the toolbar.
  218. GetItemRect( nIndex, &rect );
  219. CRect rt;
  220. pCtrl->GetWindowRect(&rt);
  221. rect.top+=max((rect.Height()-rt.Height())/2,0);  //move to middle
  222. pCtrl->SetWindowPos(0, rect.left, rect.top, 0, 0,
  223. SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOCOPYBITS );
  224. pCtrl->SetFont( GetFont( ));
  225. BOOL bVert =  IsVertDocked(); //(m_dwStyle & CBRS_ORIENT_VERT) != 0;
  226. if (bVert && m_bHideChildWndOnVertical)
  227. {
  228.     int nState=GetToolBarCtrl().GetState(nIndex);
  229.     GetToolBarCtrl().SetState(nID,(nState | TBSTATE_HIDDEN));
  230. pCtrl->ShowWindow( SW_HIDE );
  231. }
  232. else
  233. {
  234.     int nState=GetToolBarCtrl().GetState(nIndex);
  235.     GetToolBarCtrl().SetState(nIndex,(nState & ~TBSTATE_HIDDEN));
  236. pCtrl->ShowWindow( SW_SHOW );
  237. }
  238. }
  239. else
  240. {
  241. pCtrl->ShowWindow( SW_HIDE);
  242. }
  243. ModifyStyle(0,WS_CLIPCHILDREN);
  244. return pCtrl;
  245. }
  246. BOOL CToolBarEx::AddDropDownButton(UINT nIDButton, UINT nIDMenu,BOOL bArrow)
  247. {
  248. ASSERT_VALID(this);
  249. CDropDownButtonInfo* pb = FindDropDownButtonInfo(nIDButton);
  250. if (!pb) 
  251. {
  252. pb = new CDropDownButtonInfo;
  253. ASSERT(pb);
  254. pb->pNext = m_pDropButtons;
  255. m_pDropButtons = pb;
  256. }
  257. pb->idButton = nIDButton;
  258. pb->idMenu   = nIDMenu;
  259.    return SetDropDownButton(nIDButton,bArrow);
  260. }
  261. CToolBarEx::CDropDownButtonInfo* CToolBarEx::FindDropDownButtonInfo(UINT nID)
  262. {
  263. for (CDropDownButtonInfo* pb = m_pDropButtons; pb; pb = pb->pNext) 
  264. {
  265. if (pb->idButton == nID)
  266. return pb;
  267. }
  268. return NULL;
  269. }
  270. BOOL CToolBarEx::OnToolBarBtnDropDown(NMHDR* pNMHDR, LRESULT* pRes)
  271. {
  272. UNUSED_ALWAYS( pRes );
  273. const NMTOOLBAR& nmtb = *(NMTOOLBAR*)pNMHDR;
  274.   
  275. // get location of button
  276. CRect rc;
  277. GetToolBarCtrl().GetRect(nmtb.iItem, rc);
  278. ClientToScreen(&rc);
  279. // call virtual function to display dropdown menu
  280. return OnDropDownButtonInfo(nmtb, nmtb.iItem, rc);
  281. }
  282. BOOL CToolBarEx::OnDropDownButtonInfo(const NMTOOLBAR& nmtb, UINT nID, CRect rc)
  283. {
  284. UNUSED_ALWAYS( nID );
  285. CDropDownButtonInfo* pb = FindDropDownButtonInfo(nmtb.iItem);
  286. if (pb && pb->idMenu) 
  287. {
  288. // load and display popup menu
  289. CMenu menu;
  290. VERIFY(menu.LoadMenu(pb->idMenu));
  291. CMenu* pPopup = (CMenu*)menu.GetSubMenu(0);
  292. ASSERT(pPopup);
  293. pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL,
  294. rc.left, rc.bottom, AfxGetMainWnd(), &rc);
  295. return TRUE;
  296. }
  297. return FALSE;
  298. }
  299. // This function saves the state (visible buttons, toolbar position, etc.)
  300. // of the toolbar, using the registry key provided to the Create(...) function.
  301. void CToolBarEx::SaveState()
  302. {
  303. // if there is an associated registry subkey
  304. if (m_strSubKey.GetLength())
  305. {
  306. // save the toolbar state to the registry
  307. GetToolBarCtrl().SaveState( HKEY_CURRENT_USER, m_strSubKey, m_strValueName );
  308. }
  309. }
  310. // This function restores the state (visible buttons, toolbar position, etc.)
  311. // of the toolbar, using the registry key provided to the Create(...) function.
  312. void CToolBarEx::RestoreState()
  313. {
  314. IconOptions eIconOptions=GetIconOptions();
  315. TextOptions eTextOptions=GetTextOptions();
  316. // if there is an associated registry subkey
  317. if (m_strSubKey.GetLength())
  318. {
  319. // restore the toolbar state from the registry
  320. GetToolBarCtrl().RestoreState( HKEY_CURRENT_USER, m_strSubKey, m_strValueName );
  321. }
  322. //Set Icon/Text options if changed
  323. if (eTextOptions!=GetTextOptions()) SetTextOptions(GetTextOptions(),TRUE);
  324. if (eIconOptions!=GetIconOptions()) SetIconOptions(GetIconOptions(),TRUE);
  325. }
  326. // This function is called when the user begins dragging a toolbar
  327. // button or when the customization dialog is being populated with
  328. // toolbar information.  Basically, *pResult should be populated with
  329. // your answer to the question, "is the user allowed to delete this
  330. // button?".
  331. void CToolBarEx::OnToolBarQueryDelete(NMHDR *pNMHDR, LRESULT *pResult)
  332. {
  333. UNUSED_ALWAYS( pNMHDR );
  334. NMTOOLBAR * tbStruct=(TBNOTIFY *)pNMHDR;
  335. ASSERT(tbStruct);
  336. // do not allow hidden button to be deleted as they just do not go
  337. // to the Add listbox.
  338. if ((tbStruct->tbButton.idCommand) && 
  339. GetToolBarCtrl().IsButtonHidden(tbStruct->tbButton.idCommand))
  340. *pResult = FALSE;
  341. else  
  342. *pResult = TRUE;  
  343. }
  344. // This function is called when the user begins dragging a toolbar
  345. // button or when the customization dialog is being populated with
  346. // toolbar information.  Basically, *pResult should be populated with
  347. // your answer to the question, "is the user allowed to insert a
  348. // button to the left of this one?".
  349. void CToolBarEx::OnToolBarQueryInsert(NMHDR *pNMHDR, LRESULT *pResult)
  350. {
  351. UNUSED_ALWAYS( pNMHDR );
  352. *pResult = TRUE;
  353. }
  354. // This function is called whenever the user makes a change to the
  355. // layout of the toolbar.  Calling the mainframe's RecalcLayout forces
  356. // the toolbar to repaint itself.
  357. void CToolBarEx::OnToolBarChange(NMHDR *pNMHDR, LRESULT *pResult)
  358. {
  359. UNUSED_ALWAYS( pNMHDR );
  360. UNUSED_ALWAYS( pResult );
  361. SetTextOptions(m_eTextOptions,FALSE);
  362. PositionControls();
  363. // force the frame window to recalculate the size
  364. GetParentFrame()->RecalcLayout();
  365. OnIdleUpdateCmdUI(TRUE, 0L);
  366. }
  367. // This function is called when the user initially calls up the toolbar
  368. // customization dialog box.
  369. void CToolBarEx::OnToolBarBeginAdjust(NMHDR *pNMHDR, LRESULT *pResult)
  370. {
  371. UNUSED_ALWAYS( pNMHDR );
  372. UNUSED_ALWAYS( pResult );
  373.     *pResult = 0;
  374. }
  375. LRESULT CToolBarEx::OnCustomize(WPARAM,LPARAM)
  376. {
  377. LONG lResult;
  378. ASSERT(m_pCustomizeDlg==NULL);
  379.     m_pCustomizeDlg = new CCustomizeDialog( this, m_eTextOptions, m_eIconOptions );
  380.     m_hCBTHook = ::SetWindowsHookEx( WH_CBT, CBTProc, 0, ::GetCurrentThreadId() );
  381.     ASSERT( m_hCBTHook != 0 );
  382.  
  383.     lResult = Default();
  384.     VERIFY( ::UnhookWindowsHookEx( m_hCBTHook ) );
  385.     m_hCBTHook = 0;
  386.  // if custom draw is not done then update Icon Draw at end
  387.  if (GetIconOptions()!=m_pCustomizeDlg->GetIconOptions())
  388. SetIconOptions(m_pCustomizeDlg->GetIconOptions(),TRUE);
  389.     delete m_pCustomizeDlg;
  390.     m_pCustomizeDlg = NULL;
  391. SaveState();
  392. ASSERT(m_pCustomizeDlg==NULL);
  393. return  lResult;
  394. }
  395. // This function is called when the user clicks on the help button on the
  396. // toolbar customization dialog box.
  397. void CToolBarEx::OnToolBarCustomHelp(NMHDR *pNMHDR, LRESULT *pResult)
  398. {
  399. UNUSED_ALWAYS( pNMHDR );
  400. UNUSED_ALWAYS( pResult );
  401. TRACE(_T("Help on Customize Toolbar called.n"));
  402. }
  403. // This function is called when the user dismisses the toolbar customization
  404. // dialog box.
  405. void CToolBarEx::OnToolBarEndAdjust(NMHDR *pNMHDR, LRESULT *pResult)
  406. {
  407. UNUSED_ALWAYS( pNMHDR );
  408. UNUSED_ALWAYS( pResult );
  409. }
  410. // This function is called to populate the toolbar customization dialog box
  411. // with information regarding all of the possible toolbar buttons.
  412. void CToolBarEx::OnToolBarGetButtonInfo(NMHDR *pNMHDR, LRESULT *pResult)
  413. {
  414. UNUSED_ALWAYS( pResult );
  415. TBNOTIFY* tbStruct; // data needed by customize dialog box
  416. // init the pointer
  417. tbStruct = (TBNOTIFY *)pNMHDR;
  418. // if the index is valid
  419. if ((0 <= tbStruct->iItem) && (tbStruct->iItem < m_ToolBarInfo.GetSize()))
  420. {
  421. // copy the stored button structure
  422. tbStruct->tbButton = m_ToolBarInfo[tbStruct->iItem].tbButton;
  423. // copy the text for the button label in the dialog
  424. _tcscpy(tbStruct->pszText, m_ToolBarInfo[tbStruct->iItem].btnText);
  425. // indicate valid data was sent
  426. *pResult = TRUE;
  427. }
  428. else   // else there is no button for this index
  429. {
  430. *pResult = FALSE;
  431. }
  432. }
  433. // This function is called when the user clicks on the reset button on the
  434. // toolbar customization dialog box.
  435. void CToolBarEx::OnToolBarReset(NMHDR *pNMHDR, LRESULT *pResult)
  436. {
  437. UNUSED_ALWAYS( pNMHDR );
  438. UNUSED_ALWAYS( pResult );
  439.       int         nCount, i;
  440.   CToolBarCtrl &  tbCtrl =GetToolBarCtrl();
  441.       // Remove all of the existing buttons 
  442.       nCount = tbCtrl.GetButtonCount();
  443.       for(i = nCount - 1; i >= 0; i--)
  444.  tbCtrl.DeleteButton(i);
  445.       
  446.       // Restore the buttons that were saved.
  447.   for (i=0;i<m_ToolBarInfo.GetSize();i++)
  448.   {
  449.   if (m_ToolBarInfo[i].bInitiallyVisible)
  450.  tbCtrl.AddButtons(1,&m_ToolBarInfo[i].tbButton);
  451.   }
  452. if (m_pCustomizeDlg)
  453. {
  454.    ASSERT_VALID(m_pCustomizeDlg);
  455.    m_pCustomizeDlg->SetTextOptions(m_eInitialTextOptions);
  456.    m_pCustomizeDlg->SetIconOptions(m_eInitialIconOptions);
  457. }
  458. SetTextOptions(m_eInitialTextOptions); //Default Values
  459. PositionControls();
  460. // force the frame window to recalculate the size
  461. GetParentFrame()->RecalcLayout();
  462. OnIdleUpdateCmdUI(TRUE, 0L);
  463. *pResult = TRUE;
  464. }
  465. void CToolBarEx::SetToolBarInfoForCustomization(const CToolBarEx::ToolBarInfoArray * pAdditional)
  466. {
  467.  m_ToolBarInfo.RemoveAll();
  468.  const int nCount = GetToolBarCtrl().GetButtonCount();
  469.  m_ToolBarInfo.SetSize(nCount); //SetSize
  470.  CToolBarCtrl & tbCtrl = GetToolBarCtrl();
  471.  for (int i=0;i<nCount;i++)
  472.  {
  473. CToolBarButtonInfo tbButtonInfo;
  474. tbCtrl.GetButton(i,&tbButtonInfo.tbButton);
  475. CString str;
  476. str.LoadString(tbButtonInfo.tbButton.idCommand);
  477. int nPos= str.ReverseFind(_T('n'));
  478. tbButtonInfo.btnText=str.Right(str.GetLength()-nPos-1);
  479. tbButtonInfo.bInitiallyVisible=TRUE;
  480. m_ToolBarInfo.SetAt(i,tbButtonInfo);
  481.  }
  482. m_nResButtons =m_ToolBarInfo.GetSize();
  483.  // add the addiotnal buttons
  484.  if (pAdditional)
  485.  {
  486.    ASSERT_VALID(pAdditional);
  487.    m_ToolBarInfo.Append(*pAdditional);
  488.  }
  489. m_ToolBarInfo.FreeExtra();
  490. ModifyStyle(0, CCS_ADJUSTABLE);
  491. SetTextOptions(m_eInitialTextOptions); //Default Values
  492. SetIconOptions(m_eInitialIconOptions);   //Default Values 
  493. }
  494. /////////////////////////////////////////////////////////////////////////////////////////
  495. // Overrides 
  496. int CToolBarEx::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  497. {
  498. if (CToolBar::OnCreate(lpCreateStruct) == -1)
  499. return -1;
  500. _GetComCtlVersion();
  501. ASSERT(_ComCtlVersion>=VERSION_IE5);
  502. //set version
  503. // int nVer=5;
  504. // DefWindowProc(CCM_SETVERSION,nVer,0);
  505. // ASSERT(nVer==DefWindowProc(CCM_GETVERSION,nVer,0));
  506. return 0;
  507. }
  508. void CToolBarEx::PositionControls()
  509. {
  510. GetToolBarCtrl().AutoSize();
  511. m_bDelayedButtonLayout=TRUE;
  512. }
  513. // the all important function
  514. CSize CToolBarEx::GetButtonSize(TBBUTTON* pData, int iButton, DWORD dwMode)
  515. {
  516. ASSERT(_ComCtlVersion > 0);
  517. // Get the actual size of the button, not what's in m_sizeButton.
  518. // Make sure to do SendMessage instead of calling MFC's GetItemRect,
  519. // which has all sorts of bad side-effects!
  520. // 
  521. CRect rc;
  522. SendMessage(TB_GETITEMRECT, iButton, (LPARAM)&rc);
  523. CSize sz = rc.Size();
  524. DWORD dwStyle = pData[iButton].fsStyle;
  525. BOOL bVertDocked= (!(dwMode&LM_HORZ) && !(dwMode&LM_STRETCH) ) ;
  526. // do not allow sepearot to be greater than Button height ( Have to check this)
  527. if (dwStyle & TBSTYLE_SEP)
  528. sz.cy = min(sz.cy ,HIWORD(GetToolBarCtrl().GetButtonSize()));
  529. // special cas  for custom controls
  530. if (m_bHideChildWndOnVertical)
  531. {
  532. if ((dwStyle & TBSTYLE_SEP) && 
  533. (pData[iButton].idCommand!=0))
  534. {
  535. if (bVertDocked)
  536. {
  537. sz.cx=sz.cy=0;
  538. }
  539. else
  540. {
  541.     // we will get 0,0 on hidden things
  542. if (GetToolBarCtrl().IsButtonHidden(pData[iButton].idCommand))
  543. {
  544.    CWnd * pWnd =GetDlgItem(pData[iButton].idCommand);
  545. ASSERT_VALID(pWnd);
  546. CRect rt;
  547. pWnd->GetWindowRect(rt);
  548. sz=rt.Size();
  549. }
  550. }
  551. }
  552. }  
  553. ////////////////
  554. // Now must do special case for various versions of comctl32.dll,
  555. //
  556. if ((pData[iButton].fsState & TBSTATE_WRAP)) 
  557. {
  558. if (dwStyle & TBSTYLE_SEP) 
  559. {
  560. CWnd *pWnd =GetDlgItem(pData[iButton].idCommand);
  561. // Check seperator is child window
  562. if (!pWnd)
  563. {
  564. // this is the last separator in the row (eg vertically docked)
  565. // fudge the height, and ignore the width. TB_GETITEMRECT will return
  566. // size = (8 x 22) even for a separator in vertical toolbar
  567. //
  568. if (_ComCtlVersion <= VERSION_IE3)
  569. sz.cy -= 3; // empircally good fudge factor
  570. else if (_ComCtlVersion != VERSION_IE4)
  571. sz.cy = sz.cx;
  572. sz.cx = 0; // separator takes no width if it's the last one
  573. }
  574. else
  575. {
  576.   // Do not set value in case of the child window
  577.   //WE should never get here 
  578.   ASSERT_VALID(pWnd);
  579.   ASSERT(FALSE);
  580. }
  581. }
  582. //  // drop down arrow check
  583. //  if ((dwStyle & TBSTYLE_DROPDOWN) && 
  584. //   (bVertDocked) &&
  585. //    !m_bShowDropdownArrowWhenVertical ) 
  586. //  {
  587. // // ignore width of dropdown
  588. // sz.cx = sz.cy;
  589. //  }
  590. return sz;
  591. }
  592. ////////////////////////////////////////////////////////////
  593. #define CX_OVERLAP  0
  594. CSize CToolBarEx::CalcSize(TBBUTTON* pData, int nCount,DWORD dwMode)
  595. {
  596. ASSERT(pData != NULL && nCount > 0);
  597. CPoint cur(0,0);
  598. CSize sizeResult(0,0);
  599. int cyTallestOnRow = 0;
  600. int nButtons=0;
  601. for (int i = 0; i < nCount; i++)
  602. {
  603. // also calculate for hidden custom controls
  604. if (  (pData[i].fsState & TBSTATE_HIDDEN)  &&
  605. !((pData[i].fsStyle & TBSTYLE_SEP) && (pData[i].idCommand!=0)))
  606. continue;
  607. // Load actual size of button into a local variable
  608. //
  609. CSize m_sizeButton = GetButtonSize(pData, i,dwMode);
  610. //  changed the logic below to be more correct.
  611. cyTallestOnRow = max(cyTallestOnRow, m_sizeButton.cy);
  612. sizeResult.cx = max(cur.x + m_sizeButton.cx, sizeResult.cx);
  613. sizeResult.cy = max(cur.y + m_sizeButton.cy, sizeResult.cy);
  614. cur.x += m_sizeButton.cx - CX_OVERLAP;
  615. if (!(pData[i].fsState & TBSTATE_HIDDEN)) nButtons++;
  616. if (pData[i].fsState & TBSTATE_WRAP)
  617. {
  618. //only seperator is present
  619. if ((nButtons==1) && (pData[i].fsStyle & TBSTYLE_SEP))
  620. {
  621. cyTallestOnRow = HIWORD(GetToolBarCtrl().GetButtonSize());
  622. }
  623. cur.x = 0;
  624. cur.y += cyTallestOnRow;
  625. cyTallestOnRow = 0;
  626. if (pData[i].fsStyle & TBSTYLE_SEP)
  627. cur.y += m_sizeButton.cy;
  628.  nButtons=0;
  629. }
  630. }
  631. return sizeResult;
  632. }
  633. int CToolBarEx::WrapToolBar(TBBUTTON* pData, int nCount, int nWidth, DWORD dwMode)
  634. {
  635. ASSERT(pData != NULL && nCount > 0);
  636. int nResult = 0;
  637. int x = 0;
  638. for (int i = 0; i < nCount; i++)
  639. {
  640. pData[i].fsState &= ~TBSTATE_WRAP;
  641. // also calculate for hidden custom controls
  642. if (  (pData[i].fsState & TBSTATE_HIDDEN)  &&
  643. !((pData[i].fsStyle & TBSTYLE_SEP) && (pData[i].idCommand!=0)))
  644. continue;
  645. int dx, dxNext;
  646. // Load actual size of button into a local variable
  647. CSize m_sizeButton = GetButtonSize(pData, i,dwMode);
  648. dx = m_sizeButton.cx;
  649. dxNext = dx - CX_OVERLAP;
  650. if (x + dx > nWidth)
  651. {
  652. BOOL bFound = FALSE;
  653. for (int j = i; j >= 0  &&  !(pData[j].fsState & TBSTATE_WRAP); j--)
  654. {
  655. // Find last separator that isn't hidden
  656. // a separator that has a command ID is not
  657. // a separator, but a custom control.
  658. if ((pData[j].fsStyle & TBSTYLE_SEP) &&
  659. (pData[j].idCommand == 0)
  660. && !(pData[j].fsState & TBSTATE_HIDDEN))
  661. {
  662. bFound = TRUE; i = j; x = 0;
  663. pData[j].fsState |= TBSTATE_WRAP;
  664. nResult++;
  665. break;
  666. }
  667. }
  668. if (!bFound)
  669. {
  670. for (int j = i - 1; j >= 0 && !(pData[j].fsState & TBSTATE_WRAP); j--)
  671. {
  672. // Never wrap anything that is hidden,
  673. // or any custom controls
  674. if ((pData[j].fsState & TBSTATE_HIDDEN) ||
  675. ((pData[j].fsStyle & TBSTYLE_SEP) &&
  676. (pData[j].idCommand != 0)))
  677. continue;
  678. bFound = TRUE; i = j; x = 0;
  679. pData[j].fsState |= TBSTATE_WRAP;
  680. nResult++;
  681. break;
  682. }
  683. if (!bFound)
  684. x += dxNext;
  685. }
  686. }
  687. else
  688. x += dxNext;
  689. }
  690. return nResult + 1;
  691. }
  692. /////////////////////////////////////////////////////////////////////////////////////////////
  693. void CToolBarEx::SizeToolBar(TBBUTTON* pData, int nCount, int nLength, BOOL bVert, DWORD dwMode)
  694. {
  695. ASSERT(pData != NULL && nCount > 0);
  696. if (!bVert)
  697. {
  698. int nMin, nMax, nTarget, nCurrent, nMid;
  699. // Wrap ToolBar as specified
  700. nMax = nLength;
  701. nTarget = WrapToolBar(pData, nCount, nMax,dwMode);
  702. // Wrap ToolBar vertically
  703. nMin = 0;
  704. nCurrent = WrapToolBar(pData, nCount, nMin,dwMode);
  705. if (nCurrent != nTarget)
  706. {
  707. while (nMin < nMax)
  708. {
  709. nMid = (nMin + nMax) / 2;
  710. nCurrent = WrapToolBar(pData, nCount, nMid,dwMode);
  711. if (nCurrent == nTarget)
  712. nMax = nMid;
  713. else
  714. {
  715. if (nMin == nMid)
  716. {
  717. WrapToolBar(pData, nCount, nMax,dwMode);
  718. break;
  719. }
  720. nMin = nMid;
  721. }
  722. }
  723. }
  724. CSize size = CalcSize(pData, nCount,dwMode);
  725. WrapToolBar(pData, nCount, size.cx,dwMode);
  726. }
  727. else
  728. {
  729. CSize sizeMax, sizeMin, sizeMid;
  730. // Wrap ToolBar vertically
  731. WrapToolBar(pData, nCount, 0,dwMode);
  732. sizeMin = CalcSize(pData, nCount,dwMode);
  733. // Wrap ToolBar horizontally
  734. WrapToolBar(pData, nCount, 32767,dwMode);
  735. sizeMax = CalcSize(pData, nCount,dwMode);
  736. while (sizeMin.cx < sizeMax.cx)
  737. {
  738. sizeMid.cx = (sizeMin.cx + sizeMax.cx) / 2;
  739. WrapToolBar(pData, nCount, sizeMid.cx,dwMode);
  740. sizeMid = CalcSize(pData, nCount,dwMode);
  741. if (nLength < sizeMid.cy)
  742. {
  743. if (sizeMin == sizeMid)
  744. {
  745. WrapToolBar(pData, nCount, sizeMax.cx,dwMode);
  746. return;
  747. }
  748. sizeMin = sizeMid;
  749. }
  750. else if (nLength > sizeMid.cy)
  751. {
  752. if (sizeMax == sizeMid)
  753. {
  754. WrapToolBar(pData, nCount, sizeMin.cx,dwMode);
  755. return;
  756. }
  757. sizeMax = sizeMid;
  758. }
  759. else
  760. return;
  761. }
  762. }
  763. }
  764. CSize CToolBarEx::CalcLayout(DWORD dwMode, int nLength)
  765. {
  766. ASSERT_VALID(this);
  767. ASSERT(::IsWindow(m_hWnd));
  768. if (dwMode & LM_HORZDOCK)
  769. ASSERT(dwMode & LM_HORZ);
  770. int nCount;
  771. TBBUTTON* pData = NULL;
  772. CSize sizeResult(0,0);
  773. //BLOCK: Load Buttons
  774. {
  775. nCount = DefWindowProc(TB_BUTTONCOUNT, 0, 0);
  776. if (nCount != 0)
  777. {
  778. int i;
  779. pData = new TBBUTTON[nCount];
  780. for (i = 0; i < nCount; i++)
  781. _GetButton(i, &pData[i]);
  782. }
  783. }
  784. if (nCount > 0)
  785. {
  786. if (!(m_dwStyle & CBRS_SIZE_FIXED))
  787. {
  788. BOOL bDynamic = m_dwStyle & CBRS_SIZE_DYNAMIC;
  789. if (bDynamic && (dwMode & LM_MRUWIDTH))
  790. SizeToolBar(pData, nCount, m_nMRUWidth,FALSE,dwMode);
  791. else if (bDynamic && (dwMode & LM_HORZDOCK))
  792. SizeToolBar(pData, nCount, 32767,FALSE,dwMode);
  793. else if (bDynamic && (dwMode & LM_VERTDOCK))
  794. SizeToolBar(pData, nCount, 0,FALSE,dwMode);
  795. else if (bDynamic && (nLength != -1))
  796. {
  797. CRect rect; rect.SetRectEmpty();
  798. CalcInsideRect(rect, (dwMode & LM_HORZ));
  799. BOOL bVert = (dwMode & LM_LENGTHY);
  800. int nLen = nLength + (bVert ? rect.Height() : rect.Width());
  801. SizeToolBar(pData, nCount, nLen, bVert,dwMode);
  802. }
  803. else if (bDynamic && (m_dwStyle & CBRS_FLOATING))
  804. SizeToolBar(pData, nCount, m_nMRUWidth,FALSE,dwMode);
  805. else
  806. SizeToolBar(pData, nCount, (dwMode & LM_HORZ) ? 32767 : 0,FALSE,dwMode);
  807. }
  808. sizeResult = CalcSize(pData, nCount,dwMode);
  809. if (dwMode & LM_COMMIT)
  810. {
  811. int nControlCount = 0;
  812. BOOL bIsDelayed = m_bDelayedButtonLayout;
  813. m_bDelayedButtonLayout = FALSE;
  814. BOOL bVert = (m_dwStyle & CBRS_ORIENT_VERT) != 0;
  815. for (int i = 0; i < nCount; i++)
  816. if ((pData[i].fsStyle & TBSTYLE_SEP) && (pData[i].idCommand != 0))
  817. nControlCount++;
  818. if (nControlCount > 0)
  819. {
  820. for(int i = 0; i < nCount; i++)
  821. {
  822. if ((pData[i].fsStyle & TBSTYLE_SEP) && (pData[i].idCommand != 0))
  823. {
  824. CRect rt;
  825. CWnd* pWnd = GetDlgItem(pData[i].idCommand);
  826. if (pWnd != NULL)
  827. {
  828. ASSERT_VALID(pWnd);
  829.        pWnd->GetWindowRect(rt);
  830. pData[i].iBitmap=rt.Width(); //width 
  831. if (bVert && m_bHideChildWndOnVertical)
  832.     pData[i].fsState |= TBSTATE_HIDDEN;
  833. else    
  834. pData[i].fsState &= ~TBSTATE_HIDDEN;
  835. }
  836. }
  837. }
  838. }
  839. if ((m_dwStyle & CBRS_FLOATING) && (m_dwStyle & CBRS_SIZE_DYNAMIC))
  840. m_nMRUWidth = sizeResult.cx;
  841. for (i = 0; i < nCount; i++)
  842. _SetButton(i, &pData[i]);
  843. {  
  844. //Now place the windows
  845. CWnd * pWnd = GetWindow(GW_CHILD);
  846. while(pWnd)
  847. {
  848.   ASSERT_VALID(pWnd);
  849.   int id =pWnd->GetDlgCtrlID();
  850.   ///////////////////////////
  851. // make sure the id is valid, and set the button 
  852. // style for a seperator.
  853. int nIndex = CommandToIndex( id ) ;
  854. if (nIndex>-1)
  855. {
  856. ASSERT( nIndex >= 0 );
  857. // insert the control into the toolbar.
  858. CRect rect;
  859. GetItemRect( nIndex, &rect );
  860. CRect rt;
  861. pWnd->GetWindowRect(&rt);
  862. rect.top+=max((rect.Height()-rt.Height())/2,0);
  863. pWnd->SetWindowPos(0, rect.left, rect.top, 0, 0,
  864. SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOCOPYBITS );
  865. //pWnd->SetFont( GetFont( ));
  866. if (bVert && m_bHideChildWndOnVertical)
  867. {
  868. ASSERT(GetToolBarCtrl().IsButtonHidden(id));
  869. pWnd->ShowWindow( SW_HIDE );
  870. }
  871. else
  872. {
  873. ASSERT(!GetToolBarCtrl().IsButtonHidden(id));
  874. pWnd->ShowWindow( SW_SHOW );
  875. }
  876. }
  877. else
  878. {
  879. pWnd->ShowWindow( SW_HIDE);
  880. }
  881.   //////////////////////////
  882.   pWnd=pWnd->GetNextWindow();
  883. }
  884. }
  885. m_bDelayedButtonLayout = bIsDelayed;
  886. }
  887. delete[] pData;
  888. }
  889. //BLOCK: Adjust Margins
  890. {
  891. CRect rect; rect.SetRectEmpty();
  892. CalcInsideRect(rect, (dwMode & LM_HORZ));
  893. sizeResult.cy -= rect.Height();
  894. sizeResult.cx -= rect.Width();
  895. CSize size = CControlBar::CalcFixedLayout((dwMode & LM_STRETCH), (dwMode & LM_HORZ));
  896. sizeResult.cx = max(sizeResult.cx, size.cx);
  897. sizeResult.cy = max(sizeResult.cy, size.cy);
  898. }
  899. return sizeResult;
  900. }
  901. CSize CToolBarEx::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
  902. {
  903. DWORD dwMode = bStretch ? LM_STRETCH : 0;
  904. dwMode |= bHorz ? LM_HORZ : 0;
  905. return CalcLayout(dwMode);
  906. }
  907. CSize CToolBarEx::CalcDynamicLayout(int nLength, DWORD dwMode)
  908. {
  909. if ((nLength == -1) && !(dwMode & LM_MRUWIDTH) && !(dwMode & LM_COMMIT) &&
  910. ((dwMode & LM_HORZDOCK) || (dwMode & LM_VERTDOCK)))
  911. {
  912. return CalcFixedLayout(dwMode & LM_STRETCH, dwMode & LM_HORZDOCK);
  913. }
  914. return CalcLayout(dwMode, nLength);
  915. }
  916. /////////////////////////////////////////////////////////////////////////////
  917. // CToolBarEx attribute access
  918. void CToolBarEx::_GetButton(int nIndex, TBBUTTON* pButton) const
  919. {
  920. CToolBarEx* pBar = (CToolBarEx*)this;
  921. VERIFY(pBar->DefWindowProc(TB_GETBUTTON, nIndex, (LPARAM)pButton));
  922. // TBSTATE_ENABLED == TBBS_DISABLED so invert it
  923. pButton->fsState ^= TBSTATE_ENABLED;
  924. }
  925. void CToolBarEx::_SetButton(int nIndex, TBBUTTON* pButton)
  926. {
  927. // get original button state
  928. TBBUTTON button;
  929. VERIFY(DefWindowProc(TB_GETBUTTON, nIndex, (LPARAM)&button));
  930. // prepare for old/new button comparsion
  931. button.bReserved[0] = 0;
  932. button.bReserved[1] = 0;
  933. // TBSTATE_ENABLED == TBBS_DISABLED so invert it
  934. pButton->fsState ^= TBSTATE_ENABLED;
  935. pButton->bReserved[0] = 0;
  936. pButton->bReserved[1] = 0;
  937. // nothing to do if they are the same
  938. if (memcmp(pButton, &button, sizeof(TBBUTTON)) != 0)
  939. {
  940. // don't redraw everything while setting the button
  941. DWORD dwStyle = GetStyle();
  942. ModifyStyle(WS_VISIBLE, 0);
  943. VERIFY(DefWindowProc(TB_DELETEBUTTON, nIndex, 0));
  944. // Force a recalc of the toolbar's layout to work around a comctl bug
  945. int iTextRows = (int)::SendMessage(m_hWnd, TB_GETTEXTROWS, 0, 0);
  946. ::SendMessage(m_hWnd, WM_SETREDRAW, FALSE, 0);
  947. ::SendMessage(m_hWnd, TB_SETMAXTEXTROWS, iTextRows+1, 0);
  948. ::SendMessage(m_hWnd, TB_SETMAXTEXTROWS, iTextRows, 0);
  949. ::SendMessage(m_hWnd, WM_SETREDRAW, TRUE, 0);
  950. VERIFY(DefWindowProc(TB_INSERTBUTTON, nIndex, (LPARAM)pButton));
  951. ModifyStyle(0, dwStyle & WS_VISIBLE);
  952. // invalidate appropriate parts
  953. if (((pButton->fsStyle ^ button.fsStyle) & TBSTYLE_SEP) ||
  954. ((pButton->fsStyle & TBSTYLE_SEP) && pButton->iBitmap != button.iBitmap))
  955. {
  956. // changing a separator
  957. Invalidate();
  958. }
  959. else
  960. {
  961. // invalidate just the button
  962. CRect rect;
  963. if (DefWindowProc(TB_GETITEMRECT, nIndex, (LPARAM)&rect))
  964. InvalidateRect(rect);
  965. }
  966. }
  967. }
  968. BOOL CToolBarEx::SetDropDownButton(UINT nID, BOOL bArrow)
  969. {
  970. int iButton = CommandToIndex(nID);
  971. DWORD dwStyle = GetButtonStyle(iButton);
  972. dwStyle |= TBSTYLE_DROPDOWN|( (!bArrow) ?BTNS_WHOLEDROPDOWN :0);
  973. SetButtonStyle(iButton, dwStyle);
  974. GetToolBarCtrl().SetExtendedStyle(GetToolBarCtrl().GetExtendedStyle() |TBSTYLE_EX_DRAWDDARROWS);
  975. return TRUE;
  976. }
  977. BOOL CToolBarEx::IsVertDocked()
  978. {
  979. UINT nID =GetParent()->GetDlgCtrlID();
  980. return ( (nID ==AFX_IDW_DOCKBAR_LEFT) || (nID== AFX_IDW_DOCKBAR_RIGHT));
  981. }
  982. void CToolBarEx::OnPaint() 
  983. {
  984. CToolBar::OnPaint();
  985. //I have to use this, as there is not customdraw mesasges for seperators
  986. // draw the controls seperator again to hide it
  987. for (int i=0;i<GetToolBarCtrl().GetButtonCount();i++)
  988. {
  989. TBBUTTON tb;
  990. GetToolBarCtrl().GetButton(i,&tb);
  991. //only for seperators controls
  992. if  ( ((tb.fsStyle & TBSTYLE_SEP) == TBSTYLE_SEP) &&
  993.    (tb.idCommand!=0) )
  994. {
  995. CRect rc;
  996. GetItemRect(i,rc);
  997. CClientDC dc(this);
  998. CWnd *pWnd = GetDlgItem(tb.idCommand);
  999. ASSERT_VALID(pWnd);
  1000. dc.FillSolidRect(rc, m_clrBtnFace);
  1001. if (pWnd)
  1002. {
  1003. pWnd->RedrawWindow();
  1004. }
  1005. }
  1006. }
  1007.  
  1008. }
  1009. void CToolBarEx::SetTextOptions(TextOptions eTextOptions, BOOL bUpdate)
  1010. {
  1011.     ASSERT( ::IsWindow( m_hWnd ) );
  1012.     ASSERT( eTextOptions != toNone );
  1013.     m_eTextOptions = eTextOptions;
  1014.     // Modify toolbar style according to new text options
  1015.     ModifyStyle(
  1016.         ( eTextOptions == toTextOnRight ) ? 0 : TBSTYLE_LIST,
  1017.         ( eTextOptions == toTextOnRight ) ? TBSTYLE_LIST : 0 );
  1018.     CToolBarCtrl& tbCtrl = GetToolBarCtrl();
  1019.     DWORD dwStyleEx = tbCtrl.GetExtendedStyle();
  1020. tbCtrl.SetExtendedStyle(
  1021.         ( eTextOptions == toTextOnRight ) ?
  1022.             ( dwStyleEx |  TBSTYLE_EX_MIXEDBUTTONS ) :
  1023.             ( dwStyleEx & ~TBSTYLE_EX_MIXEDBUTTONS ) );
  1024. for(int i=0;i<m_ToolBarInfo.GetSize();i++)
  1025.   { 
  1026.   // if ((m_ToolBarInfo[i].tbButton.fsStyle & TBSTYLE_SEP) !=  TBSTYLE_SEP)
  1027.   {
  1028.   int nIndex= CommandToIndex(m_ToolBarInfo[i].tbButton.idCommand);
  1029.  
  1030.   if (nIndex>-1)  // buton is there on bar
  1031. {
  1032.  TBBUTTON tbinfo;
  1033. _GetButton(nIndex,&tbinfo);
  1034. if ( !( tbinfo.fsStyle & TBSTYLE_SEP ) )  //check again
  1035. {
  1036.   // attempt to lookup string index in map
  1037. int nString = -1;
  1038. if ((eTextOptions==toTextLabels) || ((eTextOptions==toTextOnRight)))
  1039. {
  1040. void* p=NULL;
  1041. CString strTemp(m_ToolBarInfo[i].btnText);
  1042. if (m_pStringMap != NULL && m_pStringMap->Lookup(strTemp, p))
  1043. nString = (int)p;
  1044. // add new string if not already in map
  1045. if (nString == -1)
  1046. {
  1047. // initialize map if necessary
  1048. if (m_pStringMap == NULL)
  1049. {
  1050. m_pStringMap = new CMapStringToPtr;
  1051. ASSERT(m_pStringMap);
  1052. }
  1053. // add new string to toolbar list
  1054. nString = (int)DefWindowProc(TB_ADDSTRING, 0, (LPARAM)(LPCTSTR)strTemp);
  1055. if (nString != -1)
  1056. {
  1057. // cache string away in string map
  1058. m_pStringMap->SetAt(strTemp, (void*)nString);
  1059. ASSERT(m_pStringMap->Lookup(strTemp, p));
  1060. }
  1061. }
  1062. }
  1063. switch ( eTextOptions )
  1064. {
  1065. case toTextLabels:
  1066. {
  1067. tbinfo.iString =nString;
  1068. tbinfo.fsStyle &= ~BTNS_SHOWTEXT;
  1069. tbinfo.fsStyle |= TBSTYLE_AUTOSIZE;
  1070. }
  1071. break;
  1072. case toTextOnRight:
  1073. {
  1074. if ((nString!=-1) && 
  1075. (HasButtonText(m_ToolBarInfo[i].tbButton.idCommand)))
  1076. {
  1077. tbinfo.iString =nString;
  1078. tbinfo.fsStyle |= ( TBSTYLE_AUTOSIZE |BTNS_SHOWTEXT );
  1079. }
  1080. else
  1081. {
  1082. tbinfo.fsStyle &= ~BTNS_SHOWTEXT;
  1083. tbinfo.fsStyle |= TBSTYLE_AUTOSIZE;
  1084. }
  1085. }
  1086. break;
  1087. case toNoTextLabels:
  1088. {
  1089.   tbinfo.iString= -1;   //Set string to zero
  1090. tbinfo.fsStyle &= ~BTNS_SHOWTEXT;
  1091. tbinfo.fsStyle |= TBSTYLE_AUTOSIZE;
  1092. }
  1093. break;
  1094. default:
  1095. ASSERT(FALSE); // anew type added
  1096. }
  1097. //Delete & add the button
  1098. {
  1099. tbinfo.fsState ^= TBSTATE_ENABLED;
  1100. m_ToolBarInfo[i].tbButton=tbinfo;
  1101. tbinfo.fsState ^= TBSTATE_ENABLED;
  1102. _SetButton(nIndex,&tbinfo);
  1103. }
  1104.   }
  1105. }
  1106. }
  1107. }
  1108. int iTextRows = 0;
  1109. // now total setting
  1110. switch ( eTextOptions )
  1111. {
  1112. case toTextLabels:
  1113. {
  1114.    iTextRows=1;
  1115. }
  1116. break;
  1117. case toTextOnRight:
  1118. {
  1119.    iTextRows=1;
  1120. }
  1121. break;
  1122. case toNoTextLabels:
  1123. {
  1124.    iTextRows=0;
  1125. }
  1126. break;
  1127. default:
  1128. ASSERT(FALSE); // anew type added
  1129. }
  1130. ::SendMessage(m_hWnd, TB_SETMAXTEXTROWS, iTextRows, 0);
  1131.     // If requested, reflect changes immediately
  1132.     if ( bUpdate )
  1133.     {
  1134. PositionControls();
  1135. GetParentFrame()->RecalcLayout();
  1136. OnIdleUpdateCmdUI(TRUE, 0L);
  1137.     }
  1138. }
  1139.  
  1140. void CToolBarEx::SetIconOptions(IconOptions eIconOptions, BOOL bUpdate)
  1141. {
  1142.     ASSERT( ::IsWindow( m_hWnd ) );
  1143.     ASSERT( eIconOptions != ioNone );
  1144.     m_eIconOptions = eIconOptions;
  1145. switch(eIconOptions)
  1146. {
  1147.  case ioSmallIcons:
  1148.  m_sizeImage= m_szImageSmall ;
  1149.  SetIconOptionBitmap(ioSmallIcons);
  1150.  GetToolBarCtrl().SetBitmapSize(m_szImageSmall);
  1151. break;
  1152.  case ioLargeIcons:
  1153.  m_sizeImage= m_szImageLarge ;
  1154.  SetIconOptionBitmap(ioLargeIcons);
  1155.  GetToolBarCtrl().SetBitmapSize(m_szImageLarge);
  1156.  break;
  1157. }
  1158. // Force a recalc of the toolbar's layout to work around a comctl bug
  1159. int iTextRows = (int)::SendMessage(m_hWnd, TB_GETTEXTROWS, 0, 0);
  1160. ::SendMessage(m_hWnd, WM_SETREDRAW, FALSE, 0);
  1161. ::SendMessage(m_hWnd, TB_SETMAXTEXTROWS, iTextRows+1, 0);
  1162. ::SendMessage(m_hWnd, TB_SETMAXTEXTROWS, iTextRows, 0);
  1163. ::SendMessage(m_hWnd, WM_SETREDRAW, TRUE, 0);
  1164.     // If requested, reflect changes immediately
  1165.     if ( bUpdate )
  1166.     {
  1167. PositionControls();
  1168. GetParentFrame()->RecalcLayout();
  1169. OnIdleUpdateCmdUI(TRUE, 0L);
  1170.     }
  1171. }
  1172. //static ftn for Hook
  1173. LRESULT CALLBACK CToolBarEx::CBTProc( int nCode, WPARAM wParam, LPARAM lParam )
  1174. {
  1175.     ASSERT( m_pCustomizeDlg != NULL );
  1176. try
  1177. {
  1178. if ( ( nCode == HCBT_CREATEWND ) && (m_pCustomizeDlg) && ( m_pCustomizeDlg->m_hWnd == 0 ) )
  1179. {
  1180. // This is where we have a good chance to subclass standard
  1181. // "Customize toolbar" dialog in order to add to it some of
  1182. // our new features (ie. text and icon options selectors)
  1183. HWND hWnd = ( HWND )wParam;
  1184. VERIFY( m_pCustomizeDlg->SubclassWindow( hWnd ) );
  1185. }
  1186. }
  1187. catch(...) // if exception is not caught then we can get in infinite loop as assert window is opened.
  1188. {
  1189. TRACE0(_T("Exception thrown while Hooking-Extra Custom features unavaialble.n"));
  1190. //Call next
  1191. LRESULT lResult=::CallNextHookEx( m_hCBTHook, nCode, wParam, lParam );
  1192. VERIFY( ::UnhookWindowsHookEx( m_hCBTHook ) );
  1193. m_hCBTHook = 0;
  1194. if (m_pCustomizeDlg) delete m_pCustomizeDlg;
  1195. m_pCustomizeDlg = NULL;
  1196. return lResult;
  1197. }
  1198.     return ::CallNextHookEx( m_hCBTHook, nCode, wParam, lParam );
  1199. }
  1200. // has to override this
  1201. BOOL CToolBarEx::HasButtonText(int nID)
  1202. {
  1203. nID;
  1204.     return TRUE;
  1205. }
  1206. /*
  1207. DIBs use RGBQUAD format:
  1208. 0xbb 0xgg 0xrr 0x00
  1209. Reasonably efficient code to convert a COLORREF into an
  1210. RGBQUAD is byte-order-dependent, so we need different
  1211. code depending on the byte order we're targeting.
  1212. */
  1213. #define RGB_TO_RGBQUAD(r,g,b)   (RGB(b,g,r))
  1214. #define CLR_TO_RGBQUAD(clr)     (RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr)))
  1215. static COLORREF MapToSysColor (COLORREF color, BOOL bUseRGBQUAD)
  1216. {
  1217. struct COLORMAP
  1218. {
  1219. // use DWORD instead of RGBQUAD so we can compare two RGBQUADs easily
  1220. DWORD rgbqFrom;
  1221. int iSysColorTo;
  1222. };
  1223. static const COLORMAP sysColorMap[] =
  1224. {
  1225. // mapping from color in DIB to system color
  1226. { RGB_TO_RGBQUAD(0x00, 0x00, 0x00),  COLOR_BTNTEXT },       // black
  1227. { RGB_TO_RGBQUAD(0x80, 0x80, 0x80),  COLOR_BTNSHADOW },     // dark grey
  1228. { RGB_TO_RGBQUAD(0xC0, 0xC0, 0xC0),  COLOR_BTNFACE },       // bright grey
  1229. { RGB_TO_RGBQUAD(0xFF, 0xFF, 0xFF),  COLOR_BTNHIGHLIGHT }   // white
  1230. };
  1231. const int nMaps = 4;
  1232. // look for matching RGBQUAD color in original
  1233. for (int i = 0; i < nMaps; i++)
  1234. {
  1235. if (color == sysColorMap[i].rgbqFrom)
  1236. {
  1237. return bUseRGBQUAD ? 
  1238. CLR_TO_RGBQUAD(::GetSysColor(sysColorMap[i].iSysColorTo)) :
  1239. ::GetSysColor(sysColorMap[i].iSysColorTo);
  1240. }
  1241. }
  1242. return color;
  1243. }
  1244. static HBITMAP LoadSysColorBitmapSize(HINSTANCE hInst, HRSRC hRsrc,CSize sz)
  1245. {
  1246. HGLOBAL hglb;
  1247. if ((hglb = LoadResource(hInst, hRsrc)) == NULL)
  1248. return NULL;
  1249. LPBITMAPINFOHEADER lpBitmap = (LPBITMAPINFOHEADER)LockResource(hglb);
  1250. if (lpBitmap == NULL)
  1251. return NULL;
  1252. UINT nSize=lpBitmap->biSize;
  1253. const int nColorTableSize = 16;
  1254. if (lpBitmap->biBitCount  <=8)
  1255. {
  1256. // make copy of BITMAPINFOHEADER so we can modify the color table
  1257. nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
  1258. }
  1259. LPBITMAPINFOHEADER lpBitmapInfo = (LPBITMAPINFOHEADER)::malloc(nSize);
  1260. if (lpBitmapInfo == NULL) return NULL;
  1261. memcpy(lpBitmapInfo, lpBitmap, nSize);
  1262. HBITMAP hbm =NULL;
  1263. if (lpBitmapInfo->biBitCount  <=8)
  1264. {
  1265. // color table is in RGBQUAD DIB format
  1266. DWORD* pColorTable =
  1267. (DWORD*)(((LPBYTE)lpBitmapInfo) + (UINT)lpBitmapInfo->biSize);
  1268. for (int iColor = 0; iColor < nColorTableSize; iColor++)
  1269. {
  1270. pColorTable[iColor] = MapToSysColor(pColorTable[iColor],TRUE) ;
  1271. }
  1272. int nWidth = (int)lpBitmapInfo->biWidth;
  1273. int nHeight = (int)lpBitmapInfo->biHeight;
  1274. HDC hDCScreen = ::GetDC(NULL);
  1275. hbm = ::CreateCompatibleBitmap(hDCScreen, sz.cx, sz.cy);
  1276. if (hbm != NULL)
  1277. {
  1278. HDC hDCGlyphs = ::CreateCompatibleDC(hDCScreen);
  1279. HBITMAP hbmOld = (HBITMAP)::SelectObject(hDCGlyphs, hbm);
  1280. LPBYTE lpBits;
  1281. lpBits = (LPBYTE)(lpBitmap + 1);
  1282. lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
  1283. StretchDIBits(hDCGlyphs, 0, 0, sz.cx, sz.cy, 0, 0, nWidth, nHeight,
  1284. lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
  1285. SelectObject(hDCGlyphs, hbmOld);
  1286. ::DeleteDC(hDCGlyphs);
  1287. }
  1288. ::ReleaseDC(NULL, hDCScreen);
  1289. }
  1290. else
  1291. {
  1292. int nWidth = (int)lpBitmapInfo->biWidth;
  1293. int nHeight = (int)lpBitmapInfo->biHeight;
  1294. HDC hDCScreen = ::GetDC(NULL);
  1295. hbm = ::CreateCompatibleBitmap(hDCScreen, sz.cx, sz.cy);
  1296. if (hbm != NULL)
  1297. {
  1298. HDC hDCGlyphs = ::CreateCompatibleDC(hDCScreen);
  1299. HBITMAP hbmOld = (HBITMAP)::SelectObject(hDCGlyphs, hbm);
  1300. LPBYTE lpBits;
  1301. lpBits = (LPBYTE)(lpBitmap + 1);
  1302. StretchDIBits(hDCGlyphs, 0, 0, sz.cx, sz.cy, 0, 0, nWidth, nHeight,
  1303. lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
  1304. // Change a specific colors to system:
  1305. for (int x = 0; x < sz.cx; x ++)
  1306. {
  1307. for (int y = 0; y < sz.cy; y ++)
  1308. {
  1309. COLORREF clrOrig = ::GetPixel (hDCGlyphs, x, y);
  1310. COLORREF clrNew = MapToSysColor (clrOrig,FALSE);
  1311. if (clrOrig != clrNew)
  1312. {
  1313. ::SetPixel (hDCGlyphs, x, y, clrNew);
  1314. }
  1315. }
  1316. }
  1317. SelectObject(hDCGlyphs, hbmOld);
  1318. ::DeleteDC(hDCGlyphs);
  1319. }
  1320. ::ReleaseDC(NULL, hDCScreen);
  1321. }
  1322. // free copy of bitmap info struct and resource itself
  1323. ::free(lpBitmapInfo);
  1324. ::FreeResource(hglb);
  1325. return hbm;
  1326. }
  1327. BOOL CToolBarEx::SetIconOptionBitmap(IconOptions eIconOptions)
  1328. {
  1329. if ((m_hInstImageWell != NULL) && (m_hRsrcImageWell != NULL))
  1330. {
  1331. HBITMAP hBitmap=NULL;
  1332. HINSTANCE  hInstImageWell= m_hInstImageWell ;
  1333. HRSRC  hRsrcImageWell =  m_hRsrcImageWell ;
  1334. int nCount = 0;
  1335. for(UINT i=0;i<m_nResButtons;i++)
  1336. {
  1337.  
  1338. if ((m_ToolBarInfo[i].tbButton.idCommand !=0))
  1339. nCount++;
  1340. }
  1341. if (eIconOptions==ioSmallIcons)
  1342. {
  1343. CSize  sizeSmallImage(nCount *m_szImageSmall.cx,m_szImageSmall.cy);
  1344. hBitmap= LoadSysColorBitmapSize(m_hInstImageWell, m_hRsrcImageWell,sizeSmallImage);
  1345. }
  1346. else
  1347. {
  1348. ASSERT(eIconOptions==ioLargeIcons);
  1349. CSize  sizeLargeImage(nCount *m_szImageLarge.cx,m_szImageLarge.cy);
  1350. hBitmap= LoadSysColorBitmapSize(m_hInstImageWell, m_hRsrcImageWell,sizeLargeImage);
  1351. }
  1352. ASSERT(hBitmap);
  1353. SetBitmap(hBitmap);
  1354. m_hInstImageWell = hInstImageWell; // SetBitmap resets these
  1355. m_hRsrcImageWell = hRsrcImageWell; // SetBitmap resets these
  1356. return TRUE;
  1357. }
  1358. return FALSE;
  1359. }
  1360. void CToolBarEx::OnSysColorChange() 
  1361. {
  1362. m_clrBtnShadow=::GetSysColor(COLOR_BTNSHADOW);
  1363. m_clrBtnHilight=::GetSysColor(COLOR_BTNHILIGHT);
  1364. m_clrBtnFace  = ::GetSysColor(COLOR_BTNFACE);
  1365. SetIconOptions(m_eIconOptions); //load bitmap again
  1366. }
  1367. void CToolBarEx::OnSave( NMHDR* pNMHDR, LRESULT* pResult )
  1368. {
  1369.     NMTBSAVE* lpnmtb = ( NMTBSAVE* )pNMHDR;
  1370.     if ( lpnmtb->iItem == -1 )
  1371.     {
  1372.         lpnmtb->cbData  += sizeof( DWORD ) * 2;
  1373.         lpnmtb->pData    = ( LPDWORD )::GlobalAlloc( GMEM_FIXED, lpnmtb->cbData );  //freed by Toolbar ( Not sure)
  1374.         lpnmtb->pCurrent = lpnmtb->pData;
  1375.         *lpnmtb->pCurrent++ = (DWORD)m_eIconOptions;
  1376.         *lpnmtb->pCurrent++ = (DWORD)m_eTextOptions;
  1377.     }
  1378.     *pResult = 0;
  1379. }
  1380. void CToolBarEx::OnRestore( NMHDR* pNMHDR, LRESULT* pResult )
  1381. {
  1382.     NMTBRESTORE* lpnmtb = ( NMTBRESTORE* )pNMHDR;
  1383.     if ( lpnmtb->iItem == -1 )
  1384.     {
  1385.         lpnmtb->cButtons = ( lpnmtb->cbData - sizeof( DWORD ) * 2 ) / lpnmtb->cbBytesPerRecord;
  1386.         lpnmtb->pCurrent = lpnmtb->pData;
  1387.         m_eIconOptions=(IconOptions)*lpnmtb->pCurrent++ ;
  1388.         m_eTextOptions=(TextOptions)*lpnmtb->pCurrent++ ;
  1389.     }
  1390.     *pResult = 0;
  1391. }
  1392. BOOL CToolBarEx::ShowContextMenu(CPoint point)
  1393. {
  1394. if( GetToolBarCtrl().GetButtonCount() && m_ToolBarInfo.GetSize())
  1395. {
  1396. CPoint pt( point );
  1397. ClientToScreen( &pt );
  1398. // load and display popup menu
  1399. CMenu popupMenu;
  1400. VERIFY(popupMenu.CreatePopupMenu());
  1401. CFrameWnd * pFrame=(CFrameWnd *)AfxGetMainWnd();
  1402. if (pFrame && pFrame->IsKindOf(RUNTIME_CLASS(CFrameWnd)) )
  1403. {
  1404. ASSERT_VALID(pFrame);
  1405. POSITION pos = pFrame->m_listControlBars.GetHeadPosition();
  1406. while (pos != NULL)
  1407. {
  1408. const CControlBar* pBar = (CControlBar*)pFrame->m_listControlBars.GetNext(pos);
  1409. ASSERT(pBar != NULL);
  1410. if (pBar && 
  1411. pBar->IsKindOf(RUNTIME_CLASS(CToolBar))) // Put any other type
  1412. {
  1413. ASSERT_VALID(pBar);
  1414. CString strName;
  1415. pBar->GetWindowText(strName);
  1416. popupMenu.AppendMenu( (pBar->GetStyle()&WS_VISIBLE?MF_CHECKED:MF_UNCHECKED)|MF_STRING,
  1417. pBar->GetDlgCtrlID(),
  1418. strName);
  1419. }
  1420. }
  1421. //Add a Seperator
  1422. popupMenu.AppendMenu(MF_SEPARATOR) ;
  1423. }
  1424. //Finally a Customize
  1425. popupMenu.AppendMenu(MF_STRING ,ID_CUSTOMIZE_BAR, STR_CUSTOMIZE);
  1426. int nResult = popupMenu.TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL|TPM_RETURNCMD,pt.x, pt.y, this );
  1427. switch(nResult)
  1428. {
  1429. case 0: //Nothing clicked  on menu
  1430. break;
  1431. case ID_CUSTOMIZE_BAR  :
  1432. // open the customization dialog.
  1433. Customize();
  1434. break;
  1435. default:
  1436. {
  1437. ASSERT_VALID(pFrame);
  1438. if (pFrame && pFrame->IsKindOf(RUNTIME_CLASS(CFrameWnd)) )
  1439. {
  1440. pFrame->OnBarCheck(nResult);
  1441. }
  1442. }
  1443. }
  1444. return TRUE;
  1445. }
  1446. return FALSE;
  1447. }
  1448. void CToolBarEx::OnContextMenu(CWnd* pWnd, CPoint point) 
  1449. {
  1450. ASSERT_VALID(pWnd);
  1451. CPoint pt(point);
  1452. if (WindowFromPoint(pt)!=this) return;
  1453. ScreenToClient(&pt);
  1454. if (!ShowContextMenu(pt))
  1455. CToolBar::OnContextMenu(pWnd,point);
  1456. }
  1457. void CToolBarEx::Customize()
  1458. {
  1459. GetToolBarCtrl().Customize();
  1460. }
  1461. void CToolBarEx::OnInitCustomize( NMHDR* /*pNMHDR*/, LRESULT* pResult )
  1462. {
  1463.     *pResult = TBNRF_HIDEHELP;  // help button  is hidden      
  1464. }
  1465. void CToolBarEx::OnCustomDraw( NMHDR* pNMHDR, LRESULT* pResult )
  1466. {
  1467. LPNMTBCUSTOMDRAW lpNMCustomDraw = (LPNMTBCUSTOMDRAW) pNMHDR;
  1468. ASSERT_POINTER(lpNMCustomDraw,NMTBCUSTOMDRAW);
  1469. switch(lpNMCustomDraw->nmcd.dwDrawStage)
  1470. {
  1471. case CDDS_PREPAINT:
  1472. *pResult = CDRF_NOTIFYITEMDRAW    ;
  1473. break;
  1474. case CDDS_ITEMPREPAINT:
  1475. // draw the button
  1476. {
  1477. if (lpNMCustomDraw->nmcd.uItemState & CDIS_HOT)
  1478. {
  1479. //draw button
  1480. CDC dc;
  1481. CRect rt(lpNMCustomDraw->nmcd.rc);
  1482. TBBUTTONINFO bbi;
  1483. int xOffset=5,yOffset=3;
  1484. dc.Attach(lpNMCustomDraw->nmcd.hdc);
  1485. //Init button info
  1486. memset(&bbi,0,sizeof(bbi));
  1487. bbi.cbSize =sizeof(bbi);
  1488. bbi.dwMask = TBIF_IMAGE;
  1489. GetToolBarCtrl().GetButtonInfo(lpNMCustomDraw->nmcd.dwItemSpec,&bbi);
  1490. //draw shadow
  1491. CDC  dcGlyphs;
  1492. dcGlyphs.CreateCompatibleDC(NULL);
  1493. HBITMAP hbmOld = (HBITMAP)dcGlyphs.SelectObject(m_hbmImageWell);
  1494. dc.BitBlt(rt.left+xOffset+1,rt.top+yOffset+1,m_sizeImage.cx,m_sizeImage.cy,&dcGlyphs,m_sizeImage.cx*bbi.iImage,0,SRCCOPY);
  1495. dcGlyphs.SelectObject(hbmOld);
  1496. dcGlyphs.DeleteDC();
  1497. // darken the drawn thing
  1498. long r,g,b;
  1499. float  perc=0.07f;
  1500. for (int x= rt.left+1;x< rt.right;x++)
  1501. for (int y= rt.top+1;y< rt.bottom;y++)
  1502. {
  1503. COLORREF cr = dc.GetPixel(CPoint(x,y));
  1504. if (cr == m_clrBtnFace)
  1505. {
  1506. r = GetRValue(cr);
  1507. g = GetGValue(cr);
  1508. b = GetBValue(cr);
  1509. r -=(BYTE)(r*perc);
  1510. g -=(BYTE)(g*perc);
  1511. b -=(BYTE)(b*perc);
  1512. dc.SetPixel(CPoint(x,y),RGB(r,g,b));
  1513. }
  1514. else
  1515. dc.SetPixel(CPoint(x,y),m_clrBtnShadow);  // this creates shadow
  1516. }
  1517. dc.Draw3dRect(&rt,m_clrBtnShadow,m_clrBtnShadow);
  1518. dc.Detach();
  1519. *pResult = CDRF_SKIPDEFAULT;
  1520. }
  1521. else  // for normal cases
  1522. {
  1523. *pResult = CDRF_DODEFAULT ;
  1524. }
  1525. }
  1526. break;
  1527. case CDRF_NOTIFYPOSTPAINT :
  1528. *pResult = CDRF_DODEFAULT ;
  1529. ASSERT(FALSE);
  1530. break;
  1531. default:
  1532. *pResult = CDRF_DODEFAULT ;
  1533. }
  1534. }
  1535. void CToolBarEx::OnNcPaint() 
  1536. {
  1537. if( GetToolBarCtrl().GetStyle()& TBSTYLE_FLAT ) 
  1538. {
  1539. // get window DC that is clipped to the non-client area
  1540. CWindowDC dc(this);
  1541. CRect rectClient;
  1542. GetClientRect(rectClient);
  1543. CRect rectWindow;
  1544. GetWindowRect(rectWindow);
  1545. ScreenToClient(rectWindow);
  1546. rectClient.OffsetRect(-rectWindow.left, -rectWindow.top);
  1547. dc.ExcludeClipRect(rectClient);
  1548. // draw borders in non-client area
  1549. rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);
  1550. Draw3DBorders(&dc, rectWindow);
  1551. dc.IntersectClipRect(rectWindow);
  1552. // erase parts not drawn
  1553. SendMessage(WM_ERASEBKGND, (WPARAM)dc.m_hDC);
  1554. DrawGripper(&dc,rectWindow);
  1555. else
  1556. {
  1557. CToolBar::OnNcPaint();
  1558. }
  1559. }
  1560. void CToolBarEx :: Draw3DBorders(CDC * pDC, CRect & rect) 
  1561. {
  1562. ASSERT_VALID(this);
  1563. ASSERT_VALID(pDC);
  1564. if( GetToolBarCtrl().GetStyle()& TBSTYLE_FLAT ) 
  1565. {
  1566. DWORD dwStyle = m_dwStyle;
  1567. if (!(dwStyle & CBRS_BORDER_ANY))
  1568. return;
  1569. COLORREF clr = (m_dwStyle & CBRS_BORDER_3D) ? m_clrBtnHilight : m_clrBtnShadow;
  1570. if(m_dwStyle & CBRS_BORDER_LEFT)
  1571. pDC->FillSolidRect(0, 0, 1, rect.Height() - 1, clr);
  1572. if(m_dwStyle & CBRS_BORDER_TOP)
  1573. pDC->FillSolidRect(0, 0, rect.Width()-1 , 1, clr);
  1574. // this for ver 6.0
  1575. if (dwStyle & CBRS_BORDER_ANY)
  1576. {
  1577. CRect rctBk;
  1578. rctBk.left = 0;
  1579. rctBk.right = rect.right;
  1580. rctBk.top = rect.top;
  1581. rctBk.bottom = rect.bottom;
  1582. pDC->FillSolidRect((LPRECT)rctBk, pDC->GetBkColor());
  1583. }
  1584. if(m_dwStyle & CBRS_BORDER_RIGHT)
  1585. pDC->FillSolidRect(rect.right, 1, -1, rect.Height() - 1, m_clrBtnShadow);
  1586. if(m_dwStyle & CBRS_BORDER_BOTTOM)
  1587. pDC->FillSolidRect(0, rect.bottom, rect.Width()-1, -1, m_clrBtnShadow);
  1588. // if undockable toolbar at top of frame, apply special formatting to mesh
  1589. // properly with frame menu
  1590. if(!m_pDockContext) 
  1591. {
  1592. pDC->FillSolidRect(0,0,rect.Width(),1,m_clrBtnShadow);
  1593. pDC->FillSolidRect(0,1,rect.Width(),1,m_clrBtnHilight);
  1594. }
  1595. if (dwStyle & CBRS_BORDER_LEFT)
  1596. ++rect.left;
  1597. if (dwStyle & CBRS_BORDER_TOP)
  1598. ++rect.top;
  1599. if (dwStyle & CBRS_BORDER_RIGHT)
  1600. --rect.right;
  1601. if (dwStyle & CBRS_BORDER_BOTTOM)
  1602. --rect.bottom;
  1603. else
  1604. {
  1605. DrawBorders(pDC, rect);
  1606. }
  1607. }
  1608.  
  1609. BOOL CToolBarEx::LoadBitmap(LPCTSTR lpszResourceName)
  1610. {
  1611. ASSERT_VALID(this);
  1612. ASSERT(lpszResourceName != NULL);
  1613. // determine location of the bitmap in resource fork
  1614. HINSTANCE hInstImageWell = AfxFindResourceHandle(lpszResourceName, RT_BITMAP);
  1615. HRSRC hRsrcImageWell = ::FindResource(hInstImageWell, lpszResourceName, RT_BITMAP);
  1616. if (hRsrcImageWell == NULL)
  1617. return FALSE;
  1618. // delete last one
  1619. if (hRsrcImageWell) ::DeleteObject(hRsrcImageWell);
  1620. // remember the resource handles so the bitmap can be recolored if necessary
  1621. m_hInstImageWell = hInstImageWell;
  1622. m_hRsrcImageWell = hRsrcImageWell;
  1623. return TRUE;
  1624. }
  1625. /////////////////////////////////////////////////////////////////////////////
  1626. // CDockBarEx
  1627. CDockBarEx::CDockBarEx()
  1628. {
  1629. // TODO: add construction code here.
  1630. }
  1631. CDockBarEx::~CDockBarEx()
  1632. {
  1633. // TODO: add destruction code here.
  1634. }
  1635. IMPLEMENT_DYNAMIC(CDockBarEx, CDockBar)
  1636. BEGIN_MESSAGE_MAP(CDockBarEx, CDockBar)
  1637. //{{AFX_MSG_MAP(CDockBarEx)   
  1638. // NOTE - the ClassWizard will add and remove mapping macros here.
  1639. //    DO NOT EDIT what you see in these blocks of generated code!
  1640. //}}AFX_MSG_MAP
  1641. END_MESSAGE_MAP()
  1642. /////////////////////////////////////////////////////////////////////////////
  1643. // CDockBarEx message handlers
  1644. CSize CDockBarEx::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
  1645. {
  1646. ASSERT_VALID(this);
  1647. CSize sizeFixed = CControlBar::CalcFixedLayout(bStretch, bHorz);
  1648. // get max size
  1649. CSize sizeMax;
  1650. if (!m_rectLayout.IsRectEmpty())
  1651. {
  1652. CRect rect = m_rectLayout;
  1653. CalcInsideRect(rect, bHorz);
  1654. sizeMax = rect.Size();
  1655. }
  1656. else
  1657. {
  1658. CRect rectFrame;
  1659. CFrameWnd* pFrame = GetParentFrame();
  1660. pFrame->GetClientRect(&rectFrame);
  1661. sizeMax = rectFrame.Size();
  1662. }
  1663. // prepare for layout
  1664. AFX_SIZEPARENTPARAMS layout;
  1665. layout.hDWP = m_bLayoutQuery ?
  1666. NULL : ::BeginDeferWindowPos(m_arrBars.GetSize());
  1667. int cxBorder = 2, cyBorder = 2;
  1668. CPoint pt(-cxBorder, -cyBorder);
  1669. int nWidth = 0;
  1670. BOOL bWrapped = FALSE;
  1671. // layout all the control bars
  1672. for (int nPos = 0; nPos < m_arrBars.GetSize(); nPos++)
  1673. {
  1674. CControlBar* pBar = GetDockedControlBar(nPos);
  1675. void* pVoid = m_arrBars[nPos];
  1676. if (pBar != NULL)
  1677. {
  1678. if(pBar->IsKindOf(RUNTIME_CLASS(CToolBarEx)))
  1679. {
  1680.   if (pBar->GetStyle() & TBSTYLE_FLAT)
  1681. cxBorder = cyBorder = 0;
  1682.   else
  1683. cxBorder = cyBorder = 2;
  1684. }
  1685. else
  1686. cxBorder = cyBorder = 2;
  1687. if (pBar->IsVisible())
  1688. {
  1689. // get ideal rect for bar
  1690. DWORD dwMode = 0;
  1691. if ((pBar->m_dwStyle & CBRS_SIZE_DYNAMIC) &&
  1692. (pBar->m_dwStyle & CBRS_FLOATING))
  1693. dwMode |= LM_HORZ | LM_MRUWIDTH;
  1694. else if (pBar->m_dwStyle & CBRS_ORIENT_HORZ)
  1695. dwMode |= LM_HORZ | LM_HORZDOCK;
  1696. else
  1697. dwMode |=  LM_VERTDOCK;
  1698. CSize sizeBar = pBar->CalcDynamicLayout(-1, dwMode);
  1699. CRect rect(pt, sizeBar);
  1700. // get current rect for bar
  1701. CRect rectBar;
  1702. pBar->GetWindowRect(&rectBar);
  1703. ScreenToClient(&rectBar);
  1704. if (bHorz)
  1705. {
  1706. // Offset Calculated Rect out to Actual
  1707. if (rectBar.left > rect.left && !m_bFloating)
  1708. rect.OffsetRect(rectBar.left - rect.left, 0);
  1709. // If ControlBar goes off the right, then right justify
  1710. if (rect.right > sizeMax.cx && !m_bFloating)
  1711. {
  1712. int x = rect.Width() - cxBorder;
  1713. x = max(sizeMax.cx - x, pt.x);
  1714. rect.OffsetRect(x - rect.left, 0);
  1715. }
  1716. // If ControlBar has been wrapped, then left justify
  1717. if (bWrapped)
  1718. {
  1719. bWrapped = FALSE;
  1720. rect.OffsetRect(-(rect.left + cxBorder), 0);
  1721. }
  1722. // If ControlBar is completely invisible, then wrap it
  1723. else if ((rect.left >= (sizeMax.cx - cxBorder)) &&
  1724. (nPos > 0) && (m_arrBars[nPos - 1] != NULL))
  1725. {
  1726. m_arrBars.InsertAt(nPos, (CObject*)NULL);
  1727. pBar = NULL; pVoid = NULL;
  1728. bWrapped = TRUE;
  1729. }
  1730. if (!bWrapped)
  1731. {
  1732. if (rect != rectBar)
  1733. {
  1734. if (!m_bLayoutQuery &&
  1735. !(pBar->m_dwStyle & CBRS_FLOATING))
  1736. {
  1737. pBar->m_pDockContext->m_rectMRUDockPos = rect;
  1738. }
  1739. AfxRepositionWindow(&layout, pBar->m_hWnd, &rect);
  1740. }
  1741. pt.x = rect.left + sizeBar.cx - cxBorder;
  1742. nWidth = max(nWidth, sizeBar.cy);
  1743. }
  1744. }
  1745. else
  1746. {
  1747. // Offset Calculated Rect out to Actual
  1748. if (rectBar.top > rect.top && !m_bFloating)
  1749. rect.OffsetRect(0, rectBar.top - rect.top);
  1750. // If ControlBar goes off the bottom, then bottom justify
  1751. if (rect.bottom > sizeMax.cy && !m_bFloating)
  1752. {
  1753. int y = rect.Height() - cyBorder;
  1754. y = max(sizeMax.cy - y, pt.y);
  1755. rect.OffsetRect(0, y - rect.top);
  1756. }
  1757. // If ControlBar has been wrapped, then top justify
  1758. if (bWrapped)
  1759. {
  1760. bWrapped = FALSE;
  1761. rect.OffsetRect(0, -(rect.top + cyBorder));
  1762. }
  1763. // If ControlBar is completely invisible, then wrap it
  1764. else if ((rect.top >= (sizeMax.cy - cyBorder)) &&
  1765. (nPos > 0) && (m_arrBars[nPos - 1] != NULL))
  1766. {
  1767. m_arrBars.InsertAt(nPos, (CObject*)NULL);
  1768. pBar = NULL; pVoid = NULL;
  1769. bWrapped = TRUE;
  1770. }
  1771. if (!bWrapped)
  1772. {
  1773. if (rect != rectBar)
  1774. {
  1775. if (!m_bLayoutQuery &&
  1776. !(pBar->m_dwStyle & CBRS_FLOATING))
  1777. {
  1778. pBar->m_pDockContext->m_rectMRUDockPos = rect;
  1779. }
  1780. AfxRepositionWindow(&layout, pBar->m_hWnd, &rect);
  1781. }
  1782. pt.y = rect.top + sizeBar.cy - cyBorder;
  1783. nWidth = max(nWidth, sizeBar.cx);
  1784. }
  1785. }
  1786. }
  1787. if (!bWrapped)
  1788. {
  1789. // handle any delay/show hide for the bar
  1790. pBar->RecalcDelayShow(&layout);
  1791. }
  1792. }
  1793. if (pBar == NULL && pVoid == NULL && nWidth != 0)
  1794. {
  1795. // end of row because pBar == NULL
  1796. if (bHorz)
  1797. {
  1798. pt.y += nWidth - cyBorder;
  1799. sizeFixed.cx = max(sizeFixed.cx, pt.x);
  1800. sizeFixed.cy = max(sizeFixed.cy, pt.y);
  1801. pt.x = -cxBorder;
  1802. }
  1803. else
  1804. {
  1805. pt.x += nWidth - cxBorder;
  1806. sizeFixed.cx = max(sizeFixed.cx, pt.x);
  1807. sizeFixed.cy = max(sizeFixed.cy, pt.y);
  1808. pt.y = -cyBorder;
  1809. }
  1810. nWidth = 0;
  1811. }
  1812. }
  1813. if (!m_bLayoutQuery)
  1814. {
  1815. // move and resize all the windows at once!
  1816. if (layout.hDWP == NULL || !::EndDeferWindowPos(layout.hDWP))
  1817. TRACE0("Warning: DeferWindowPos failed - low system resources.n");
  1818. }
  1819. // adjust size for borders on the dock bar itself
  1820. CRect rect;
  1821. rect.SetRectEmpty();
  1822. CalcInsideRect(rect, bHorz);
  1823. if ((!bStretch || !bHorz) && sizeFixed.cx != 0)
  1824. sizeFixed.cx += -rect.right + rect.left;
  1825. if ((!bStretch || bHorz) && sizeFixed.cy != 0)
  1826. sizeFixed.cy += -rect.bottom + rect.top;
  1827. return sizeFixed;
  1828. }
  1829. // dwDockBarMap
  1830. const DWORD dwDockBarMap[4][2] =
  1831. {
  1832. { AFX_IDW_DOCKBAR_TOP,      CBRS_TOP    },
  1833. { AFX_IDW_DOCKBAR_BOTTOM,   CBRS_BOTTOM },
  1834. { AFX_IDW_DOCKBAR_LEFT,     CBRS_LEFT   },
  1835. { AFX_IDW_DOCKBAR_RIGHT,    CBRS_RIGHT  },
  1836. };
  1837. void FrameEnableDocking(CFrameWnd * pFrame, DWORD dwDockStyle) 
  1838. {
  1839. ASSERT_VALID(pFrame);
  1840. // must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only
  1841. ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);
  1842. pFrame->EnableDocking(dwDockStyle);
  1843. for (int i = 0; i < 4; i++) {
  1844. if (dwDockBarMap[i][1] & dwDockStyle & CBRS_ALIGN_ANY) {
  1845. CDockBar* pDock = (CDockBar*)pFrame->GetControlBar(dwDockBarMap[i][0]);
  1846. // make sure the dock bar is of correct type
  1847. if( pDock == 0 || ! pDock->IsKindOf(RUNTIME_CLASS(CDockBarEx)) ) {
  1848. BOOL bNeedDelete = ! pDock->m_bAutoDelete;
  1849. pDock->m_pDockSite->RemoveControlBar(pDock);
  1850. pDock->m_pDockSite = 0; // avoid problems in destroying the dockbar
  1851. pDock->DestroyWindow();
  1852. if( bNeedDelete )
  1853. delete pDock;
  1854. pDock = 0;
  1855. }
  1856. if( pDock == 0 ) {
  1857. pDock = new CDockBarEx;
  1858. ASSERT_VALID(pDock);
  1859. if ((!pDock) || (!pDock->Create(pFrame,
  1860. WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE |
  1861. dwDockBarMap[i][1], dwDockBarMap[i][0]))) {
  1862. AfxThrowResourceException();
  1863. }
  1864. }
  1865. }
  1866. }
  1867. }
  1868. BOOL CToolBarEx::MarkDefaultState()
  1869. {
  1870.  CToolBarCtrl & tbCtrl = GetToolBarCtrl();
  1871.  //Set intial Visible info
  1872. for (int i=0;i<m_ToolBarInfo.GetSize();i++)
  1873. {
  1874. if  ( (m_ToolBarInfo[i].tbButton.fsStyle & TBSTYLE_SEP) == 0)  //   seperator ?
  1875. {  // Not a seperator
  1876.  if  (tbCtrl.CommandToIndex(m_ToolBarInfo[i].tbButton.idCommand)==-1) // button exists on toolbar
  1877. {
  1878. m_ToolBarInfo[i].bInitiallyVisible=FALSE;
  1879. }
  1880. else
  1881. {
  1882. m_ToolBarInfo[i].bInitiallyVisible=TRUE;
  1883. }
  1884. }
  1885. else
  1886. {
  1887. if (m_ToolBarInfo[i].tbButton.idCommand>0)
  1888. {
  1889. if (tbCtrl.CommandToIndex(m_ToolBarInfo[i].tbButton.idCommand)==-1)
  1890. {
  1891. m_ToolBarInfo[i].bInitiallyVisible=FALSE;
  1892. }
  1893. else
  1894. {
  1895. m_ToolBarInfo[i].bInitiallyVisible=TRUE;
  1896. }
  1897. }
  1898. else
  1899. {
  1900. m_ToolBarInfo[i].bInitiallyVisible=TRUE; // simple seperatores are visible
  1901. }
  1902. }
  1903. }
  1904. return TRUE;
  1905. }