// coming soon: new deskbar (old deskbar moved to browbar base class) #include "priv.h" #include "sccls.h" #include "resource.h" #include "browbs.h" #include "browbar.h" #include "theater.h" #include "shbrows2.h" #include "varutil.h" #ifdef UNIX #include #endif #define SUPERCLASS CDockingBar static const WCHAR c_szExplorerBars[] = TEXT("Software\\Microsoft\\Internet Explorer\\Explorer Bars\\"); //*** CBrowserBar_CreateInstance -- // STDAPI CBrowserBar_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi) { // aggregation checking is handled in class factory CBrowserBar *pwbar = new CBrowserBar(); if (pwbar) { *ppunk = SAFECAST(pwbar, IDockingWindow*); return S_OK; } return E_OUTOFMEMORY; } //*** // NOTES // this creates the BrowserBar (infobar) and sets up it's specific style // such as captionless rebar and such HRESULT BrowserBar_Init(CBrowserBar* pdb, IUnknown** ppbs, int idBar) { HRESULT hr; if (ppbs) *ppbs = NULL; CBrowserBandSite *pcbs = new CBrowserBandSite(); if (pcbs) { IDeskBarClient *pdbc = SAFECAST(pcbs, IDeskBarClient*); BANDSITEINFO bsinfo; bsinfo.dwMask = BSIM_STYLE; bsinfo.dwStyle = BSIS_NOGRIPPER | BSIS_LEFTALIGN; pcbs->SetBandSiteInfo(&bsinfo); hr = pdb->SetClient(pdbc); if (SUCCEEDED(hr)) { if (ppbs) { *ppbs = pdbc; pdbc->AddRef(); } } pdbc->Release(); ASSERT(idBar == IDBAR_VERTICAL || idBar == IDBAR_HORIZONTAL); pdb->SetIdBar(idBar); } else { hr = E_OUTOFMEMORY; } return hr; } //*** CBrowserBar::IPersistStream*::* { HRESULT CBrowserBar::GetClassID(CLSID *pClassID) { *pClassID = CLSID_BrowserBar; return S_OK; } HRESULT CBrowserBar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut) { if (!pguidCmdGroup) { // nothing } else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup)) { return IUnknown_Exec(_punkChild, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut); } else if (IsEqualGUID(CGID_DeskBarClient, *pguidCmdGroup)) { switch (nCmdID) { case DBCID_EMPTY: if (_ptbSite) { // if we have no bands left, hide VARIANT var = {VT_UNKNOWN}; var.punkVal = SAFECAST(this, IDeskBar*); AddRef(); _StopCurrentBand(); IUnknown_Exec(_ptbSite, &CGID_Explorer, SBCMDID_TOOLBAREMPTY, nCmdexecopt, &var, NULL); VariantClearLazy(&var); } break; case DBCID_RESIZE: goto ForwardUp; break; case DBCID_CLSIDOFBAR: ASSERT(nCmdexecopt == 0 || nCmdexecopt == 1); if (nCmdexecopt == 0) { //bar is being hidden _StopCurrentBand(); _clsidCurrentBand = GUID_NULL; } else if (pvarargIn && pvarargIn->vt == VT_BSTR) { CLSID clsidTemp; GUIDFromString(pvarargIn->bstrVal, &clsidTemp); //if given a clsid and it's a new one, save the old one's settings //then set it as the current clsid if (!IsEqualIID(clsidTemp, _clsidCurrentBand)) { _PersistState(_hwnd, TRUE); _StopCurrentBand(); } _clsidCurrentBand = clsidTemp; if (_hwnd && IsWindow(_hwnd)) { UINT uiNewWidthOrHeight = _PersistState(_hwnd, FALSE); RECT rc = {0}; GetWindowRect(_hwnd, &rc); if (_idBar == IDBAR_VERTICAL) rc.right = rc.left + uiNewWidthOrHeight; else rc.top = rc.bottom - uiNewWidthOrHeight; SetWindowPos(_hwnd, NULL, 0, 0, RECTWIDTH(rc), RECTHEIGHT(rc), SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE); } } else if (!pvarargIn && pvarargOut) { return InitBSTRVariantFromGUID(pvarargOut, _clsidCurrentBand); } else ASSERT(FALSE); break; } return S_OK; } else if (IsEqualGUID(CGID_Theater, *pguidCmdGroup)) { switch (nCmdID) { case THID_ACTIVATE: // if we're on a small monitor, start off as autohide _fTheater = TRUE; ResizeBorderDW(NULL, NULL, FALSE); _OnSize(); // pass back pin button's state pvarargOut->vt = VT_I4; pvarargOut->lVal = !_fNoAutoHide; break; case THID_DEACTIVATE: _fTheater = FALSE; // if we're on a small monitor, restore to theater default width _szChild.cx = _iTheaterWidth; _AdjustToChildSize(); break; case THID_SETBROWSERBARAUTOHIDE: // pvarargIn->lVal contains new _fAutoHide. // fake message pin button was pressed only when _fNoAutoHide == pvarargIn->lVal // which means new _fNoAutoHide != old _fNoAutoHide if ((_fNoAutoHide && pvarargIn->lVal) || !(_fNoAutoHide || pvarargIn->lVal)) { // first update state and change bitmap _fNoAutoHide = !pvarargIn->lVal; // then notify theater mode manager because it owns the msg hook and does // the hiding IUnknown_Exec(_ptbSite, &CGID_Theater, THID_SETBROWSERBARAUTOHIDE, 0, pvarargIn, NULL); // negotiate with the browser for space _Recalc(); _PersistState(_hwnd, FALSE); } break; default: goto ForwardUp; } IUnknown_Exec(_punkChild, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut); } ForwardUp: return SUPERCLASS::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut); } #define ABS(i) (((i) < 0) ? -(i) : (i)) void CBrowserBar::_HandleWindowPosChanging(LPWINDOWPOS pwp) { if (_fDragging) { int cxMin = GetSystemMetrics(SM_CXVSCROLL) * 4; if (pwp->cx < cxMin) pwp->cx = cxMin; } } LRESULT CBrowserBar::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_NCHITTEST: { LRESULT lres = _OnNCHitTest(wParam, lParam); #ifdef DEBUG // non-LHS bar useful for testing discussion bar etc. stuff // so allow drag to get it there if (0) #endif { // don't allow drag in browbar if (lres == HTCAPTION) lres = HTCLIENT; } return lres; } case WM_ERASEBKGND: if (_fTheater) { HDC hdc = (HDC) wParam; RECT rc; GetClientRect(hwnd, &rc); SHFillRectClr(hdc, &rc, RGB(0,0,0)); return 1; } break; case WM_EXITSIZEMOVE: { // save explorer bar's new width to registry _PersistState(hwnd, TRUE); } break; case WM_SIZE: { // browser bandsite needs to hear about resizing LRESULT lres; _CheckForwardWinEvent(uMsg, wParam, lParam, &lres); } break; } return SUPERCLASS::v_WndProc(hwnd, uMsg, wParam, lParam); } BOOL CBrowserBar::_CheckForwardWinEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres) { HWND hwnd = NULL; switch (uMsg) { case WM_SIZE: { // HACKHACK: munge the size so that width is browbandsite's // new width. bbs needs to hear about resizing so that it // can reposition its close/autohide window. POINT pt = {LOWORD(lParam), HIWORD(lParam)}; pt.x -= 4 * GetSystemMetrics(SM_CXEDGE); lParam = MAKELONG(pt.x, pt.y); hwnd = _hwndChild; break; } } if (hwnd && _pWEH && _pWEH->IsWindowOwner(hwnd) == S_OK) { _pWEH->OnWinEvent(_hwnd, uMsg, wParam, lParam, plres); return TRUE; } return SUPERCLASS::_CheckForwardWinEvent(uMsg, wParam, lParam, plres); } void CBrowserBar::_GetChildPos(LPRECT prc) { GetClientRect(_hwnd, prc); if (_fTheater) prc->right--; else { // Make room for the resizing bar and make sure the right scrollbar is // tucked under the right edge of the parent if we are on the top or bottom switch(_uSide) { case ABE_TOP: prc->bottom -= GetSystemMetrics(SM_CYFRAME); prc->right += GetSystemMetrics(SM_CXFRAME); break; case ABE_BOTTOM: prc->top += GetSystemMetrics(SM_CYFRAME); prc->right += GetSystemMetrics(SM_CXFRAME); break; case ABE_LEFT: prc->right -= GetSystemMetrics(SM_CXFRAME); break; case ABE_RIGHT: prc->left += GetSystemMetrics(SM_CXFRAME); break; } } if (prc->left > prc->right) prc->right = prc->left; if (prc->top > prc->bottom) prc->bottom = prc->top; } void CBrowserBar::_GetStyleForMode(UINT eMode, LONG* plStyle, LONG *plExStyle, HWND* phwndParent) { *plStyle = WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS; *plExStyle= 0; *phwndParent = PARENT_BBTMMOST(); } // bSetNewRect controls whether we override the current rect or autohide setting UINT CBrowserBar::_PersistState(HWND hwnd, BOOL bSetNewRect) { BROWBARSAVE bbs = {0}; RECT rc = {0}; UINT retval = 0; if (IsEqualIID(_clsidCurrentBand, GUID_NULL)) { //FEATURE: this assert is getting hit, why? //ASSERT(FALSE); //do we even need to check this anymore? return 0; } // use current uiWidthOrHeight and fAutoHide in case there is no value in registry yet if (hwnd) { GetWindowRect(hwnd, &rc); // bad hack if (_idBar == IDBAR_VERTICAL) bbs.uiWidthOrHeight = RECTWIDTH(rc); else bbs.uiWidthOrHeight = RECTHEIGHT(rc); } bbs.fAutoHide = !_fNoAutoHide; WCHAR wszClsid[GUIDSTR_MAX]; DWORD dwType = REG_BINARY; DWORD cbSize = SIZEOF(BROWBARSAVE); SHStringFromGUID(_clsidCurrentBand, wszClsid, ARRAYSIZE(wszClsid)); WCHAR wszKeyPath[MAX_PATH]; StrCpyN(wszKeyPath, c_szExplorerBars, ARRAYSIZE(wszKeyPath)); StrCatBuff(wszKeyPath, wszClsid, ARRAYSIZE(wszKeyPath)); SHRegGetUSValueW(wszKeyPath, L"BarSize", &dwType, (LPBYTE)&bbs, &cbSize, FALSE, NULL, 0); //if there is no window yet and no saved size, pick a reasonable default if (bbs.uiWidthOrHeight == 0) bbs.uiWidthOrHeight = (IDBAR_VERTICAL == _idBar) ? COMMBAR_HEIGHT : INFOBAR_WIDTH; if (bSetNewRect) { if (_idBar == IDBAR_VERTICAL) { bbs.uiWidthOrHeight = RECTWIDTH(rc); retval = RECTWIDTH(rc); } else { bbs.uiWidthOrHeight = RECTHEIGHT(rc); retval = RECTHEIGHT(rc); } } else { bbs.fAutoHide = !_fNoAutoHide; retval = bbs.uiWidthOrHeight; } if (bSetNewRect) SHRegSetUSValueW(wszKeyPath, L"BarSize", dwType, (LPBYTE)&bbs, cbSize, SHREGSET_FORCE_HKCU); return retval; } void CBrowserBar::_StopCurrentBand() { //stop any streaming content or navigations, except for the search band if we stop it // then we could have incompletely loaded ui if (!IsEqualGUID(CLSID_SearchBand, _clsidCurrentBand)) { IUnknown_Exec(_punkChild, NULL, OLECMDID_STOP, 0, NULL, NULL); } } // }