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.

1347 lines
41 KiB

  1. #include "priv.h"
  2. #include "theater.h"
  3. #include "browbs.h"
  4. #include "resource.h"
  5. #include "legacy.h"
  6. #include "uxtheme.h" // needed for Margin.
  7. #include "mluisupp.h"
  8. #include "apithk.h"
  9. #define SUPERCLASS CBandSite
  10. TCHAR GetAccelerator(LPCTSTR psz, BOOL bUseDefault);
  11. #define ABS(x) (((x) < 0) ? -(x) : (x))
  12. #define CX_TEXTOFFSET 6
  13. #define CY_TEXTOFFSET 4
  14. #define CX_TBOFFSET 1
  15. #define CY_TBPADDING 1
  16. #define CY_ETCH 2
  17. #define CY_FLUFF 7
  18. // *** IInputObject methods ***
  19. HRESULT CBrowserBandSite::HasFocusIO()
  20. {
  21. HWND hwnd = GetFocus();
  22. if (hwnd && (hwnd == _hwndTB || hwnd == _hwndOptionsTB))
  23. return S_OK;
  24. else
  25. return SUPERCLASS::HasFocusIO();
  26. }
  27. // *** IDeskBarClient methods ***
  28. HRESULT CBrowserBandSite::SetModeDBC(DWORD dwMode)
  29. {
  30. if ((dwMode ^ _dwMode) & DBIF_VIEWMODE_VERTICAL) {
  31. // switching horizontal/vertical; need to toggle toolbar
  32. // since we hide toolbar for horizontal bars
  33. if (_hwndTBRebar) {
  34. if (dwMode & DBIF_VIEWMODE_VERTICAL) {
  35. ShowWindow(_hwndTBRebar, SW_SHOW);
  36. _fToolbar = _pCmdTarget ? TRUE : FALSE;
  37. } else {
  38. ShowWindow(_hwndTBRebar, SW_HIDE);
  39. _fToolbar = FALSE;
  40. }
  41. }
  42. }
  43. return SUPERCLASS::SetModeDBC(dwMode);
  44. }
  45. HRESULT CBrowserBandSite::TranslateAcceleratorIO(LPMSG lpMsg)
  46. {
  47. TraceMsg(TF_ACCESSIBILITY, "CBrowserBandSite::TranslateAcceleratorIO (hwnd=0x%08X) key=%d", _hwnd, lpMsg->wParam);
  48. HRESULT hr = S_FALSE;
  49. ASSERT((lpMsg->message >= WM_KEYFIRST) && (lpMsg->message <= WM_KEYLAST));
  50. #if 0 //Disabled until a better key combination can be determined
  51. // check for Control-Shift arrow keys and resize if necessary
  52. if ((GetKeyState(VK_SHIFT) < 0) && (GetKeyState(VK_CONTROL) < 0))
  53. {
  54. switch (lpMsg->wParam)
  55. {
  56. case VK_UP:
  57. case VK_DOWN:
  58. case VK_LEFT:
  59. case VK_RIGHT:
  60. IUnknown_Exec(_punkSite, &CGID_DeskBarClient, DBCID_RESIZE, (DWORD)lpMsg->wParam, NULL, NULL);
  61. return S_OK;
  62. }
  63. }
  64. #endif
  65. if (!g_fRunningOnNT && (lpMsg->message == WM_SYSCHAR))
  66. {
  67. // See AnsiWparamToUnicode for why this character tweak is needed
  68. lpMsg->wParam = AnsiWparamToUnicode(lpMsg->wParam);
  69. }
  70. // Give toolbar a crack
  71. if (hr != S_OK && _hwndTB && SendMessage(_hwndTB, TB_TRANSLATEACCELERATOR, 0, (LPARAM)lpMsg))
  72. return S_OK;
  73. else if (hr != S_OK && SendMessage(_hwndOptionsTB, TB_TRANSLATEACCELERATOR, 0, (LPARAM)lpMsg))
  74. return S_OK;
  75. // to get a mapping, forward system characters to toolbar (if any) or xBar
  76. if (WM_SYSCHAR == lpMsg->message)
  77. {
  78. if (hr == S_OK)
  79. {
  80. return S_OK;
  81. }
  82. if ((NULL != _hwndTB) && (NULL != _pCmdTarget))
  83. {
  84. UINT idBtn;
  85. if (SendMessage(_hwndTB, TB_MAPACCELERATOR, lpMsg->wParam, (LPARAM)&idBtn))
  86. {
  87. TCHAR szButtonText[MAX_PATH];
  88. // comctl says this one is the one, let's make sure we aren't getting
  89. // one of the unwanted "use the first letter" accelerators that it
  90. // will return.
  91. UINT cch = (UINT)SendMessage(_hwndTB, TB_GETBUTTONTEXT, idBtn, NULL);
  92. if (cch != 0 && cch < ARRAYSIZE(szButtonText))
  93. {
  94. if ((SendMessage(_hwndTB, TB_GETBUTTONTEXT, idBtn, (LPARAM)szButtonText) > 0) &&
  95. (GetAccelerator(szButtonText, FALSE) != (TCHAR)-1))
  96. {
  97. // (tnoonan) - it feels kinda cheesy to send mouse messages, but
  98. // I don't know of a cleaner way which will accomplish what we
  99. // want (like deal with split buttons, mutually exclusive
  100. // buttons, etc.).
  101. RECT rc;
  102. SendMessage(_hwndTB, TB_GETRECT, idBtn, (LPARAM)&rc);
  103. SendMessage(_hwndTB, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(rc.left, rc.top));
  104. SendMessage(_hwndTB, WM_LBUTTONUP, 0, MAKELONG(rc.left, rc.top));
  105. hr = S_OK;
  106. }
  107. }
  108. }
  109. }
  110. }
  111. if (hr != S_OK)
  112. hr = SUPERCLASS::TranslateAcceleratorIO(lpMsg);
  113. return hr;
  114. }
  115. HRESULT CBrowserBandSite::_TrySetFocusTB(int iDir)
  116. {
  117. HRESULT hres = S_FALSE;
  118. if (_hwndTB)
  119. {
  120. int cBtns = (int) SendMessage(_hwndTB, TB_BUTTONCOUNT, 0, 0);
  121. if (cBtns > 0)
  122. {
  123. // Set focus on tb. This will also set the first button to hottracked,
  124. // generating a hot item change notify, but _OnHotItemChange will ignore
  125. // the notify as neither HICF_RESELECT, HICF_ARROWKEYS nor HICF_ACCELERATOR will be set.
  126. SetFocus(_hwndTB);
  127. // If going back, make rightmost button hottracked,
  128. // else make first button hottracked.
  129. int iHotPos = (iDir == -1) ? cBtns - 1 : 0;
  130. // Pass HICF_RESELECT so that if we're reselecting the same item, another notify
  131. // is generated, and so that the filter in _OnHotItemChange will let the notification
  132. // through (and pop down the chevron menu if necessary).
  133. SendMessage(_hwndTB, TB_SETHOTITEM2, iHotPos, HICF_RESELECT);
  134. hres = S_OK;
  135. }
  136. }
  137. return hres;
  138. }
  139. HRESULT CBrowserBandSite::_CycleFocusBS(LPMSG lpMsg)
  140. {
  141. //
  142. // Tab order goes: (out)->_hwndOptionsTB->bands->(out)
  143. //
  144. // The order is reversed when shift is pressed.
  145. //
  146. // When control is pressed, and we have focus (i.e., have already been tabbed
  147. // into), we reject focus since ctl-tab is supposed to tab between contexts.
  148. //
  149. // Once _hwndOptionsTB gets focus, user can arrow over to _hwndTB. If
  150. // that happens, replace _hwndOptionsTB with _hwndTB in order above.
  151. //
  152. BOOL fHasFocus = (HasFocusIO() == S_OK);
  153. ASSERT(fHasFocus || !_ptbActive);
  154. if (fHasFocus && IsVK_CtlTABCycler(lpMsg))
  155. {
  156. // Bail on ctl-tab if one of our guys already has focus
  157. return S_FALSE;
  158. }
  159. HWND hwnd = GetFocus();
  160. BOOL fHasTBFocus = (hwnd && (hwnd == _hwndTB || hwnd == _hwndOptionsTB));
  161. BOOL fShift = (GetKeyState(VK_SHIFT) < 0);
  162. HRESULT hres = S_FALSE;
  163. // hidden options toolbar, bandsite cannot set focus to it (e.g. iBar)
  164. BOOL fStdExplorerBar = IsWindowVisible(_hwndOptionsTB);
  165. if (fHasTBFocus)
  166. {
  167. if (!fShift)
  168. hres = SUPERCLASS::_CycleFocusBS(lpMsg);
  169. }
  170. else
  171. {
  172. // Here, since !fHasTBFocus, fHasFocus => a band has focus
  173. if (fHasFocus || fShift || (!fHasFocus && !fStdExplorerBar))
  174. hres = SUPERCLASS::_CycleFocusBS(lpMsg);
  175. if (hres != S_OK && (!fHasFocus || (fHasFocus && fShift)))
  176. {
  177. // try passing focus to options toolbar if visible;
  178. if (fStdExplorerBar)
  179. {
  180. SetFocus(_hwndOptionsTB);
  181. TraceMsg(TF_ACCESSIBILITY, "CBrowserBandSite::_CycleFocusBS (hwnd=0x%08X) setting focus to optionsTB (=0x%08X)", _hwnd, _hwndOptionsTB);
  182. hres = S_OK;
  183. }
  184. }
  185. }
  186. return hres;
  187. }
  188. // this class subclasses the CBandSite class and adds functionality specific to
  189. // being hosted in the browser....
  190. //
  191. // it implements close as hide
  192. // it has its own title drawing
  193. void CBrowserBandSite::_OnCloseBand(DWORD dwBandID)
  194. {
  195. int iIndex = _BandIDToIndex(dwBandID);
  196. CBandItemData *pbid = _GetBandItem(iIndex);
  197. if (pbid)
  198. {
  199. _ShowBand(pbid, FALSE);
  200. if (_pct)
  201. {
  202. BOOL fShowing = FALSE;
  203. for (int i = _GetBandItemCount() - 1; i >= 0; i--)
  204. {
  205. CBandItemData *pbidLoop = _GetBandItem(i);
  206. if (pbidLoop)
  207. {
  208. fShowing |= pbid->fShow;
  209. pbidLoop->Release();
  210. }
  211. }
  212. if (!fShowing)
  213. {
  214. _pct->Exec(&CGID_DeskBarClient, DBCID_EMPTY, 0, NULL, NULL);
  215. }
  216. }
  217. pbid->Release();
  218. }
  219. }
  220. // don't allow d/d of any band in here
  221. LRESULT CBrowserBandSite::_OnBeginDrag(NMREBAR* pnm)
  222. {
  223. return 1;
  224. }
  225. CBrowserBandSite::CBrowserBandSite() : CBandSite(NULL)
  226. {
  227. _dwBandIDCur = -1;
  228. }
  229. CBrowserBandSite::~CBrowserBandSite()
  230. {
  231. ATOMICRELEASE(_pCmdTarget);
  232. }
  233. HFONT CBrowserBandSite::_GetTitleFont(BOOL fForceRefresh)
  234. {
  235. if (_hfont && fForceRefresh)
  236. DeleteObject(_hfont);
  237. if (!_hfont || fForceRefresh) {
  238. // create our font to use for title & toolbar text
  239. // use A version for win9x compat
  240. NONCLIENTMETRICSA ncm;
  241. ncm.cbSize = sizeof(ncm);
  242. SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
  243. if (!(_dwMode & DBIF_VIEWMODE_VERTICAL)) {
  244. // horizontal band w/ vertical caption, so rotate the font
  245. ncm.lfMenuFont.lfEscapement = 900; // rotate by 90 degrees
  246. ncm.lfMenuFont.lfOutPrecision = OUT_TT_ONLY_PRECIS; // TT can be rotated
  247. }
  248. _hfont = CreateFontIndirectA(&ncm.lfMenuFont);
  249. }
  250. return _hfont;
  251. }
  252. void CBrowserBandSite::_InitLayout()
  253. {
  254. // force update font
  255. _GetTitleFont(TRUE);
  256. // update toolbar font
  257. _UpdateToolbarFont();
  258. // recalc title and toolbar heights
  259. _CalcHeights();
  260. _UpdateLayout();
  261. }
  262. void CBrowserBandSite::_UpdateAllBands(BOOL fBSOnly, BOOL fNoAutoSize)
  263. {
  264. if (!fBSOnly && !fNoAutoSize)
  265. _InitLayout();
  266. SUPERCLASS::_UpdateAllBands(fBSOnly, fNoAutoSize);
  267. }
  268. HRESULT CBrowserBandSite::_Initialize(HWND hwndParent)
  269. {
  270. HRESULT hres = SUPERCLASS::_Initialize(hwndParent);
  271. SendMessage(_hwnd, CCM_SETUNICODEFORMAT, DLL_IS_UNICODE, 0);
  272. _CreateOptionsTB();
  273. _InitLayout();
  274. return hres;
  275. }
  276. void CBrowserBandSite::_CalcHeights()
  277. {
  278. // calc title height
  279. // calc height of captionless bandsites, too, needed to calc toolband height
  280. // HACKHACK: use height of 'All Folders' as standard title height
  281. TCHAR szTitle[64];
  282. if (MLLoadStringW(IDS_TREETITLE, szTitle, ARRAYSIZE(szTitle))) {
  283. HDC hdc = GetDC(_hwnd);
  284. if (hdc)
  285. {
  286. HFONT hfont = _GetTitleFont(FALSE);
  287. HFONT hfontOld = (HFONT)SelectObject(hdc, hfont);
  288. int iLen = lstrlen(szTitle);
  289. SIZE size;
  290. GetTextExtentPoint32(hdc, szTitle, iLen, &size);
  291. _uTitle = size.cy;
  292. // make space for etch line + space
  293. _uTitle += CY_ETCH + CY_FLUFF;
  294. SelectObject(hdc, hfontOld);
  295. ReleaseDC(_hwnd, hdc);
  296. }
  297. } else {
  298. // no string; use a default height
  299. _uTitle = BROWSERBAR_TITLEHEIGHT;
  300. }
  301. // calc toolbar height
  302. _uToolbar = _uTitle + (2 * CY_TBPADDING) + CY_ETCH;
  303. if (_dwStyle & BSIS_NOCAPTION)
  304. {
  305. // rebar has no caption
  306. _uTitle = 0;
  307. }
  308. }
  309. void CBrowserBandSite::_UpdateToolbarFont()
  310. {
  311. if (_hwndTB && (_dwMode & DBIF_VIEWMODE_VERTICAL)) {
  312. // use same font for title and toolbar
  313. HFONT hfont = _GetTitleFont(FALSE);
  314. if (hfont)
  315. SendMessage(_hwndTB, WM_SETFONT, (WPARAM)hfont, TRUE);
  316. }
  317. }
  318. void CBrowserBandSite::_ShowBand(CBandItemData *pbid, BOOL fShow)
  319. {
  320. if (fShow && (_dwBandIDCur != pbid->dwBandID)) {
  321. _dwBandIDCur = pbid->dwBandID;
  322. _UpdateLayout();
  323. } else if (!fShow && _dwBandIDCur == pbid->dwBandID) {
  324. _dwBandIDCur = -1;
  325. }
  326. SUPERCLASS::_ShowBand(pbid, fShow);
  327. }
  328. void CBrowserBandSite::_UpdateLayout()
  329. {
  330. // update toolbar button size
  331. if (_hwndTB && SendMessage(_hwndTB, TB_BUTTONCOUNT, 0, 0) > 0)
  332. {
  333. // try to set button height to title height
  334. LONG lSize = MAKELONG(0, _uTitle);
  335. SendMessage(_hwndTB, TB_SETBUTTONSIZE, 0, lSize);
  336. // see what toolbar actually gave us
  337. RECT rc;
  338. SendMessage(_hwndTB, TB_GETITEMRECT, 0, (LPARAM)&rc);
  339. // calc toolbar height (final version)
  340. _uToolbar = RECTHEIGHT(rc) + CY_ETCH + 2 * CY_TBPADDING;
  341. }
  342. // update header height for the current band
  343. if (_dwBandIDCur != -1)
  344. {
  345. REBARBANDINFO rbbi;
  346. rbbi.cbSize = sizeof(rbbi);
  347. rbbi.fMask = RBBIM_HEADERSIZE;
  348. rbbi.cxHeader = _uTitle + (_fToolbar ? _uToolbar : 0);
  349. SendMessage(_hwnd, RB_SETBANDINFO, _BandIDToIndex(_dwBandIDCur), (LPARAM)&rbbi);
  350. }
  351. // update toolbar size
  352. _UpdateToolbarBand();
  353. // reposition toolbars
  354. _PositionToolbars(NULL);
  355. }
  356. void CBrowserBandSite::_BandInfoFromBandItem(REBARBANDINFO *prbbi, CBandItemData *pbid, BOOL fBSOnly)
  357. {
  358. SUPERCLASS::_BandInfoFromBandItem(prbbi, pbid, fBSOnly);
  359. if (prbbi)
  360. {
  361. // we override header width so we can fit browbs's fancy ui (title,
  362. // toolbar, close & autohide buttons) in the band's header area.
  363. prbbi->cxHeader = _uTitle + (_fToolbar ? _uToolbar : 0);
  364. }
  365. }
  366. void CBrowserBandSite::_DrawEtchline(HDC hdc, LPRECT prc, int iOffset, BOOL fVertEtch)
  367. {
  368. RECT rc;
  369. CopyRect(&rc, prc);
  370. if (fVertEtch) {
  371. rc.left += iOffset - CY_ETCH;
  372. rc.right = rc.left + 1;
  373. } else {
  374. rc.top += iOffset - CY_ETCH;
  375. rc.bottom = rc.top + 1;
  376. }
  377. SHFillRectClr(hdc, &rc, GetSysColor(COLOR_BTNSHADOW));
  378. if (fVertEtch) {
  379. rc.left++;
  380. rc.right++;
  381. } else {
  382. rc.bottom++;
  383. rc.top++;
  384. }
  385. SHFillRectClr(hdc, &rc, GetSysColor(COLOR_BTNHILIGHT));
  386. }
  387. LRESULT CBrowserBandSite::_OnCDNotify(LPNMCUSTOMDRAW pnm)
  388. {
  389. switch (pnm->dwDrawStage) {
  390. case CDDS_PREPAINT:
  391. return CDRF_NOTIFYITEMDRAW;
  392. case CDDS_PREERASE:
  393. return CDRF_NOTIFYITEMDRAW;
  394. case CDDS_ITEMPREPAINT:
  395. if (!(_dwStyle & BSIS_NOCAPTION))
  396. {
  397. // horz bar has vert caption and vice versa
  398. BOOL fVertCaption = (_dwMode&DBIF_VIEWMODE_VERTICAL) ? FALSE:TRUE;
  399. CBandItemData *pbid = (CBandItemData *)pnm->lItemlParam;
  400. if (pbid)
  401. {
  402. int iLen;
  403. HFONT hfont, hfontOld = NULL;
  404. LPCTSTR pszTitle;
  405. SIZE size;
  406. USES_CONVERSION;
  407. hfont = _GetTitleFont(FALSE);
  408. hfontOld = (HFONT)SelectObject(pnm->hdc, hfont);
  409. pszTitle = pbid->szTitle;
  410. iLen = lstrlen(pszTitle);
  411. GetTextExtentPoint32(pnm->hdc, pszTitle, iLen, &size);
  412. // center text inside caption and draw edge at bottom/right.
  413. if (!fVertCaption)
  414. {
  415. // vertical bar, has horizontal text
  416. int x = pnm->rc.left + CX_TEXTOFFSET;
  417. int y = pnm->rc.top + ((_uTitle - CY_ETCH) - size.cy) / 2;
  418. ExtTextOut(pnm->hdc, x, y, NULL, NULL, pszTitle, iLen, NULL);
  419. _DrawEtchline(pnm->hdc, &pnm->rc, RECTHEIGHT(pnm->rc), fVertCaption);
  420. if (_fToolbar)
  421. _DrawEtchline(pnm->hdc, &pnm->rc, _uTitle, fVertCaption);
  422. }
  423. else
  424. {
  425. // horizontal bar, has vertical text
  426. UINT nPrevAlign = SetTextAlign(pnm->hdc, TA_BOTTOM);
  427. int x = pnm->rc.right - ((_uTitle - CY_ETCH) - size.cy) / 2;
  428. int y = pnm->rc.bottom - CY_TEXTOFFSET;
  429. ExtTextOut(pnm->hdc, x, y, NULL, NULL, pszTitle, iLen, NULL);
  430. SetTextAlign(pnm->hdc, nPrevAlign);
  431. _DrawEtchline(pnm->hdc, &pnm->rc, RECTWIDTH(pnm->rc), fVertCaption);
  432. ASSERT(!_fToolbar);
  433. }
  434. if (hfontOld)
  435. SelectObject(pnm->hdc, hfontOld);
  436. }
  437. }
  438. return CDRF_SKIPDEFAULT;
  439. }
  440. return CDRF_DODEFAULT;
  441. }
  442. LRESULT CBrowserBandSite::_OnNotify(LPNMHDR pnm)
  443. {
  444. switch (pnm->idFrom)
  445. {
  446. case FCIDM_REBAR:
  447. switch (pnm->code)
  448. {
  449. case NM_CUSTOMDRAW:
  450. return _OnCDNotify((LPNMCUSTOMDRAW)pnm);
  451. case NM_NCHITTEST:
  452. {
  453. NMMOUSE *pnmMouse = (NMMOUSE*)pnm;
  454. RECT rc;
  455. GetClientRect(_hwnd, &rc);
  456. if (pnmMouse->dwItemSpec == (DWORD)-1) {
  457. Lchktrans:
  458. //
  459. // Edges are mirrored if the window is mirrored. [samera]
  460. //
  461. if (IS_WINDOW_RTL_MIRRORED(_hwnd)) {
  462. int iTmp = rc.right;
  463. rc.right = rc.left;
  464. rc.left = iTmp;
  465. }
  466. // gotta check all 4 edges or non-left-side bars (e.g.
  467. // commbar) won't work.
  468. // (we separate this into 2 checks to give a trace,
  469. // since the old code only checked the right side)
  470. if (pnmMouse->pt.x > rc.right) {
  471. return HTTRANSPARENT;
  472. }
  473. if (pnmMouse->pt.x < rc.left ||
  474. pnmMouse->pt.y > rc.bottom || pnmMouse->pt.y < rc.top) {
  475. return HTTRANSPARENT;
  476. }
  477. } else if (pnmMouse->dwHitInfo == RBHT_CLIENT) {
  478. InflateRect(&rc, -(GetSystemMetrics(SM_CXFRAME)),
  479. -(GetSystemMetrics(SM_CYFRAME)));
  480. goto Lchktrans;
  481. }
  482. return SUPERCLASS::_OnNotify(pnm);
  483. }
  484. default:
  485. return SUPERCLASS::_OnNotify(pnm);
  486. }
  487. default:
  488. return SUPERCLASS::_OnNotify(pnm);
  489. }
  490. return 0;
  491. }
  492. IDropTarget* CBrowserBandSite::_WrapDropTargetForBand(IDropTarget* pdtBand)
  493. {
  494. pdtBand->AddRef();
  495. return pdtBand;
  496. }
  497. HRESULT CBrowserBandSite::v_InternalQueryInterface(REFIID riid, void **ppv)
  498. {
  499. static const QITAB qit[] = {
  500. QITABENT(CBrowserBandSite, IExplorerToolbar),
  501. { 0 },
  502. };
  503. HRESULT hr;
  504. if (IsEqualIID(riid, IID_IDropTarget))
  505. {
  506. *ppv = NULL;
  507. hr = E_NOINTERFACE;
  508. }
  509. else
  510. {
  511. hr = QISearch(this, qit, riid, ppv);
  512. if (FAILED(hr))
  513. hr = SUPERCLASS::v_InternalQueryInterface(riid, ppv);
  514. }
  515. return hr;
  516. }
  517. DWORD CBrowserBandSite::_GetWindowStyle(DWORD *pdwExStyle)
  518. {
  519. *pdwExStyle = 0;
  520. return RBS_REGISTERDROP |
  521. RBS_VERTICALGRIPPER |
  522. RBS_VARHEIGHT | RBS_DBLCLKTOGGLE |
  523. WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_BORDER |
  524. WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN;
  525. }
  526. // *** IOleCommandTarget ***
  527. HRESULT CBrowserBandSite::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,
  528. VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  529. {
  530. if (pguidCmdGroup == NULL)
  531. {
  532. }
  533. #ifdef UNIX
  534. // IEUNIX: Special case to handle the case where the band wants to
  535. // close itself. Used in Cache Warning pane (msgband.cpp)
  536. else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  537. {
  538. switch (nCmdID)
  539. {
  540. case SBCMDID_MSGBAND:
  541. {
  542. IDockingWindow * pdw;
  543. if (SUCCEEDED(_punkSite->QueryInterface(IID_PPV_ARG(IDockingWindow, &pdw))))
  544. {
  545. pdw->ShowDW((BOOL)nCmdexecopt);
  546. pdw->Release();
  547. }
  548. }
  549. }
  550. }
  551. #endif
  552. else if (IsEqualGUID(CGID_Theater, *pguidCmdGroup))
  553. {
  554. switch (nCmdID)
  555. {
  556. case THID_ACTIVATE:
  557. _fTheater = TRUE;
  558. SHSetWindowBits(_hwnd, GWL_EXSTYLE, WS_EX_CLIENTEDGE, 0);
  559. // fall through
  560. case THID_SETBROWSERBARAUTOHIDE:
  561. if (pvarargIn && pvarargIn->vt == VT_I4)
  562. _fNoAutoHide = !(pvarargIn->lVal);
  563. SendMessage(_hwndOptionsTB, TB_CHANGEBITMAP, IDM_AB_AUTOHIDE, _fNoAutoHide ? 2 : 0);
  564. break;
  565. case THID_DEACTIVATE:
  566. _fTheater = FALSE;
  567. SHSetWindowBits(_hwnd, GWL_EXSTYLE, WS_EX_CLIENTEDGE, WS_EX_CLIENTEDGE);
  568. break;
  569. }
  570. SetWindowPos(_hwnd, NULL, 0,0,0,0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
  571. _SizeOptionsTB();
  572. return S_OK;
  573. }
  574. return SUPERCLASS::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  575. }
  576. #define BBSC_REBAR 0x00000001
  577. #define BBSC_TOOLBAR 0x00000002
  578. void CBrowserBandSite::_CreateTBRebar()
  579. {
  580. ASSERT(!_hwndTBRebar);
  581. _hwndTBRebar = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL,
  582. WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN |
  583. WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN,
  584. 0, 0, 100, 36,
  585. _hwnd, (HMENU) BBSC_REBAR, HINST_THISDLL, NULL);
  586. if (_hwndTBRebar)
  587. SendMessage(_hwndTBRebar, CCM_SETVERSION, COMCTL32_VERSION, 0);
  588. }
  589. void CBrowserBandSite::_InsertToolbarBand()
  590. {
  591. if (_hwndTBRebar && _hwndTB)
  592. {
  593. // Assert that we haven't added the toolbar band yet
  594. ASSERT(SendMessage(_hwndTBRebar, RB_GETBANDCOUNT, 0, 0) == 0);
  595. // Assert that we've calculated toolbar height
  596. ASSERT(_uToolbar);
  597. REBARBANDINFO rbbi;
  598. rbbi.cbSize = sizeof(REBARBANDINFO);
  599. rbbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE;
  600. // RBBIM_CHILD
  601. rbbi.hwndChild = _hwndTB;
  602. // RBBIM_CHILDSIZE
  603. rbbi.cxMinChild = 0;
  604. rbbi.cyMinChild = _uToolbar - (CY_ETCH + 2 * CY_TBPADDING);
  605. // RBBIM_STYLE
  606. rbbi.fStyle = RBBS_NOGRIPPER | RBBS_USECHEVRON;
  607. SendMessage(_hwndTBRebar, RB_INSERTBAND, -1, (LPARAM)&rbbi);
  608. }
  609. }
  610. void CBrowserBandSite::_UpdateToolbarBand()
  611. {
  612. if (_hwndTBRebar && _hwndTB)
  613. {
  614. // Assert that we've added the toolbar band
  615. ASSERT(SendMessage(_hwndTBRebar, RB_GETBANDCOUNT, 0, 0) == 1);
  616. // Assert that we've calculated toolbar height
  617. ASSERT(_uToolbar);
  618. REBARBANDINFO rbbi;
  619. rbbi.cbSize = sizeof(REBARBANDINFO);
  620. rbbi.fMask = RBBIM_CHILDSIZE;
  621. SIZE size = {0, _uToolbar};
  622. if (SendMessage(_hwndTB, TB_GETIDEALSIZE, FALSE, (LPARAM)&size))
  623. {
  624. // RBBIM_IDEALSIZE
  625. rbbi.fMask |= RBBIM_IDEALSIZE;
  626. rbbi.cxIdeal = size.cx;
  627. }
  628. // RBBIM_CHILDSIZE
  629. rbbi.cxMinChild = 0;
  630. rbbi.cyMinChild = _uToolbar - (CY_ETCH + 2 * CY_TBPADDING);
  631. SendMessage(_hwndTBRebar, RB_SETBANDINFO, 0, (LPARAM)&rbbi);
  632. }
  633. }
  634. void CBrowserBandSite::_CreateTB()
  635. {
  636. ASSERT(!_hwndTB);
  637. // Create a rebar too so we get the chevron
  638. _CreateTBRebar();
  639. if (_hwndTBRebar)
  640. {
  641. _hwndTB = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
  642. WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS |
  643. TBSTYLE_FLAT | TBSTYLE_LIST | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE,
  644. 0, 0, 0, 0,
  645. _hwndTBRebar, (HMENU) BBSC_TOOLBAR, HINST_THISDLL, NULL);
  646. }
  647. if (_hwndTB)
  648. {
  649. SendMessage(_hwndTB, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
  650. SendMessage(_hwndTB, CCM_SETVERSION, COMCTL32_VERSION, 0);
  651. // FEATURE: use TBSTYLE_EX_HIDECLIPPEDBUTTONS here? looks kinda goofy so i'm leaving it out for now.
  652. SendMessage(_hwndTB, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS | TBSTYLE_EX_MIXEDBUTTONS);
  653. SendMessage(_hwndTB, TB_SETMAXTEXTROWS, 1, 0L);
  654. _UpdateToolbarFont();
  655. _InsertToolbarBand();
  656. }
  657. }
  658. void CBrowserBandSite::_RemoveAllButtons()
  659. {
  660. if (!_hwndTB || !_hwndTBRebar)
  661. return;
  662. ShowWindow(_hwndTBRebar, SW_HIDE);
  663. _fToolbar = FALSE;
  664. INT_PTR nCount = SendMessage(_hwndTB, TB_BUTTONCOUNT, 0, 0L);
  665. while (nCount-- > 0)
  666. SendMessage(_hwndTB, TB_DELETEBUTTON, nCount, 0L);
  667. _UpdateLayout();
  668. }
  669. void CBrowserBandSite::_Close()
  670. {
  671. ATOMICRELEASE(_pCmdTarget);
  672. //
  673. // Destroying _hwndTBRebar will take care of _hwndTB too
  674. //
  675. ASSERT(!_hwndTB || IsChild(_hwndTBRebar, _hwndTB));
  676. DESTROY_OBJ_WITH_HANDLE(_hwndTBRebar, DestroyWindow);
  677. DESTROY_OBJ_WITH_HANDLE(_hwndOptionsTB, DestroyWindow);
  678. DESTROY_OBJ_WITH_HANDLE(_hfont, DeleteObject);
  679. SUPERCLASS::_Close();
  680. }
  681. LRESULT CBrowserBandSite::_OnHotItemChange(LPNMTBHOTITEM pnmtb)
  682. {
  683. LRESULT lres = 0;
  684. // We might want to drop down the chevron menu if the hot item change
  685. // flags has these characteristics:
  686. //
  687. // - not HICF_LEAVING, since if HICF_LEAVING, the hot item should instead wrap to _hwndClose
  688. // - and not HICF_MOUSE, since we only drop down on keyboard hot item change
  689. // - HICF_ACCELERATOR | HICF_ARROWKEYS, since we only drop down on keyboard hot item change
  690. // - or HICF_RESELECT, since we force a reselect in _TrySetFocusTB
  691. //
  692. if (!(pnmtb->dwFlags & (HICF_LEAVING | HICF_MOUSE)) &&
  693. (pnmtb->dwFlags & (HICF_RESELECT | HICF_ACCELERATOR | HICF_ARROWKEYS)))
  694. {
  695. // Check to see if new hot button is clipped. If it is,
  696. // then we pop down the chevron menu.
  697. RECT rc;
  698. GetClientRect(_hwndTB, &rc);
  699. int iButton = (int)SendMessage(_hwndTB, TB_COMMANDTOINDEX, pnmtb->idNew, 0);
  700. if (SHIsButtonObscured(_hwndTB, &rc, iButton))
  701. {
  702. // Clear hot item
  703. SendMessage(_hwndTB, TB_SETHOTITEM, -1, 0);
  704. // Figure out whether to highlight first or last item in menu
  705. UINT uSelect;
  706. int cButtons = (int)SendMessage(_hwndTB, TB_BUTTONCOUNT, 0, 0);
  707. if (iButton == cButtons - 1)
  708. uSelect = DBPC_SELECTLAST;
  709. else
  710. uSelect = DBPC_SELECTFIRST;
  711. // Pop it down
  712. SendMessage(_hwndTBRebar, RB_PUSHCHEVRON, 0, uSelect);
  713. lres = 1;
  714. }
  715. }
  716. return lres;
  717. }
  718. LRESULT CBrowserBandSite::_OnNotifyBBS(LPNMHDR pnm)
  719. {
  720. switch (pnm->code)
  721. {
  722. case TBN_DROPDOWN:
  723. if (EVAL(_pCmdTarget))
  724. {
  725. LPNMTOOLBAR pnmtoolbar = (LPNMTOOLBAR)pnm;
  726. VARIANTARG var;
  727. RECT rc = pnmtoolbar->rcButton;
  728. var.vt = VT_I4;
  729. MapWindowPoints(_hwndTB, HWND_DESKTOP, (LPPOINT)&rc, 2);
  730. var.lVal = MAKELONG(rc.left, rc.bottom);
  731. _pCmdTarget->Exec(&_guidButtonGroup, pnmtoolbar->iItem, OLECMDEXECOPT_PROMPTUSER, &var, NULL);
  732. }
  733. break;
  734. case TBN_WRAPHOTITEM:
  735. {
  736. LPNMTBWRAPHOTITEM pnmwh = (LPNMTBWRAPHOTITEM) pnm;
  737. if (pnmwh->nReason & HICF_ARROWKEYS) {
  738. if (pnm->hwndFrom == _hwndOptionsTB) {
  739. if (_TrySetFocusTB(pnmwh->iDir) != S_OK)
  740. return 0;
  741. } else {
  742. ASSERT(pnm->hwndFrom == _hwndTB);
  743. SetFocus(_hwndOptionsTB);
  744. }
  745. return 1;
  746. }
  747. }
  748. break;
  749. case TBN_HOTITEMCHANGE:
  750. if (pnm->hwndFrom == _hwndTB)
  751. return _OnHotItemChange((LPNMTBHOTITEM)pnm);
  752. break;
  753. case TBN_GETINFOTIP:
  754. // [scotthan] We'll ask the toolbar owner for tip text via
  755. // IOleCommandTarget::QueryStatus, like we do w/ defview for itbar buttons
  756. if (_pCmdTarget && pnm->hwndFrom == _hwndTB)
  757. {
  758. NMTBGETINFOTIP* pgit = (NMTBGETINFOTIP*)pnm ;
  759. OLECMDTEXTV<MAX_TOOLTIP_STRING> cmdtv;
  760. OLECMDTEXT *pcmdText = &cmdtv;
  761. pcmdText->cwBuf = MAX_TOOLTIP_STRING;
  762. pcmdText->cmdtextf = OLECMDTEXTF_NAME;
  763. pcmdText->cwActual = 0;
  764. OLECMD rgcmd = {pgit->iItem, 0};
  765. HRESULT hr = _pCmdTarget->QueryStatus(&_guidButtonGroup, 1, &rgcmd, pcmdText);
  766. if (SUCCEEDED(hr) && (pcmdText->cwActual))
  767. {
  768. SHUnicodeToTChar(pcmdText->rgwz, pgit->pszText, pgit->cchTextMax);
  769. return 1;
  770. }
  771. }
  772. break ;
  773. case RBN_CHEVRONPUSHED:
  774. LPNMREBARCHEVRON pnmch = (LPNMREBARCHEVRON) pnm;
  775. MapWindowPoints(pnmch->hdr.hwndFrom, HWND_DESKTOP, (LPPOINT)&pnmch->rc, 2);
  776. ToolbarMenu_Popup(_hwnd, &pnmch->rc, NULL, _hwndTB, 0, (DWORD)pnmch->lParamNM);
  777. return 1;
  778. }
  779. return 0;
  780. }
  781. // *** IWinEventHandler ***
  782. HRESULT CBrowserBandSite::OnWinEvent(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres)
  783. {
  784. switch (uMsg)
  785. {
  786. case WM_COMMAND:
  787. {
  788. HWND hwndControl = GET_WM_COMMAND_HWND(wParam, lParam);
  789. UINT idCmd = GET_WM_COMMAND_ID(wParam, lParam);
  790. if (hwndControl && hwndControl == _hwndTB)
  791. {
  792. if (EVAL(_pCmdTarget))
  793. {
  794. RECT rc;
  795. VARIANTARG var;
  796. var.vt = VT_I4;
  797. SendMessage(_hwndTB, TB_GETRECT, idCmd, (LPARAM)&rc);
  798. MapWindowPoints(_hwndTB, HWND_DESKTOP, (LPPOINT)&rc, 2);
  799. var.lVal = MAKELONG(rc.left, rc.bottom);
  800. _pCmdTarget->Exec(&_guidButtonGroup, idCmd, 0, &var, NULL);
  801. }
  802. return S_OK;
  803. }
  804. else if (hwndControl == _hwndOptionsTB) {
  805. switch (idCmd) {
  806. case IDM_AB_CLOSE:
  807. IUnknown_Exec(_punkSite, &CGID_DeskBarClient, DBCID_EMPTY, 0, NULL, NULL);
  808. break;
  809. case IDM_AB_AUTOHIDE:
  810. {
  811. VARIANTARG v = {0};
  812. v.vt = VT_I4;
  813. v.lVal = _fNoAutoHide;
  814. IUnknown_Exec(_punkSite, &CGID_Theater, THID_SETBROWSERBARAUTOHIDE, 0, &v, NULL);
  815. break;
  816. }
  817. }
  818. return S_OK;
  819. }
  820. }
  821. break;
  822. case WM_NOTIFY:
  823. {
  824. LPNMHDR pnm = (LPNMHDR)lParam;
  825. if (pnm && (pnm->hwndFrom == _hwndTB || pnm->hwndFrom == _hwndOptionsTB || pnm->hwndFrom == _hwndTBRebar)) {
  826. *plres = _OnNotifyBBS(pnm);
  827. return S_OK;
  828. }
  829. }
  830. break;
  831. case WM_SIZE:
  832. {
  833. POINT pt = {LOWORD(lParam), HIWORD(lParam)};
  834. _PositionToolbars(&pt);
  835. }
  836. break;
  837. }
  838. return SUPERCLASS::OnWinEvent(hwnd, uMsg, wParam, lParam, plres);
  839. }
  840. HRESULT CBrowserBandSite::IsWindowOwner(HWND hwnd)
  841. {
  842. if (hwnd && (hwnd == _hwndTB) || (hwnd == _hwndOptionsTB) || (hwnd == _hwndTBRebar))
  843. return S_OK;
  844. return SUPERCLASS::IsWindowOwner(hwnd);
  845. }
  846. // *** IBandSite ***
  847. HRESULT CBrowserBandSite::SetBandSiteInfo(const BANDSITEINFO * pbsinfo)
  848. {
  849. // recompute our layout if vertical viewmode is changing
  850. BOOL fUpdate = ((pbsinfo->dwMask & BSIM_STATE) &&
  851. ((pbsinfo->dwState ^ _dwMode) & DBIF_VIEWMODE_VERTICAL));
  852. // ...or if caption is turned on or off
  853. BOOL fCaptionStyleChanged = ( (pbsinfo->dwMask & BSIM_STYLE)
  854. && ((pbsinfo->dwStyle ^ _dwStyle) & BSIS_NOCAPTION));
  855. HRESULT hres = SUPERCLASS::SetBandSiteInfo(pbsinfo);
  856. if (fCaptionStyleChanged && _hwndOptionsTB)
  857. {
  858. if (_fToolbar) {
  859. // don't know if "new" band requires buttons or not, expect band to add buttons again if needed
  860. _RemoveAllButtons();
  861. }
  862. // show or hide close/hide toolbar; is always created since bandsites get reused!
  863. ::ShowWindow(_hwndOptionsTB, (_dwStyle & BSIS_NOCAPTION) ? SW_HIDE : SW_SHOW);
  864. }
  865. if (fUpdate || fCaptionStyleChanged) {
  866. _InitLayout();
  867. }
  868. return hres;
  869. }
  870. // *** IExplorerToolbar ***
  871. HRESULT CBrowserBandSite::SetCommandTarget(IUnknown* punkCmdTarget, const GUID* pguidButtonGroup, DWORD dwFlags)
  872. {
  873. HRESULT hres = S_OK;
  874. BOOL fRemoveButtons = TRUE;
  875. // dwFlags is not used
  876. ASSERT(!(dwFlags));
  877. ATOMICRELEASE(_pCmdTarget);
  878. if (punkCmdTarget && pguidButtonGroup)
  879. {
  880. hres = punkCmdTarget->QueryInterface(IID_IOleCommandTarget, (void**)&(_pCmdTarget));
  881. if (!_hwndTB)
  882. {
  883. _CreateTB();
  884. }
  885. else if (_fToolbar && IsEqualGUID(_guidButtonGroup, *pguidButtonGroup))
  886. {
  887. fRemoveButtons = FALSE;
  888. hres = S_FALSE;
  889. }
  890. _guidButtonGroup = *pguidButtonGroup;
  891. }
  892. else
  893. ASSERT(!punkCmdTarget);
  894. if (fRemoveButtons)
  895. _RemoveAllButtons();
  896. ASSERT(SUCCEEDED(hres));
  897. return hres;
  898. }
  899. // client should have already called AddString
  900. HRESULT CBrowserBandSite::AddButtons(const GUID* pguidButtonGroup, UINT nButtons, const TBBUTTON* lpButtons)
  901. {
  902. if (!_hwndTB || !nButtons)
  903. return E_FAIL;
  904. _RemoveAllButtons();
  905. if (SendMessage(_hwndTB, TB_ADDBUTTONS, nButtons, (LPARAM)lpButtons))
  906. {
  907. ShowWindow(_hwndTBRebar, SW_SHOW);
  908. _fToolbar = TRUE;
  909. _UpdateLayout();
  910. return S_OK;
  911. }
  912. return E_FAIL;
  913. }
  914. HRESULT CBrowserBandSite::AddString(const GUID* pguidButtonGroup, HINSTANCE hInst, UINT_PTR uiResID, LRESULT* pOffset)
  915. {
  916. *pOffset = -1;
  917. if (!_hwndTB)
  918. return E_FAIL;
  919. *pOffset = SendMessage(_hwndTB, TB_ADDSTRING, (WPARAM)hInst, (LPARAM)uiResID);
  920. if (*pOffset != -1)
  921. return S_OK;
  922. return E_FAIL;
  923. }
  924. HRESULT CBrowserBandSite::GetButton(const GUID* pguidButtonGroup, UINT uiCommand, LPTBBUTTON lpButton)
  925. {
  926. if (!_hwndTB)
  927. return E_FAIL;
  928. UINT_PTR uiIndex = SendMessage(_hwndTB, TB_COMMANDTOINDEX, uiCommand, 0L);
  929. if (SendMessage(_hwndTB, TB_GETBUTTON, uiIndex, (LPARAM)lpButton))
  930. return S_OK;
  931. return E_FAIL;
  932. }
  933. HRESULT CBrowserBandSite::GetState(const GUID* pguidButtonGroup, UINT uiCommand, UINT* pfState)
  934. {
  935. if (!_hwndTB)
  936. return E_FAIL;
  937. *pfState = (UINT)SendMessage(_hwndTB, TB_GETSTATE, uiCommand, 0L);
  938. return S_OK;
  939. }
  940. HRESULT CBrowserBandSite::SetState(const GUID* pguidButtonGroup, UINT uiCommand, UINT fState)
  941. {
  942. if (!_hwndTB)
  943. return E_FAIL;
  944. UINT_PTR uiState = SendMessage(_hwndTB, TB_GETSTATE, uiCommand, NULL);
  945. uiState ^= fState;
  946. if (uiState)
  947. SendMessage(_hwndTB, TB_SETSTATE, uiCommand, (LPARAM)fState);
  948. return S_OK;
  949. }
  950. HRESULT CBrowserBandSite::SetImageList( const GUID* pguidCmdGroup, HIMAGELIST himlNormal, HIMAGELIST himlHot, HIMAGELIST himlDisabled)
  951. {
  952. if (IsEqualGUID(*pguidCmdGroup, _guidButtonGroup)) {
  953. SendMessage(_hwndTB, TB_SETIMAGELIST, 0, (LPARAM)himlNormal);
  954. SendMessage(_hwndTB, TB_SETHOTIMAGELIST, 0, (LPARAM)himlHot);
  955. SendMessage(_hwndTB, TB_SETDISABLEDIMAGELIST, 0, (LPARAM)himlDisabled);
  956. }
  957. return S_OK;
  958. };
  959. BYTE TBStateFromIndex(HWND hwnd, int iIndex)
  960. {
  961. TBBUTTONINFO tbbi;
  962. tbbi.cbSize = sizeof(TBBUTTONINFO);
  963. tbbi.dwMask = TBIF_BYINDEX | TBIF_STATE;
  964. tbbi.fsState = 0;
  965. SendMessage(hwnd, TB_GETBUTTONINFO, iIndex, (LPARAM)&tbbi);
  966. return tbbi.fsState;
  967. }
  968. int CBrowserBandSite::_ContextMenuHittest(LPARAM lParam, POINT* ppt)
  969. {
  970. if (lParam == (LPARAM)-1)
  971. {
  972. //
  973. // Keyboard activation. If one of our toolbars has
  974. // focus, and it has a hottracked button, put up the
  975. // context menu below that button.
  976. //
  977. HWND hwnd = GetFocus();
  978. if (hwnd && (hwnd == _hwndTB || hwnd == _hwndOptionsTB))
  979. {
  980. INT_PTR iHot = SendMessage(hwnd, TB_GETHOTITEM, 0, 0);
  981. if (iHot == -1)
  982. {
  983. // couldn't find a hot item, just use the first visible button
  984. iHot = 0;
  985. while (TBSTATE_HIDDEN & TBStateFromIndex(hwnd, (int)iHot))
  986. iHot++;
  987. ASSERT(iHot < SendMessage(hwnd, TB_BUTTONCOUNT, 0, 0));
  988. }
  989. RECT rc;
  990. SendMessage(hwnd, TB_GETITEMRECT, iHot, (LPARAM)&rc);
  991. ppt->x = rc.left;
  992. ppt->y = rc.bottom;
  993. MapWindowPoints(hwnd, HWND_DESKTOP, ppt, 1);
  994. return -1;
  995. }
  996. }
  997. return SUPERCLASS::_ContextMenuHittest(lParam, ppt);
  998. }
  999. HMENU CBrowserBandSite::_LoadContextMenu()
  1000. {
  1001. HMENU hmenu = SUPERCLASS::_LoadContextMenu();
  1002. DeleteMenu(hmenu, BSIDM_SHOWTITLEBAND, MF_BYCOMMAND);
  1003. return hmenu;
  1004. }
  1005. // create the options (close/hide) buttons
  1006. void CBrowserBandSite::_CreateOptionsTB()
  1007. {
  1008. // create toolbar for close/hide button always since band site is reused
  1009. // for captionless band sites (iBar), this toolbar is only hidden
  1010. _hwndOptionsTB = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
  1011. WS_VISIBLE |
  1012. WS_CHILD | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS |
  1013. WS_CLIPCHILDREN |
  1014. WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOMOVEY | CCS_NOPARENTALIGN |
  1015. CCS_NORESIZE,
  1016. 0, 0, 30, 18, _hwnd, 0, HINST_THISDLL, NULL);
  1017. _PrepareOptionsTB();
  1018. }
  1019. // init as toolbar and load bitmaps
  1020. void CBrowserBandSite::_PrepareOptionsTB()
  1021. {
  1022. if (_hwndOptionsTB)
  1023. {
  1024. static const TBBUTTON c_tb[] =
  1025. {
  1026. { 0, IDM_AB_AUTOHIDE, TBSTATE_ENABLED, TBSTYLE_CHECK, {0,0}, 0, 0 },
  1027. { 1, IDM_AB_CLOSE, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, 1 }
  1028. };
  1029. SendMessage(_hwndOptionsTB, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
  1030. SendMessage(_hwndOptionsTB, CCM_SETVERSION, COMCTL32_VERSION, 0);
  1031. SendMessage(_hwndOptionsTB, TB_SETBITMAPSIZE, 0, (LPARAM) MAKELONG(13, 11));
  1032. TBADDBITMAP tbab = { HINST_THISDLL, IDB_BROWSERTOOLBAR };
  1033. SendMessage(_hwndOptionsTB, TB_ADDBITMAP, 3, (LPARAM)&tbab);
  1034. LONG_PTR cbOffset = SendMessage(_hwndOptionsTB, TB_ADDSTRING, (WPARAM)MLGetHinst(), (LPARAM)IDS_BANDSITE_CLOSE_LABELS);
  1035. TBBUTTON tb[ARRAYSIZE(c_tb)];
  1036. UpdateButtonArray(tb, c_tb, ARRAYSIZE(c_tb), cbOffset);
  1037. SendMessage(_hwndOptionsTB, TB_SETMAXTEXTROWS, 0, 0);
  1038. SendMessage(_hwndOptionsTB, TB_ADDBUTTONS, ARRAYSIZE(tb), (LPARAM)tb);
  1039. SendMessage(_hwndOptionsTB, TB_SETINDENT, (WPARAM)0, 0);
  1040. _SizeOptionsTB();
  1041. }
  1042. }
  1043. void CBrowserBandSite::_PositionToolbars(LPPOINT ppt)
  1044. {
  1045. RECT rc;
  1046. if (ppt)
  1047. {
  1048. rc.left = 0;
  1049. rc.right = ppt->x;
  1050. }
  1051. else
  1052. {
  1053. GetClientRect(_hwnd, &rc);
  1054. }
  1055. if (_hwndOptionsTB)
  1056. {
  1057. // always put the close restore at the top right of the floater window
  1058. int x;
  1059. if (_dwMode & DBIF_VIEWMODE_VERTICAL)
  1060. {
  1061. RECT rcTB;
  1062. GetWindowRect(_hwndOptionsTB, &rcTB);
  1063. x = rc.right - RECTWIDTH(rcTB) - 1;
  1064. }
  1065. else
  1066. {
  1067. x = rc.left;
  1068. }
  1069. MARGINS mBorders = {0, 1, 0, 0}; // 1 mimics old behavior downlevel.
  1070. Comctl32_GetBandMargins(_hwnd, &mBorders);
  1071. SetWindowPos(_hwndOptionsTB, HWND_TOP, x - mBorders.cxRightWidth, mBorders.cyTopHeight, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
  1072. }
  1073. if (_hwndTBRebar)
  1074. {
  1075. if (_fToolbar)
  1076. {
  1077. // toolbar goes on its own line below title
  1078. SetWindowPos(_hwndTBRebar, HWND_TOP,
  1079. rc.left + CX_TBOFFSET,
  1080. _uTitle + CX_TBOFFSET,
  1081. rc.right - 2 * CX_TBOFFSET,
  1082. _uToolbar,
  1083. SWP_SHOWWINDOW);
  1084. }
  1085. else
  1086. {
  1087. ASSERT(!IsWindowVisible(_hwndTBRebar));
  1088. }
  1089. }
  1090. }
  1091. // sets the size of the toolbar. if we're in theater mode, we need to show the pushpin.
  1092. // otherwise just show the close
  1093. void CBrowserBandSite::_SizeOptionsTB()
  1094. {
  1095. RECT rc;
  1096. GetWindowRect(_hwndOptionsTB, &rc);
  1097. LRESULT lButtonSize = SendMessage(_hwndOptionsTB, TB_GETBUTTONSIZE, 0, 0L);
  1098. SetWindowPos(_hwndOptionsTB, NULL, 0, 0, LOWORD(lButtonSize) * (_fTheater ? 2 : 1),
  1099. RECTHEIGHT(rc), SWP_NOMOVE | SWP_NOACTIVATE);
  1100. DWORD_PTR dwState = SendMessage(_hwndOptionsTB, TB_GETSTATE, IDM_AB_AUTOHIDE, 0);
  1101. dwState &= ~(TBSTATE_HIDDEN | TBSTATE_CHECKED);
  1102. if (!_fTheater)
  1103. dwState |= TBSTATE_HIDDEN;
  1104. if (_fNoAutoHide)
  1105. dwState |= TBSTATE_CHECKED;
  1106. SendMessage(_hwndOptionsTB, TB_SETSTATE, IDM_AB_AUTOHIDE, dwState);
  1107. _PositionToolbars(NULL);
  1108. }