Toolbarex.cpp
上传用户:lczygg
上传日期:2007-07-03
资源大小:2947k
文件大小:56k
源码类别:

语音合成与识别

开发平台:

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