Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1379 lines
39 KiB

  1. /******************************************************************************
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. Toolbar.cpp
  5. Abstract:
  6. This file contains the ActiveX control that makes Win32 ToolBars available to HTML.
  7. Revision History:
  8. Davide Massarenti (Dmassare) 03/04/2001
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. #include <comctrlp.h>
  13. ////////////////////////////////////////////////////////////////////////////////
  14. #define HISTORY_MENU__LIMIT (10) // Just pick a limited number of items.
  15. ////////////////////////////////////////////////////////////////////////////////
  16. static const MPC::StringToBitField c_Images[] =
  17. {
  18. { L"BACK" , -1, 0, -1 },
  19. { L"FORWARD" , -1, 1, -1 },
  20. { L"HOME" , -1, 2, -1 },
  21. { L"INDEX" , -1, 3, -1 },
  22. { L"FAVORITES" , -1, 4, -1 },
  23. { L"HISTORY" , -1, 5, -1 },
  24. { L"SUPPORT" , -1, 6, -1 },
  25. { L"OPTIONS" , -1, 7, -1 },
  26. { L"ADDFAV" , -1, 8, -1 },
  27. { L"PRINT" , -1, 9, -1 },
  28. { L"LOCATE" , -1, 10, -1 },
  29. { L"LAYOUT_SMALL", -1, 11, -1 },
  30. { L"LAYOUT_LARGE", -1, 12, -1 },
  31. { NULL }
  32. };
  33. const MPC::StringToBitField CPCHToolBar::c_TypeLookup[] =
  34. {
  35. { L"BACK" , -1, CPCHToolBar::TYPE_back , -1 },
  36. { L"FORWARD" , -1, CPCHToolBar::TYPE_forward , -1 },
  37. { L"SEPARATOR", -1, CPCHToolBar::TYPE_separator, -1 },
  38. { L"GENERIC" , -1, CPCHToolBar::TYPE_generic , -1 },
  39. { NULL }
  40. };
  41. CFG_BEGIN_FIELDS_MAP(CPCHToolBar::Button)
  42. CFG_ATTRIBUTE ( L"ID" , wstring, m_strID ),
  43. CFG_ATTRIBUTE ( L"ACCESSKEY" , WCHAR , m_wch ),
  44. CFG_ATTRIBUTE ( L"ENABLED" , bool , m_fEnabled ),
  45. CFG_ATTRIBUTE ( L"VISIBLE" , bool , m_fVisible ),
  46. CFG_ATTRIBUTE ( L"HIDETEXT" , bool , m_fHideText ),
  47. CFG_ATTRIBUTE ( L"SYSTEMMENU" , bool , m_fSystemMenu ),
  48. CFG_ATTRIBUTE__BITFIELD( L"TYPE" , m_dwType , c_TypeLookup ),
  49. CFG_ELEMENT ( L"IMAGE_NORMAL" , wstring, m_strImage_Normal ),
  50. CFG_ELEMENT ( L"IMAGE_HOT" , wstring, m_strImage_Hot ),
  51. CFG_ELEMENT ( L"TEXT" , wstring, m_strText ),
  52. CFG_ELEMENT ( L"TOOLTIP" , wstring, m_strToolTip ),
  53. CFG_END_FIELDS_MAP()
  54. CFG_BEGIN_CHILD_MAP(CPCHToolBar::Button)
  55. CFG_END_CHILD_MAP()
  56. DEFINE_CFG_OBJECT(CPCHToolBar::Button,L"BUTTON")
  57. DEFINE_CONFIG_METHODS__NOCHILD(CPCHToolBar::Button)
  58. ////////////////////
  59. CFG_BEGIN_FIELDS_MAP(CPCHToolBar::Config)
  60. CFG_ATTRIBUTE( L"WIDTH" , long, m_lWidth ),
  61. CFG_ATTRIBUTE( L"HEIGHT" , long, m_lHeight ),
  62. CFG_ATTRIBUTE( L"ICONSIZE", long, m_lIconSize ),
  63. CFG_END_FIELDS_MAP()
  64. CFG_BEGIN_CHILD_MAP(CPCHToolBar::Config)
  65. CFG_CHILD(CPCHToolBar::Button)
  66. CFG_END_CHILD_MAP()
  67. DEFINE_CFG_OBJECT(CPCHToolBar::Config,L"TOOLBAR")
  68. DEFINE_CONFIG_METHODS_CREATEINSTANCE_SECTION(CPCHToolBar::Config,tag,defSubType)
  69. if(tag == _cfg_table_tags[0])
  70. {
  71. defSubType = &(*(m_lstButtons.insert( m_lstButtons.end() )));
  72. return S_OK;
  73. }
  74. DEFINE_CONFIG_METHODS_SAVENODE_SECTION(CPCHToolBar::Config,xdn)
  75. DEFINE_CONFIG_METHODS_END(CPCHToolBar::Config)
  76. ////////////////////////////////////////////////////////////////////////////////
  77. CPCHToolBar::Button::Button()
  78. {
  79. // MPC::wstring m_strID;
  80. m_wch = 0; // WCHAR m_wch;
  81. m_fEnabled = false; // bool m_fEnabled;
  82. m_fVisible = false; // bool m_fVisible;
  83. m_fHideText = false; // bool m_fHideText;
  84. m_fSystemMenu = false; // bool m_fSystemMenu;
  85. // MPC::wstring m_strType;
  86. //
  87. // MPC::wstring m_strImage_Normal;
  88. // MPC::wstring m_strImage_Hot;
  89. // MPC::wstring m_strText;
  90. // MPC::wstring m_strToolTip;
  91. //
  92. //
  93. m_idCmd = 0; // int m_idCmd;
  94. m_iImage_Normal = -1; // int m_iImage_Normal;
  95. m_iImage_Hot = -1; // int m_iImage_Hot;
  96. }
  97. void CPCHToolBar::Button::UpdateState( /*[in]*/ HWND hwndTB )
  98. {
  99. LRESULT lResult = ::SendMessageW( hwndTB, TB_GETSTATE, m_idCmd, 0 );
  100. lResult &= ~(TBSTATE_ENABLED | TBSTATE_INDETERMINATE | TBSTATE_HIDDEN);
  101. lResult |= (m_fEnabled ? TBSTATE_ENABLED : TBSTATE_INDETERMINATE);
  102. lResult |= (m_fVisible ? 0 : TBSTATE_HIDDEN );
  103. ::SendMessageW( hwndTB, TB_SETSTATE, m_idCmd, MAKELONG(lResult, 0) );
  104. }
  105. ////////////////////////////////////////////////////////////////////////////////
  106. CPCHToolBar::Config::Config()
  107. {
  108. // long m_lWidth;
  109. // long m_lHeight;
  110. // long m_lIconSize;
  111. //
  112. m_mode = TB_SELECTED; // TB_MODE m_mode;
  113. // ButtonList m_lstButtons;
  114. //
  115. m_himlNormal = NULL; // HIMAGELIST m_himlNormal;
  116. m_himlHot = NULL; // HIMAGELIST m_himlHot;
  117. if(CPCHOptions::s_GLOBAL)
  118. {
  119. m_mode = CPCHOptions::s_GLOBAL->TextLabels();
  120. }
  121. Reset();
  122. }
  123. CPCHToolBar::Button* CPCHToolBar::Config::LookupButton( /*[in]*/ LPCWSTR szID ,
  124. /*[in]*/ int idCmd )
  125. {
  126. for(ButtonIter it = m_lstButtons.begin(); it != m_lstButtons.end(); it++)
  127. {
  128. Button& bt = *it;
  129. if(szID != NULL && bt.m_strID == szID ) return &bt;
  130. if(idCmd != -1 && bt.m_idCmd == idCmd) return &bt;
  131. }
  132. return NULL;
  133. }
  134. void CPCHToolBar::Config::Reset()
  135. {
  136. (void)::ImageList_Destroy( m_himlNormal );
  137. (void)::ImageList_Destroy( m_himlHot );
  138. m_lWidth = 0; // long m_lWidth;
  139. m_lHeight = 0; // long m_lHeight;
  140. m_lIconSize = 24; // long m_lIconSize;
  141. m_fRTL = false; // bool m_fRTL;
  142. //
  143. m_lstButtons.clear(); // ButtonList m_lstButtons;
  144. //
  145. m_himlNormal = NULL; // HIMAGELIST m_himlNormal;
  146. m_himlHot = NULL; // HIMAGELIST m_himlHot;
  147. }
  148. HRESULT CPCHToolBar::Config::Load( /*[in]*/ LPCWSTR szBaseURL ,
  149. /*[in]*/ LPCWSTR szDefinition ,
  150. /*[in]*/ LPCWSTR szDir )
  151. {
  152. __HCP_FUNC_ENTRY( "CPCHToolBar::Config::Load" );
  153. HRESULT hr;
  154. CComPtr<IStream> stream;
  155. Reset();
  156. m_fRTL = (MPC::StrICmp( szDir, L"RTL" ) == 0);
  157. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::HTML::OpenStream( szBaseURL, szDefinition, stream ));
  158. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::Config::LoadStream( this, stream ));
  159. //
  160. // Load all the images.
  161. //
  162. {
  163. COLORREF crMask = RGB( 255, 0, 255 );
  164. LPCWSTR szDef;
  165. LPCWSTR szHot;
  166. int cx;
  167. if(m_lIconSize == 24)
  168. {
  169. szDef = MAKEINTRESOURCEW(IDB_TB_DEF_24);
  170. szHot = MAKEINTRESOURCEW(IDB_TB_HOT_24);
  171. cx = 24;
  172. }
  173. else
  174. {
  175. szDef = MAKEINTRESOURCEW(IDB_TB_DEF_16);
  176. szHot = MAKEINTRESOURCEW(IDB_TB_HOT_16);
  177. cx = 16;
  178. }
  179. m_himlNormal = ::ImageList_LoadImageW( ::GetModuleHandle( NULL ), szDef, cx, 0, crMask, IMAGE_BITMAP, LR_CREATEDIBSECTION );
  180. m_himlHot = ::ImageList_LoadImageW( ::GetModuleHandle( NULL ), szHot, cx, 0, crMask, IMAGE_BITMAP, LR_CREATEDIBSECTION );
  181. for(ButtonIter it = m_lstButtons.begin(); it != m_lstButtons.end(); it++)
  182. {
  183. Button& bt = *it;
  184. if(bt.m_strImage_Normal.size())
  185. {
  186. if(bt.m_strImage_Hot.length() == 0) bt.m_strImage_Hot = bt.m_strImage_Normal;
  187. __MPC_EXIT_IF_METHOD_FAILS(hr, MergeImage( szBaseURL, bt.m_strImage_Normal.c_str(), m_himlNormal, bt.m_iImage_Normal ));
  188. __MPC_EXIT_IF_METHOD_FAILS(hr, MergeImage( szBaseURL, bt.m_strImage_Hot .c_str(), m_himlHot , bt.m_iImage_Hot ));
  189. }
  190. }
  191. }
  192. hr = S_OK;
  193. __HCP_FUNC_CLEANUP;
  194. if(FAILED(hr)) Reset();
  195. __HCP_FUNC_EXIT(hr);
  196. }
  197. HRESULT CPCHToolBar::Config::CreateButtons( /*[in]*/ HWND hwndTB )
  198. {
  199. __HCP_FUNC_ENTRY( "CPCHToolBar::Config::CreateButtons" );
  200. HRESULT hr;
  201. TBBUTTON* tbs = NULL;
  202. int iNum = m_lstButtons.size();
  203. int iCmd = 1;
  204. //
  205. // Remove previous buttons.
  206. //
  207. {
  208. INT_PTR nCount = ::SendMessageW( hwndTB, TB_BUTTONCOUNT, 0, 0L );
  209. while(nCount-- > 0) ::SendMessageW( hwndTB, TB_DELETEBUTTON, nCount, 0L );
  210. }
  211. if(iNum)
  212. {
  213. TBBUTTON* ptr;
  214. ButtonIter it;
  215. __MPC_EXIT_IF_ALLOC_FAILS(hr, tbs, new TBBUTTON[iNum]);
  216. ::SendMessageW( hwndTB, TB_SETIMAGELIST , 0, (LPARAM)m_himlNormal );
  217. ::SendMessageW( hwndTB, TB_SETHOTIMAGELIST, 0, (LPARAM)m_himlHot );
  218. for(ptr = tbs, it = m_lstButtons.begin(); it != m_lstButtons.end(); ptr++, it++)
  219. {
  220. Button& bt = *it; ::ZeroMemory( ptr, sizeof(TBBUTTON) );
  221. bt.m_idCmd = iCmd++;
  222. ptr->iBitmap = I_IMAGECALLBACK;
  223. ptr->idCommand = bt.m_idCmd;
  224. ptr->fsState = (bt.m_fEnabled ? TBSTATE_ENABLED : TBSTATE_INDETERMINATE) | (bt.m_fVisible ? 0 : TBSTATE_HIDDEN) | TBSTATE_ELLIPSES;
  225. ptr->fsStyle |= BTNS_AUTOSIZE;
  226. if(bt.m_strText.size())
  227. {
  228. switch(m_mode)
  229. {
  230. case TB_NONE:
  231. break;
  232. case TB_SELECTED:
  233. if(bt.m_fHideText) break;
  234. case TB_ALL:
  235. ptr->iString = (INT_PTR)bt.m_strText.c_str();
  236. ptr->fsStyle |= BTNS_SHOWTEXT;
  237. break;
  238. }
  239. }
  240. switch(bt.m_dwType)
  241. {
  242. case TYPE_back : ptr->fsStyle |= BTNS_DROPDOWN; break;
  243. case TYPE_forward : ptr->fsStyle |= BTNS_DROPDOWN; break;
  244. case TYPE_separator: ptr->fsStyle |= BTNS_SEP ; ptr->fsStyle &= ~(BTNS_AUTOSIZE | BTNS_SHOWTEXT); break;
  245. case TYPE_generic : break;
  246. }
  247. }
  248. ::SendMessageW( hwndTB, TB_ADDBUTTONSW, iNum, (LPARAM)tbs );
  249. }
  250. ::SendMessageW( hwndTB, TB_AUTOSIZE, 0, 0 );
  251. hr = S_OK;
  252. __HCP_FUNC_CLEANUP;
  253. delete [] tbs;
  254. __HCP_FUNC_EXIT(hr);
  255. }
  256. void CPCHToolBar::Config::UpdateSize( /*[in]*/ HWND hwndTB, /*[in]*/ HWND hwndRB, /*[out]*/ SIZEL& ptIdeal )
  257. {
  258. REBARBANDINFOW rbbi; ::ZeroMemory( &rbbi, sizeof(rbbi) );
  259. RECT rcMax = { 0, 0, 0, 0 };
  260. for(ButtonIter it = m_lstButtons.begin(); it != m_lstButtons.end(); it++)
  261. {
  262. Button& bt = *it;
  263. RECT rc;
  264. if(::SendMessage( hwndTB, TB_GETRECT, bt.m_idCmd, (LPARAM)&rc ))
  265. {
  266. if(rcMax.left > rc.left ) rcMax.left = rc.left ;
  267. if(rcMax.right < rc.right ) rcMax.right = rc.right ;
  268. if(rcMax.top > rc.top ) rcMax.top = rc.top ;
  269. if(rcMax.bottom < rc.bottom) rcMax.bottom = rc.bottom;
  270. }
  271. }
  272. ptIdeal.cx = rcMax.right - rcMax.left;
  273. ptIdeal.cy = rcMax.bottom - rcMax.top;
  274. if(hwndRB)
  275. {
  276. rbbi.cbSize = sizeof(REBARBANDINFOW);
  277. rbbi.fMask = RBBIM_IDEALSIZE;
  278. ::SendMessage( hwndRB, RB_GETBANDINFOW, 0, (LPARAM)&rbbi );
  279. if(rbbi.cxIdeal != ptIdeal.cx)
  280. {
  281. rbbi.cxIdeal = ptIdeal.cx;
  282. ::SendMessage( hwndRB, RB_SETBANDINFOW, 0, (LPARAM)&rbbi );
  283. }
  284. }
  285. }
  286. HRESULT CPCHToolBar::Config::MergeImage( /*[in ]*/ LPCWSTR szBaseURL ,
  287. /*[in ]*/ LPCWSTR szRelativeURL ,
  288. /*[in ]*/ HIMAGELIST himl ,
  289. /*[out]*/ int& iImage )
  290. {
  291. __HCP_FUNC_ENTRY( "CPCHToolBar::Config::MergeImage" );
  292. HRESULT hr;
  293. HBITMAP hBMP = NULL;
  294. if(wcschr( szRelativeURL, '#' ))
  295. {
  296. DWORD dwImage = -1;
  297. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertStringToBitField( &szRelativeURL[1], dwImage, c_Images, /*fUseTilde*/false ));
  298. iImage = dwImage;
  299. }
  300. else
  301. {
  302. COLORREF crMask = RGB( 255, 0, 255 );
  303. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::HTML::DownloadBitmap( szBaseURL, szRelativeURL, crMask, hBMP ));
  304. iImage = ::ImageList_GetImageCount( himl );
  305. ::ImageList_AddMasked( himl, (HBITMAP)hBMP, crMask );
  306. }
  307. hr = S_OK;
  308. __HCP_FUNC_CLEANUP;
  309. if(hBMP) ::DeleteObject( hBMP );
  310. __HCP_FUNC_EXIT(hr);
  311. }
  312. ////////////////////////////////////////////////////////////////////////////////
  313. CPCHToolBar::CPCHToolBar()
  314. {
  315. m_bWindowOnly = TRUE; // Inherited from CComControlBase
  316. m_parent = NULL; // CPCHHelpCenterExternal* m_parent;
  317. m_hwndRB = NULL; // HWND m_hwndRB;
  318. m_hwndTB = NULL; // HWND m_hwndTB;
  319. //
  320. // Config m_cfg;
  321. m_fLoaded = false; // bool m_fLoaded;
  322. {
  323. SIZE ptIdeal;
  324. ptIdeal.cx = 30;
  325. ptIdeal.cy = 30;
  326. AtlPixelToHiMetric( &ptIdeal, &m_sizeExtent );
  327. }
  328. }
  329. CPCHToolBar::~CPCHToolBar()
  330. {
  331. }
  332. STDMETHODIMP CPCHToolBar::SetClientSite( IOleClientSite *pClientSite )
  333. {
  334. CComQIPtr<IServiceProvider> sp = pClientSite;
  335. if(m_parent)
  336. {
  337. CComQIPtr<IPCHHelpCenterExternalPrivate> hcep = m_parent;
  338. if(hcep)
  339. {
  340. hcep->RegisterForMessages( this, /*fRemove*/true );
  341. }
  342. }
  343. MPC::Release( (IUnknown*&)m_parent );
  344. if(sp && SUCCEEDED(sp->QueryService( SID_SElementBehaviorFactory, IID_IPCHHelpCenterExternal, (void **)&m_parent )))
  345. {
  346. CComQIPtr<IPCHHelpCenterExternalPrivate> hcep = m_parent;
  347. if(hcep)
  348. {
  349. hcep->RegisterForMessages( this, /*fRemove*/false );
  350. }
  351. }
  352. return IOleObjectImpl<CPCHToolBar>::SetClientSite( pClientSite );
  353. }
  354. STDMETHODIMP CPCHToolBar::GetExtent( DWORD dwDrawAspect, SIZEL *psizel )
  355. {
  356. if(SUCCEEDED(Config_Load()))
  357. {
  358. UpdateSize();
  359. if(m_cfg.m_lWidth || m_cfg.m_lHeight)
  360. {
  361. SIZE ptIdeal;
  362. SIZEL sizeExtent;
  363. ptIdeal.cx = m_cfg.m_lWidth;
  364. ptIdeal.cy = m_cfg.m_lHeight;
  365. AtlPixelToHiMetric( &ptIdeal, &sizeExtent );
  366. if(m_cfg.m_lWidth != 0) m_sizeExtent.cx = sizeExtent.cx;
  367. if(m_cfg.m_lHeight != 0) m_sizeExtent.cy = sizeExtent.cy;
  368. }
  369. }
  370. return IOleObjectImpl<CPCHToolBar>::GetExtent( dwDrawAspect, psizel );
  371. }
  372. /////////////////////////////////////////////////////////////////////////////
  373. static bool local_IsButtonObscured( /*[in]*/ HWND hwnd, /*[in]*/ RECT& rcSrc, /*[in]*/ UINT_PTR iCmd )
  374. {
  375. UINT_PTR iButton = (UINT_PTR)::SendMessage( hwnd, TB_COMMANDTOINDEX, iCmd, 0 );
  376. if(iButton != -1)
  377. {
  378. RECT rcItem;
  379. if(::SendMessage( hwnd, TB_GETITEMRECT, iButton, (LPARAM)&rcItem ))
  380. {
  381. if(rcSrc.left <= rcItem.left &&
  382. rcSrc.right >= rcItem.right &&
  383. rcSrc.top <= rcItem.top &&
  384. rcSrc.bottom >= rcItem.bottom )
  385. {
  386. return false;
  387. }
  388. }
  389. }
  390. return true;
  391. }
  392. BOOL CPCHToolBar::ProcessWindowMessage( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID )
  393. {
  394. lResult = 0;
  395. switch(uMsg)
  396. {
  397. case WM_THEMECHANGED:
  398. case WM_SYSCOLORCHANGE:
  399. UpdateSize();
  400. break;
  401. case WM_SETTINGCHANGE:
  402. // (weizhao) Relay message to the toolbar control for appropriate handling
  403. // of settings change.
  404. ::SendMessageW( m_hwndTB, uMsg, wParam, lParam);
  405. UpdateSize();
  406. break;
  407. case WM_NOTIFYFORMAT:
  408. if(lParam == NF_QUERY)
  409. {
  410. lResult = NFR_UNICODE;
  411. return TRUE;
  412. }
  413. break;
  414. case WM_CREATE:
  415. if(SUCCEEDED(Rebar_Create ()) &&
  416. SUCCEEDED(Toolbar_Create()) &&
  417. SUCCEEDED(Rebar_AddBand ()) )
  418. {
  419. ;
  420. }
  421. return TRUE;
  422. case WM_SIZE:
  423. {
  424. int nWidth = LOWORD(lParam); // width of client area
  425. int nHeight = HIWORD(lParam); // height of client area
  426. if(m_hwndRB)
  427. {
  428. RECT rc;
  429. int nClientWidth;
  430. int nClientHeight;
  431. ::GetClientRect( m_hwndRB, &rc );
  432. nClientWidth = rc.right - rc.left;
  433. nClientHeight = rc.bottom - rc.top;
  434. // resize the width of the toolbar
  435. if(nClientWidth != nWidth ||
  436. nClientHeight != nHeight )
  437. {
  438. ::SetWindowPos( m_hwndRB, NULL, 0, 0, nWidth, nHeight, SWP_NOZORDER|SWP_NOACTIVATE );
  439. }
  440. }
  441. if(m_parent) (void)m_parent->RefreshLayout();
  442. }
  443. return TRUE;
  444. case WM_DESTROY:
  445. m_hwndRB = NULL;
  446. m_hwndTB = NULL;
  447. return TRUE;
  448. case WM_COMMAND:
  449. switch( HIWORD(wParam) )
  450. {
  451. case BN_CLICKED:
  452. (void)Fire_onCommand( LOWORD(wParam) );
  453. return TRUE;
  454. }
  455. break;
  456. case WM_SYSCOMMAND:
  457. {
  458. for(Config::ButtonIter it = m_cfg.m_lstButtons.begin(); it != m_cfg.m_lstButtons.end(); it++)
  459. {
  460. Button& bt = *it;
  461. if(bt.m_idCmd == LOWORD(wParam))
  462. {
  463. (void)Fire_onCommand( LOWORD(wParam) );
  464. return TRUE;
  465. }
  466. }
  467. }
  468. break;
  469. case WM_NOTIFY:
  470. switch( ((LPNMHDR)lParam)->code )
  471. {
  472. case TBN_GETINFOTIPW:
  473. (void)OnTooltipRequest( (int)wParam, (LPNMTBGETINFOTIPW)lParam );
  474. return TRUE;
  475. case TBN_GETDISPINFOW:
  476. (void)OnDispInfoRequest( (int)wParam, (LPNMTBDISPINFOW)lParam );
  477. return TRUE;
  478. case TBN_DROPDOWN:
  479. (void)OnDropDown( (int)wParam, (LPNMTOOLBAR)lParam );
  480. return TRUE;
  481. case RBN_CHEVRONPUSHED:
  482. (void)OnChevron( (int)wParam, (LPNMREBARCHEVRON)lParam );
  483. return TRUE;
  484. }
  485. break;
  486. case WM_SYSCHAR:
  487. if(ProcessAccessKey( uMsg, wParam, lParam ))
  488. {
  489. lResult = TRUE;
  490. return TRUE;
  491. }
  492. break;
  493. }
  494. return CComControl<CPCHToolBar>::ProcessWindowMessage( hWnd, uMsg, wParam, lParam, lResult, dwMsgMapID );
  495. }
  496. BOOL CPCHToolBar::ProcessAccessKey( UINT uMsg, WPARAM wParam, LPARAM lParam )
  497. {
  498. if(m_hwndTB && ::IsWindowVisible( m_hwndTB ))
  499. {
  500. WCHAR rgBuf1[2]; rgBuf1[0] = (WCHAR)wParam; rgBuf1[1] = 0; ::CharUpperW( rgBuf1 );
  501. WCHAR rgBuf2[2]; rgBuf2[1] = 0;
  502. for(Config::ButtonIter it = m_cfg.m_lstButtons.begin(); it != m_cfg.m_lstButtons.end(); it++)
  503. {
  504. Button& bt = *it;
  505. rgBuf2[0] = bt.m_wch; ::CharUpperW( rgBuf2 );
  506. if(rgBuf1[0] == rgBuf2[0])
  507. {
  508. LRESULT lState = ::SendMessageW( m_hwndTB, TB_GETSTATE, bt.m_idCmd, 0 );
  509. if(!(lState & TBSTATE_HIDDEN ) &&
  510. (lState & TBSTATE_ENABLED) )
  511. {
  512. // (weizhao) - Check if button is obscured (i.e. out of the toolbar
  513. // window). If so, fire the command directly. Otherwise, fire the
  514. // command by sending the mouse messages, as explained below.
  515. // This is added to enable keyboard accessability.
  516. RECT rcSrc;
  517. ::GetClientRect( m_hwndTB, &rcSrc );
  518. if (local_IsButtonObscured( m_hwndTB, rcSrc, bt.m_idCmd ))
  519. {
  520. Fire_onCommand(&bt);
  521. }
  522. else
  523. {
  524. // (tnoonan) - it feels kinda cheesy to send mouse messages, but
  525. // I don't know of a cleaner way which will accomplish what we
  526. // want (like deal with split buttons, mutually exclusive
  527. // buttons, etc.).
  528. RECT rc;
  529. ::SendMessage( m_hwndTB, TB_GETRECT, bt.m_idCmd, (LPARAM)&rc );
  530. ::SendMessage( m_hwndTB, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(rc.left, rc.top) );
  531. ::SendMessage( m_hwndTB, WM_LBUTTONUP , 0 , MAKELONG(rc.left, rc.top) );
  532. }
  533. return TRUE;
  534. }
  535. }
  536. }
  537. }
  538. return FALSE;
  539. }
  540. /////////////////////////////////////////////////////////////////////////////
  541. HRESULT CPCHToolBar::Fire_onCommand( /*[in]*/ Button* bt )
  542. {
  543. if(bt)
  544. {
  545. CComVariant pvars[2];
  546. pvars[1] = this;
  547. pvars[0] = bt->m_strID.c_str();
  548. (void)FireAsync_Generic( DISPID_PCH_TBE__ONCOMMAND, pvars, ARRAYSIZE( pvars ), NULL );
  549. }
  550. return S_OK;
  551. }
  552. HRESULT CPCHToolBar::Fire_onCommand( /*[in]*/ UINT_PTR iCmd )
  553. {
  554. return Fire_onCommand( m_cfg.LookupButton( NULL, iCmd ) );
  555. }
  556. ////////////////////
  557. HRESULT CPCHToolBar::OnTooltipRequest( int idCtrl, LPNMTBGETINFOTIPW tool )
  558. {
  559. Button* bt = m_cfg.LookupButton( NULL, tool->iItem );
  560. if(bt)
  561. {
  562. wcsncpy( tool->pszText, bt->m_strToolTip.c_str(), tool->cchTextMax - 1 );
  563. }
  564. return S_OK;
  565. }
  566. HRESULT CPCHToolBar::OnDispInfoRequest( int idCtrl, LPNMTBDISPINFOW info )
  567. {
  568. Button* bt = m_cfg.LookupButton( NULL, info->idCommand );
  569. if(bt)
  570. {
  571. if(info->dwMask & TBNF_IMAGE)
  572. {
  573. info->iImage = bt->m_iImage_Normal;
  574. }
  575. }
  576. return S_OK;
  577. }
  578. HRESULT CPCHToolBar::OnDropDown( int idCtrl, LPNMTOOLBAR tool )
  579. {
  580. __HCP_FUNC_ENTRY( "CPCHToolBar::OnDropDown" );
  581. HRESULT hr;
  582. Button* bt = m_cfg.LookupButton( NULL, tool->iItem );
  583. HMENU hMenu = NULL;
  584. if(bt)
  585. {
  586. if(m_parent)
  587. {
  588. CPCHHelpSession* hs = m_parent->HelpSession();
  589. if(hs && hs->IsTravelling() == false)
  590. {
  591. CPCHHelpSessionItem* item = hs->Current();
  592. if(item)
  593. {
  594. int iCount = 0;
  595. __MPC_EXIT_IF_CALL_RETURNS_NULL(hr, (hMenu = ::CreatePopupMenu()));
  596. while((item = (bt->m_dwType == TYPE_back ? item->Previous() : item->Next())))
  597. {
  598. if(iCount++ < HISTORY_MENU__LIMIT)
  599. {
  600. CComBSTR bstrTitle;
  601. __MPC_EXIT_IF_METHOD_FAILS(hr, item->get_Title( &bstrTitle ));
  602. if(bstrTitle.Length() == 0) MPC::LocalizeString( IDS_HELPCTR_HIST_NOTITLE, bstrTitle );
  603. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::AppendMenuW( hMenu, MF_STRING, iCount, bstrTitle ));
  604. }
  605. }
  606. if(iCount)
  607. {
  608. ::MapWindowPoints( tool->hdr.hwndFrom, HWND_DESKTOP, (LPPOINT)&tool->rcButton, 2 );
  609. iCount = ::TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY,
  610. tool->rcButton.left, tool->rcButton.bottom, 0, m_hWnd, NULL );
  611. if(iCount != 0)
  612. {
  613. if(bt->m_dwType == TYPE_back) hs->Back ( iCount );
  614. else hs->Forward( iCount );
  615. }
  616. }
  617. }
  618. }
  619. }
  620. }
  621. hr = S_OK;
  622. __HCP_FUNC_CLEANUP;
  623. if(hMenu) ::DestroyMenu( hMenu );
  624. __HCP_FUNC_EXIT(hr);
  625. }
  626. HRESULT CPCHToolBar::OnChevron( int idCtrl, LPNMREBARCHEVRON chev )
  627. {
  628. __HCP_FUNC_ENTRY( "CPCHToolBar::OnChevron" );
  629. HRESULT hr;
  630. RECT rcSrc;
  631. HMENU hMenu = NULL;
  632. bool fFound = false;
  633. __MPC_EXIT_IF_CALL_RETURNS_NULL(hr, (hMenu = ::CreatePopupMenu()));
  634. ::GetClientRect( m_hwndTB, &rcSrc );
  635. for(Config::ButtonIter it = m_cfg.m_lstButtons.begin(); it != m_cfg.m_lstButtons.end(); it++)
  636. {
  637. Button& bt = *it;
  638. if(bt.m_fVisible && bt.m_fEnabled && bt.m_strText.size() && local_IsButtonObscured( m_hwndTB, rcSrc, bt.m_idCmd ))
  639. {
  640. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::AppendMenuW( hMenu, MF_STRING, bt.m_idCmd, bt.m_strText.c_str() ));
  641. fFound = true;
  642. }
  643. }
  644. if(fFound)
  645. {
  646. int iSelected;
  647. ::MapWindowPoints( chev->hdr.hwndFrom, HWND_DESKTOP, (LPPOINT)&chev->rc, 2 );
  648. iSelected = ::TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, chev->rc.left, chev->rc.bottom, 0, m_hWnd, NULL );
  649. if(iSelected != 0)
  650. {
  651. (void)Fire_onCommand( iSelected );
  652. }
  653. }
  654. hr = S_OK;
  655. __HCP_FUNC_CLEANUP;
  656. if(hMenu) ::DestroyMenu( hMenu );
  657. __HCP_FUNC_EXIT(hr);
  658. }
  659. ////////////////////////////////////////////////////////////////////////////////
  660. void CPCHToolBar::UpdateSize()
  661. {
  662. if(m_hwndTB)
  663. {
  664. SIZE ptIdeal;
  665. SIZEL sizeExtent;
  666. m_cfg.UpdateSize( m_hwndTB, m_hwndRB, ptIdeal );
  667. AtlPixelToHiMetric( &ptIdeal, &sizeExtent );
  668. if(m_cfg.m_lHeight == 0) m_sizeExtent.cy = sizeExtent.cy;
  669. {
  670. CComPtr<IHTMLElement> elem;
  671. CComQIPtr<IHTMLElement2> elem2;
  672. if(SUCCEEDED(FindElementThroughThunking( elem )) && (elem2 = elem))
  673. {
  674. CComPtr<IHTMLCurrentStyle> style1;
  675. CComPtr<IHTMLStyle> style2;
  676. if(SUCCEEDED(elem2->get_currentStyle( &style1 )) && style1 &&
  677. SUCCEEDED(elem ->get_style ( &style2 )) && style2 )
  678. {
  679. CComVariant v1;
  680. CComVariant v2;
  681. WCHAR rgBuf[64]; swprintf( rgBuf, L"%ldpx", ptIdeal.cy );
  682. v2 = rgBuf;
  683. style1->get_height( &v1 );
  684. if(v1 != v2)
  685. {
  686. style2->put_height( v2 );
  687. }
  688. }
  689. }
  690. }
  691. if(m_parent && m_parent->Window())
  692. {
  693. HMENU hSys = NULL;
  694. for(Config::ButtonIter it = m_cfg.m_lstButtons.begin(); it != m_cfg.m_lstButtons.end(); it++)
  695. {
  696. Button& bt = *it;
  697. if(bt.m_fSystemMenu)
  698. {
  699. if(!hSys)
  700. {
  701. HMENU hTop;
  702. MENUITEMINFO mii;
  703. CComBSTR bstrTitle; MPC::LocalizeString( IDS_HELPCTR_SYSMENU_GOTO, bstrTitle );
  704. ::ZeroMemory( &mii, sizeof(mii) );
  705. mii.cbSize = sizeof(mii);
  706. mii.fMask = MIIM_ID | MIIM_STRING | MIIM_SUBMENU;
  707. mii.fType = MFT_STRING;
  708. mii.wID = 1;
  709. mii.dwTypeData = bstrTitle;
  710. mii.hSubMenu = hSys = ::CreatePopupMenu();
  711. (void) ::GetSystemMenu( m_parent->Window(), TRUE );
  712. hTop = ::GetSystemMenu( m_parent->Window(), FALSE );
  713. ::AppendMenuW ( hTop, MF_SEPARATOR, 0, 0 );
  714. ::InsertMenuItem( hTop, ::GetMenuItemCount(hTop), TRUE, &mii );
  715. }
  716. if(hSys)
  717. {
  718. switch(bt.m_dwType)
  719. {
  720. case TYPE_separator:
  721. (void)::AppendMenuW( hSys, MF_SEPARATOR, 0, 0 );
  722. break;
  723. case TYPE_back :
  724. case TYPE_forward:
  725. case TYPE_generic:
  726. (void)::AppendMenuW( hSys, MF_STRING | (bt.m_fEnabled ? 0 : MF_GRAYED), bt.m_idCmd, bt.m_strText.c_str() );
  727. break;
  728. }
  729. }
  730. }
  731. }
  732. }
  733. }
  734. }
  735. void CPCHToolBar::Config_Clear()
  736. {
  737. m_cfg.Reset();
  738. m_fLoaded = false;
  739. }
  740. HRESULT CPCHToolBar::Config_Load()
  741. {
  742. __HCP_FUNC_ENTRY( "CPCHToolBar::Config_Load" );
  743. HRESULT hr;
  744. if(!m_fLoaded)
  745. {
  746. CComPtr<IServiceProvider> sp;
  747. CComPtr<IHTMLDocument2> doc2;
  748. CComPtr<IHTMLDocument3> doc3;
  749. CComBSTR bstrBase;
  750. CComBSTR bstrDir;
  751. __MPC_EXIT_IF_METHOD_FAILS(hr, m_spAmbientDispatch->QueryInterface( IID_IServiceProvider, (void**)&sp ));
  752. __MPC_EXIT_IF_METHOD_FAILS(hr, sp->QueryService( SID_SContainerDispatch, IID_IHTMLDocument2, (void **)&doc2 ));
  753. __MPC_EXIT_IF_METHOD_FAILS(hr, doc2->get_URL( &bstrBase ));
  754. __MPC_EXIT_IF_METHOD_FAILS(hr, sp->QueryService( SID_SContainerDispatch, IID_IHTMLDocument3, (void **)&doc3 ));
  755. __MPC_EXIT_IF_METHOD_FAILS(hr, doc3->get_dir( &bstrDir ));
  756. Config_Clear();
  757. __MPC_EXIT_IF_METHOD_FAILS(hr, m_cfg.Load( bstrBase, m_bstrDefinition, bstrDir ));
  758. m_fLoaded = true;
  759. }
  760. hr = S_OK;
  761. __HCP_FUNC_CLEANUP;
  762. if(FAILED(hr))
  763. {
  764. Config_Clear();
  765. }
  766. __HCP_FUNC_EXIT(hr);
  767. }
  768. HRESULT CPCHToolBar::Toolbar_Create()
  769. {
  770. __HCP_FUNC_ENTRY( "CPCHToolBar::Toolbar_Create" );
  771. HRESULT hr;
  772. if(FAILED(Config_Load()))
  773. {
  774. ; // Empty toolbar...
  775. }
  776. __MPC_EXIT_IF_METHOD_FAILS(hr, Rebar_Create());
  777. if(m_hwndRB && !m_hwndTB)
  778. {
  779. DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
  780. TBSTYLE_TOOLTIPS | TBSTYLE_FLAT |
  781. CCS_NORESIZE | CCS_NODIVIDER | CCS_NOPARENTALIGN;
  782. DWORD dwStyleEx = TBSTYLE_EX_DRAWDDARROWS | TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_DOUBLEBUFFER;
  783. if(m_cfg.m_mode == TB_SELECTED)
  784. {
  785. dwStyle |= TBSTYLE_LIST;
  786. }
  787. m_hwndTB = ::CreateWindowEx( WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL, dwStyle, 0, 0, 0, 0, m_hwndRB, NULL, NULL, NULL );
  788. if(m_hwndTB == NULL)
  789. {
  790. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::GetLastError());
  791. }
  792. ::SendMessageW( m_hwndTB, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON) , 0 );
  793. ::SendMessageW( m_hwndTB, TB_SETEXTENDEDSTYLE, dwStyleEx , dwStyleEx );
  794. ::SendMessageW( m_hwndTB, TB_SETMAXTEXTROWS , 1 , 0 );
  795. ::SendMessageW( m_hwndTB, TB_SETDROPDOWNGAP , ::GetSystemMetrics( SM_CXEDGE ) / 2, 0 );
  796. ::SendMessageW( m_hwndTB, CCM_SETVERSION , COMCTL32_VERSION , 0 );
  797. __MPC_EXIT_IF_METHOD_FAILS(hr, m_cfg.CreateButtons( m_hwndTB ));
  798. }
  799. hr = S_OK;
  800. __HCP_FUNC_CLEANUP;
  801. __HCP_FUNC_EXIT(hr);
  802. }
  803. HRESULT CPCHToolBar::Rebar_Create()
  804. {
  805. __HCP_FUNC_ENTRY( "CPCHToolBar::Rebar_Create" );
  806. HRESULT hr;
  807. if(m_hWnd && !m_hwndRB)
  808. {
  809. DWORD dwStyle = RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE |
  810. WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
  811. CCS_NODIVIDER | CCS_NOPARENTALIGN;
  812. DWORD dwStyleEx = WS_EX_TOOLWINDOW;
  813. if(m_cfg.m_fRTL) dwStyleEx |= WS_EX_LAYOUTRTL;
  814. m_hwndRB = ::CreateWindowEx( dwStyleEx, REBARCLASSNAME, NULL, dwStyle, 0, 0, 24, 24, m_hWnd, NULL, NULL, NULL );
  815. if(m_hwndRB == NULL)
  816. {
  817. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ::GetLastError());
  818. }
  819. ::SendMessageW( m_hwndRB, RB_SETTEXTCOLOR, 0 , CLR_DEFAULT );
  820. ::SendMessageW( m_hwndRB, RB_SETBKCOLOR , 0 , CLR_DEFAULT );
  821. ::SendMessageW( m_hwndRB, CCM_SETVERSION , COMCTL32_VERSION, 0 );
  822. }
  823. hr = S_OK;
  824. __HCP_FUNC_CLEANUP;
  825. __HCP_FUNC_EXIT(hr);
  826. }
  827. HRESULT CPCHToolBar::Rebar_AddBand()
  828. {
  829. __HCP_FUNC_ENTRY( "CPCHToolBar::Rebar_AddBand" );
  830. HRESULT hr;
  831. if(m_hwndRB && m_hwndTB)
  832. {
  833. REBARBANDINFOW rbbi; ::ZeroMemory( &rbbi, sizeof(rbbi) );
  834. SIZE ptIdeal;
  835. m_cfg.UpdateSize( m_hwndTB, NULL, ptIdeal );
  836. rbbi.cbSize = sizeof(rbbi);
  837. rbbi.fMask = RBBIM_ID | RBBIM_CHILDSIZE | RBBIM_CHILD | RBBIM_SIZE | RBBIM_STYLE | RBBIM_IDEALSIZE;
  838. rbbi.fStyle = RBBS_NOGRIPPER | RBBS_USECHEVRON/* | RBBS_CHILDEDGE | RBBS_FIXEDBMP*/;
  839. rbbi.hwndChild = m_hwndTB;
  840. rbbi.cx = 0;
  841. rbbi.cxMinChild = 0;
  842. rbbi.cyMinChild = ptIdeal.cy;
  843. rbbi.cxIdeal = ptIdeal.cx;
  844. ::SendMessageW( m_hwndRB, RB_INSERTBANDW, 0, (LPARAM)&rbbi );
  845. ::SendMessageW( m_hwndRB, RB_SHOWBAND , 0, (LPARAM)TRUE );
  846. }
  847. hr = S_OK;
  848. __HCP_FUNC_EXIT(hr);
  849. }
  850. /////////////////////////////////////////////////////////////////////////////
  851. ////#define CH_PREFIX TEXT('&')
  852. ////
  853. ////static WCHAR local_GetAccelerator( LPCWSTR sz, BOOL bUseDefault )
  854. ////{
  855. //// WCHAR ch = (TCHAR)-1;
  856. //// LPCWSTR szAccel = sz;
  857. ////
  858. //// // then prefixes are allowed.... see if it has one
  859. //// do
  860. //// {
  861. //// szAccel = StrChrW( szAccel, CH_PREFIX );
  862. //// if(szAccel)
  863. //// {
  864. //// szAccel++;
  865. ////
  866. //// // handle having &&
  867. //// if(*szAccel != CH_PREFIX)
  868. //// {
  869. //// ch = *szAccel;
  870. //// }
  871. //// else
  872. //// {
  873. //// szAccel++;
  874. //// }
  875. //// }
  876. //// } while (szAccel && (ch == (WCHAR)-1));
  877. ////
  878. //// if((ch == (WCHAR)-1) && bUseDefault)
  879. //// {
  880. //// ch = *sz;
  881. //// }
  882. ////
  883. //// return ch;
  884. ////}
  885. BOOL CPCHToolBar::PreTranslateAccelerator( LPMSG pMsg, HRESULT& hRet )
  886. {
  887. // Give toolbar a chance.
  888. if(m_hwndTB)
  889. {
  890. if(::SendMessage( m_hwndTB, TB_TRANSLATEACCELERATOR, 0, (LPARAM)pMsg )) return TRUE;
  891. if(::SendMessage( m_hwndTB, WM_FORWARDMSG, 0, (LPARAM)pMsg )) return TRUE;
  892. //// if(pMsg->message == WM_SYSCHAR)
  893. //// {
  894. //// UINT idBtn;
  895. ////
  896. //// if(::SendMessage( m_hwndTB, TB_MAPACCELERATOR, pMsg->wParam, (LPARAM)&idBtn ))
  897. //// {
  898. //// WCHAR rgButtonText[MAX_PATH];
  899. ////
  900. //// // comctl says this one is the one, let's make sure we aren't getting
  901. //// // one of the unwanted "use the first letter" accelerators that it
  902. //// // will return.
  903. //// if((::SendMessage( m_hwndTB, TB_GETBUTTONTEXTW, idBtn, (LPARAM)rgButtonText ) > 0) &&
  904. //// (local_GetAccelerator( rgButtonText, FALSE ) != (WCHAR)-1))
  905. //// {
  906. //// // (tnoonan) - it feels kinda cheesy to send mouse messages, but
  907. //// // I don't know of a cleaner way which will accomplish what we
  908. //// // want (like deal with split buttons, mutually exclusive
  909. //// // buttons, etc.).
  910. //// RECT rc;
  911. ////
  912. //// ::SendMessage( m_hwndTB, TB_GETRECT, idBtn, (LPARAM)&rc );
  913. ////
  914. //// ::SendMessage( m_hwndTB, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(rc.left, rc.top) );
  915. //// ::SendMessage( m_hwndTB, WM_LBUTTONUP , 0 , MAKELONG(rc.left, rc.top) );
  916. ////
  917. //// return TRUE;
  918. //// }
  919. //// }
  920. //// }
  921. }
  922. return CComControl<CPCHToolBar>::PreTranslateAccelerator( pMsg, hRet );
  923. }
  924. ////////////////////////////////////////////////////////////////////////////////
  925. ////////////////////////////////////////////////////////////////////////////////
  926. STDMETHODIMP CPCHToolBar::get_Definition( /*[out, retval]*/ BSTR *pVal )
  927. {
  928. return MPC::GetBSTR( m_bstrDefinition, pVal );
  929. }
  930. STDMETHODIMP CPCHToolBar::put_Definition( /*[in]*/ BSTR newVal )
  931. {
  932. Config_Clear();
  933. return MPC::PutBSTR( m_bstrDefinition, newVal );
  934. }
  935. STDMETHODIMP CPCHToolBar::get_Mode( /*[out, retval]*/ TB_MODE *pVal )
  936. {
  937. if(!pVal) return E_POINTER;
  938. *pVal = m_cfg.m_mode;
  939. return S_OK;
  940. }
  941. STDMETHODIMP CPCHToolBar::put_Mode( /*[in]*/ TB_MODE newVal )
  942. {
  943. bool fRecreate = false;
  944. switch(newVal)
  945. {
  946. case TB_ALL :
  947. case TB_SELECTED:
  948. case TB_NONE : break;
  949. default: return E_INVALIDARG;
  950. }
  951. //
  952. // Adjust style.
  953. //
  954. if(m_hwndRB && (m_cfg.m_mode != newVal))
  955. {
  956. ::DestroyWindow( m_hwndRB );
  957. m_hwndRB = NULL;
  958. m_hwndTB = NULL;
  959. fRecreate = true;
  960. }
  961. m_cfg.m_mode = newVal;
  962. if(fRecreate)
  963. {
  964. if(SUCCEEDED(Rebar_Create ()) &&
  965. SUCCEEDED(Toolbar_Create()) &&
  966. SUCCEEDED(Rebar_AddBand ()) &&
  967. m_hwndRB )
  968. {
  969. RECT rc;
  970. ::GetClientRect( m_hWnd, &rc );
  971. ::SetWindowPos( m_hwndRB, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER|SWP_NOACTIVATE );
  972. UpdateSize();
  973. }
  974. }
  975. return S_OK;
  976. }
  977. STDMETHODIMP CPCHToolBar::SetState( /*[in]*/ BSTR bstrText, /*[in]*/ VARIANT_BOOL fEnabled )
  978. {
  979. if(SUCCEEDED(Config_Load()))
  980. {
  981. Button* bt = m_cfg.LookupButton( bstrText, -1 );
  982. if(bt)
  983. {
  984. bt->m_fEnabled = (fEnabled == VARIANT_TRUE);
  985. bt->UpdateState( m_hwndTB );
  986. UpdateSize();
  987. }
  988. }
  989. return S_OK;
  990. }
  991. STDMETHODIMP CPCHToolBar::SetVisibility( /*[in]*/ BSTR bstrText, /*[in]*/ VARIANT_BOOL fVisible )
  992. {
  993. if(SUCCEEDED(Config_Load()))
  994. {
  995. Button* bt = m_cfg.LookupButton( bstrText, -1 );
  996. if(bt)
  997. {
  998. bt->m_fVisible = (fVisible == VARIANT_TRUE);
  999. bt->UpdateState( m_hwndTB );
  1000. UpdateSize();
  1001. }
  1002. }
  1003. return S_OK;
  1004. }
  1005. ////////////////////////////////////////////////////////////////////////////////
  1006. //
  1007. // This is ugly, but unless we find a better way to get the HTML element for our site it's our only hope..
  1008. //
  1009. HRESULT CPCHToolBar::FindElementThroughThunking( /*[out]*/ CComPtr<IHTMLElement>& elem )
  1010. {
  1011. __HCP_FUNC_ENTRY( "CPCHToolBar::FindElementThroughThunking" );
  1012. HRESULT hr;
  1013. CComPtr<IServiceProvider> sp;
  1014. CComPtr<IHTMLDocument2> doc2;
  1015. CComPtr<IHTMLElementCollection> coll;
  1016. MPC::HTML::IHTMLElementList lst;
  1017. elem.Release();
  1018. //
  1019. // Get Document element.
  1020. //
  1021. __MPC_EXIT_IF_METHOD_FAILS(hr, m_spAmbientDispatch->QueryInterface( IID_IServiceProvider, (void**)&sp ));
  1022. __MPC_EXIT_IF_METHOD_FAILS(hr, sp->QueryService( SID_SContainerDispatch, IID_IHTMLDocument2, (void **)&doc2 ));
  1023. //
  1024. // Get list of OBJECT elements.
  1025. //
  1026. MPC_SCRIPTHELPER_GET__DIRECT__NOTNULL(coll, doc2, all);
  1027. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::HTML::EnumerateCollection( lst, coll, L"<OBJECT" ));
  1028. //
  1029. // Try to locate ourself.
  1030. //
  1031. for(MPC::HTML::IHTMLElementIter it=lst.begin(); it != lst.end(); it++)
  1032. {
  1033. CComQIPtr<IPCHToolBarPrivate> tb = *it;
  1034. if(tb && SUCCEEDED(tb->SameObject( this )))
  1035. {
  1036. elem = *it;
  1037. break;
  1038. }
  1039. }
  1040. hr = S_OK;
  1041. __HCP_FUNC_CLEANUP;
  1042. __HCP_FUNC_EXIT(hr);
  1043. }