Source code of Windows XP (NT5)
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.

420 lines
12 KiB

  1. // coming soon: new deskbar (old deskbar moved to browbar base class)
  2. #include "priv.h"
  3. #include "sccls.h"
  4. #include "resource.h"
  5. #include "browbs.h"
  6. #include "browbar.h"
  7. #include "theater.h"
  8. #include "shbrows2.h"
  9. #include "varutil.h"
  10. #ifdef UNIX
  11. #include <mainwin.h>
  12. #endif
  13. #define SUPERCLASS CDockingBar
  14. static const WCHAR c_szExplorerBars[] = TEXT("Software\\Microsoft\\Internet Explorer\\Explorer Bars\\");
  15. //*** CBrowserBar_CreateInstance --
  16. //
  17. STDAPI CBrowserBar_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  18. {
  19. // aggregation checking is handled in class factory
  20. CBrowserBar *pwbar = new CBrowserBar();
  21. if (pwbar) {
  22. *ppunk = SAFECAST(pwbar, IDockingWindow*);
  23. return S_OK;
  24. }
  25. return E_OUTOFMEMORY;
  26. }
  27. //***
  28. // NOTES
  29. // this creates the BrowserBar (infobar) and sets up it's specific style
  30. // such as captionless rebar and such
  31. HRESULT BrowserBar_Init(CBrowserBar* pdb, IUnknown** ppbs, int idBar)
  32. {
  33. HRESULT hr;
  34. if (ppbs)
  35. *ppbs = NULL;
  36. CBrowserBandSite *pcbs = new CBrowserBandSite();
  37. if (pcbs)
  38. {
  39. IDeskBarClient *pdbc = SAFECAST(pcbs, IDeskBarClient*);
  40. BANDSITEINFO bsinfo;
  41. bsinfo.dwMask = BSIM_STYLE;
  42. bsinfo.dwStyle = BSIS_NOGRIPPER | BSIS_LEFTALIGN;
  43. pcbs->SetBandSiteInfo(&bsinfo);
  44. hr = pdb->SetClient(pdbc);
  45. if (SUCCEEDED(hr))
  46. {
  47. if (ppbs)
  48. {
  49. *ppbs = pdbc;
  50. pdbc->AddRef();
  51. }
  52. }
  53. pdbc->Release();
  54. ASSERT(idBar == IDBAR_VERTICAL || idBar == IDBAR_HORIZONTAL);
  55. pdb->SetIdBar(idBar);
  56. }
  57. else
  58. {
  59. hr = E_OUTOFMEMORY;
  60. }
  61. return hr;
  62. }
  63. //*** CBrowserBar::IPersistStream*::* {
  64. HRESULT CBrowserBar::GetClassID(CLSID *pClassID)
  65. {
  66. *pClassID = CLSID_BrowserBar;
  67. return S_OK;
  68. }
  69. HRESULT CBrowserBar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,
  70. VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  71. {
  72. if (!pguidCmdGroup)
  73. {
  74. // nothing
  75. }
  76. else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  77. {
  78. return IUnknown_Exec(_punkChild, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  79. }
  80. else if (IsEqualGUID(CGID_DeskBarClient, *pguidCmdGroup))
  81. {
  82. switch (nCmdID) {
  83. case DBCID_EMPTY:
  84. if (_ptbSite) {
  85. // if we have no bands left, hide
  86. VARIANT var = {VT_UNKNOWN};
  87. var.punkVal = SAFECAST(this, IDeskBar*);
  88. AddRef();
  89. _StopCurrentBand();
  90. IUnknown_Exec(_ptbSite, &CGID_Explorer, SBCMDID_TOOLBAREMPTY, nCmdexecopt, &var, NULL);
  91. VariantClearLazy(&var);
  92. }
  93. break;
  94. case DBCID_RESIZE:
  95. goto ForwardUp;
  96. break;
  97. case DBCID_CLSIDOFBAR:
  98. ASSERT(nCmdexecopt == 0 || nCmdexecopt == 1);
  99. if (nCmdexecopt == 0)
  100. {
  101. //bar is being hidden
  102. _StopCurrentBand();
  103. _clsidCurrentBand = GUID_NULL;
  104. }
  105. else if (pvarargIn && pvarargIn->vt == VT_BSTR)
  106. {
  107. CLSID clsidTemp;
  108. GUIDFromString(pvarargIn->bstrVal, &clsidTemp);
  109. //if given a clsid and it's a new one, save the old one's settings
  110. //then set it as the current clsid
  111. if (!IsEqualIID(clsidTemp, _clsidCurrentBand))
  112. {
  113. _PersistState(_hwnd, TRUE);
  114. _StopCurrentBand();
  115. }
  116. _clsidCurrentBand = clsidTemp;
  117. if (_hwnd && IsWindow(_hwnd))
  118. {
  119. UINT uiNewWidthOrHeight = _PersistState(_hwnd, FALSE);
  120. RECT rc = {0};
  121. GetWindowRect(_hwnd, &rc);
  122. if (_idBar == IDBAR_VERTICAL)
  123. rc.right = rc.left + uiNewWidthOrHeight;
  124. else
  125. rc.top = rc.bottom - uiNewWidthOrHeight;
  126. SetWindowPos(_hwnd, NULL, 0, 0, RECTWIDTH(rc), RECTHEIGHT(rc), SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
  127. }
  128. }
  129. else if (!pvarargIn && pvarargOut)
  130. {
  131. return InitBSTRVariantFromGUID(pvarargOut, _clsidCurrentBand);
  132. }
  133. else
  134. ASSERT(FALSE);
  135. break;
  136. }
  137. return S_OK;
  138. }
  139. else if (IsEqualGUID(CGID_Theater, *pguidCmdGroup)) {
  140. switch (nCmdID) {
  141. case THID_ACTIVATE:
  142. // if we're on a small monitor, start off as autohide
  143. _fTheater = TRUE;
  144. ResizeBorderDW(NULL, NULL, FALSE);
  145. _OnSize();
  146. // pass back pin button's state
  147. pvarargOut->vt = VT_I4;
  148. pvarargOut->lVal = !_fNoAutoHide;
  149. break;
  150. case THID_DEACTIVATE:
  151. _fTheater = FALSE;
  152. // if we're on a small monitor, restore to theater default width
  153. _szChild.cx = _iTheaterWidth;
  154. _AdjustToChildSize();
  155. break;
  156. case THID_SETBROWSERBARAUTOHIDE:
  157. // pvarargIn->lVal contains new _fAutoHide.
  158. // fake message pin button was pressed only when _fNoAutoHide == pvarargIn->lVal
  159. // which means new _fNoAutoHide != old _fNoAutoHide
  160. if ((_fNoAutoHide && pvarargIn->lVal) || !(_fNoAutoHide || pvarargIn->lVal)) {
  161. // first update state and change bitmap
  162. _fNoAutoHide = !pvarargIn->lVal;
  163. // then notify theater mode manager because it owns the msg hook and does
  164. // the hiding
  165. IUnknown_Exec(_ptbSite, &CGID_Theater, THID_SETBROWSERBARAUTOHIDE, 0, pvarargIn, NULL);
  166. // negotiate with the browser for space
  167. _Recalc();
  168. _PersistState(_hwnd, FALSE);
  169. }
  170. break;
  171. default:
  172. goto ForwardUp;
  173. }
  174. IUnknown_Exec(_punkChild, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  175. }
  176. ForwardUp:
  177. return SUPERCLASS::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  178. }
  179. #define ABS(i) (((i) < 0) ? -(i) : (i))
  180. void CBrowserBar::_HandleWindowPosChanging(LPWINDOWPOS pwp)
  181. {
  182. if (_fDragging) {
  183. int cxMin = GetSystemMetrics(SM_CXVSCROLL) * 4;
  184. if (pwp->cx < cxMin)
  185. pwp->cx = cxMin;
  186. }
  187. }
  188. LRESULT CBrowserBar::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  189. {
  190. switch (uMsg) {
  191. case WM_NCHITTEST:
  192. {
  193. LRESULT lres = _OnNCHitTest(wParam, lParam);
  194. #ifdef DEBUG
  195. // non-LHS bar useful for testing discussion bar etc. stuff
  196. // so allow drag to get it there
  197. if (0)
  198. #endif
  199. {
  200. // don't allow drag in browbar
  201. if (lres == HTCAPTION)
  202. lres = HTCLIENT;
  203. }
  204. return lres;
  205. }
  206. case WM_ERASEBKGND:
  207. if (_fTheater) {
  208. HDC hdc = (HDC) wParam;
  209. RECT rc;
  210. GetClientRect(hwnd, &rc);
  211. SHFillRectClr(hdc, &rc, RGB(0,0,0));
  212. return 1;
  213. }
  214. break;
  215. case WM_EXITSIZEMOVE:
  216. { // save explorer bar's new width to registry
  217. _PersistState(hwnd, TRUE);
  218. }
  219. break;
  220. case WM_SIZE:
  221. {
  222. // browser bandsite needs to hear about resizing
  223. LRESULT lres;
  224. _CheckForwardWinEvent(uMsg, wParam, lParam, &lres);
  225. }
  226. break;
  227. }
  228. return SUPERCLASS::v_WndProc(hwnd, uMsg, wParam, lParam);
  229. }
  230. BOOL CBrowserBar::_CheckForwardWinEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres)
  231. {
  232. HWND hwnd = NULL;
  233. switch (uMsg) {
  234. case WM_SIZE:
  235. {
  236. // HACKHACK: munge the size so that width is browbandsite's
  237. // new width. bbs needs to hear about resizing so that it
  238. // can reposition its close/autohide window.
  239. POINT pt = {LOWORD(lParam), HIWORD(lParam)};
  240. pt.x -= 4 * GetSystemMetrics(SM_CXEDGE);
  241. lParam = MAKELONG(pt.x, pt.y);
  242. hwnd = _hwndChild;
  243. break;
  244. }
  245. }
  246. if (hwnd && _pWEH && _pWEH->IsWindowOwner(hwnd) == S_OK) {
  247. _pWEH->OnWinEvent(_hwnd, uMsg, wParam, lParam, plres);
  248. return TRUE;
  249. }
  250. return SUPERCLASS::_CheckForwardWinEvent(uMsg, wParam, lParam, plres);
  251. }
  252. void CBrowserBar::_GetChildPos(LPRECT prc)
  253. {
  254. GetClientRect(_hwnd, prc);
  255. if (_fTheater)
  256. prc->right--;
  257. else
  258. {
  259. // Make room for the resizing bar and make sure the right scrollbar is
  260. // tucked under the right edge of the parent if we are on the top or bottom
  261. switch(_uSide)
  262. {
  263. case ABE_TOP:
  264. prc->bottom -= GetSystemMetrics(SM_CYFRAME);
  265. prc->right += GetSystemMetrics(SM_CXFRAME);
  266. break;
  267. case ABE_BOTTOM:
  268. prc->top += GetSystemMetrics(SM_CYFRAME);
  269. prc->right += GetSystemMetrics(SM_CXFRAME);
  270. break;
  271. case ABE_LEFT:
  272. prc->right -= GetSystemMetrics(SM_CXFRAME);
  273. break;
  274. case ABE_RIGHT:
  275. prc->left += GetSystemMetrics(SM_CXFRAME);
  276. break;
  277. }
  278. }
  279. if (prc->left > prc->right)
  280. prc->right = prc->left;
  281. if (prc->top > prc->bottom)
  282. prc->bottom = prc->top;
  283. }
  284. void CBrowserBar::_GetStyleForMode(UINT eMode, LONG* plStyle, LONG *plExStyle, HWND* phwndParent)
  285. {
  286. *plStyle = WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
  287. *plExStyle= 0;
  288. *phwndParent = PARENT_BBTMMOST();
  289. }
  290. // bSetNewRect controls whether we override the current rect or autohide setting
  291. UINT CBrowserBar::_PersistState(HWND hwnd, BOOL bSetNewRect)
  292. {
  293. BROWBARSAVE bbs = {0};
  294. RECT rc = {0};
  295. UINT retval = 0;
  296. if (IsEqualIID(_clsidCurrentBand, GUID_NULL))
  297. {
  298. //FEATURE: this assert is getting hit, why?
  299. //ASSERT(FALSE); //do we even need to check this anymore?
  300. return 0;
  301. }
  302. // use current uiWidthOrHeight and fAutoHide in case there is no value in registry yet
  303. if (hwnd)
  304. {
  305. GetWindowRect(hwnd, &rc); // bad hack
  306. if (_idBar == IDBAR_VERTICAL)
  307. bbs.uiWidthOrHeight = RECTWIDTH(rc);
  308. else
  309. bbs.uiWidthOrHeight = RECTHEIGHT(rc);
  310. }
  311. bbs.fAutoHide = !_fNoAutoHide;
  312. WCHAR wszClsid[GUIDSTR_MAX];
  313. DWORD dwType = REG_BINARY;
  314. DWORD cbSize = SIZEOF(BROWBARSAVE);
  315. SHStringFromGUID(_clsidCurrentBand, wszClsid, ARRAYSIZE(wszClsid));
  316. WCHAR wszKeyPath[MAX_PATH];
  317. StrCpyN(wszKeyPath, c_szExplorerBars, ARRAYSIZE(wszKeyPath));
  318. StrCatBuff(wszKeyPath, wszClsid, ARRAYSIZE(wszKeyPath));
  319. SHRegGetUSValueW(wszKeyPath, L"BarSize", &dwType, (LPBYTE)&bbs, &cbSize, FALSE, NULL, 0);
  320. //if there is no window yet and no saved size, pick a reasonable default
  321. if (bbs.uiWidthOrHeight == 0)
  322. bbs.uiWidthOrHeight = (IDBAR_VERTICAL == _idBar) ? COMMBAR_HEIGHT : INFOBAR_WIDTH;
  323. if (bSetNewRect)
  324. {
  325. if (_idBar == IDBAR_VERTICAL)
  326. {
  327. bbs.uiWidthOrHeight = RECTWIDTH(rc);
  328. retval = RECTWIDTH(rc);
  329. }
  330. else
  331. {
  332. bbs.uiWidthOrHeight = RECTHEIGHT(rc);
  333. retval = RECTHEIGHT(rc);
  334. }
  335. }
  336. else
  337. {
  338. bbs.fAutoHide = !_fNoAutoHide;
  339. retval = bbs.uiWidthOrHeight;
  340. }
  341. if (bSetNewRect)
  342. SHRegSetUSValueW(wszKeyPath, L"BarSize", dwType, (LPBYTE)&bbs, cbSize, SHREGSET_FORCE_HKCU);
  343. return retval;
  344. }
  345. void CBrowserBar::_StopCurrentBand()
  346. {
  347. //stop any streaming content or navigations, except for the search band if we stop it
  348. // then we could have incompletely loaded ui
  349. if (!IsEqualGUID(CLSID_SearchBand, _clsidCurrentBand))
  350. {
  351. IUnknown_Exec(_punkChild, NULL, OLECMDID_STOP, 0, NULL, NULL);
  352. }
  353. }
  354. // }