windows-nt/Source/XPSP1/NT/shell/browseui/browbar.cpp

421 lines
12 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
// 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 <mainwin.h>
#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);
}
}
// }