windows-nt/Source/XPSP1/NT/shell/browseui/brand.cpp
2020-09-26 16:20:57 +08:00

1343 lines
41 KiB
C++

#include "priv.h"
#include "sccls.h"
#include "legacy.h"
#include "itbar.h"
#include "itbdrop.h"
#include "brand.h"
#include "theater.h"
#include "resource.h"
#include <tb_ids.h>
#include "mluisupp.h"
typedef struct {
HPALETTE hpal;
HBITMAP hbm;
int cyBrand;
int cxBrandExtent;
int cyBrandExtent;
int cyBrandLeadIn;
COLORREF clrBkStat;
COLORREF clrBkAnim;
LPTSTR pszBitmap;
LPTSTR pszStaticBitmap;
} BRANDCONTEXT;
class CBrandBand : public CToolBand,
public IWinEventHandler,
public IDispatch
{
public:
// IUnknown
virtual STDMETHODIMP_(ULONG) AddRef(void) { return CToolBand::AddRef(); }
virtual STDMETHODIMP_(ULONG) Release(void) { return CToolBand::Release(); }
virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
// IObjectWithSite
virtual STDMETHODIMP SetSite(IUnknown* punkSite);
// *** IDeskBand methods ***
virtual STDMETHODIMP GetBandInfo(DWORD dwBandID, DWORD fViewMode, DESKBANDINFO* pdbi);
// IOleCommandTarget
virtual STDMETHODIMP Exec(const GUID *pguidCmdGroup,
DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn,
VARIANTARG *pvarargOut);
// IPersist
virtual STDMETHODIMP GetClassID(CLSID *pClassID);
// IPersistStream
virtual STDMETHODIMP Load(IStream *pStm);
virtual STDMETHODIMP Save(IStream *pStm, BOOL fClearDirty);
// IWinEventHandler
virtual STDMETHODIMP OnWinEvent(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plre);
virtual STDMETHODIMP IsWindowOwner(HWND hwnd);
// IDispatch
virtual STDMETHODIMP GetTypeInfoCount(UINT *pctinfo){return(E_NOTIMPL);}
virtual STDMETHODIMP GetTypeInfo(UINT itinfo,LCID lcid,ITypeInfo **pptinfo){return(E_NOTIMPL);}
virtual STDMETHODIMP GetIDsOfNames(REFIID riid,OLECHAR **rgszNames,UINT cNames, LCID lcid, DISPID * rgdispid){return(E_NOTIMPL);}
virtual STDMETHODIMP Invoke(DISPID dispidMember,REFIID riid,LCID lcid,WORD wFlags,
DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,UINT * puArgErr);
// IServiceProvider
virtual STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void ** ppvObj);
protected:
CBrandBand();
virtual ~CBrandBand();
friend HRESULT CBrandBand_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi); // for ctor
BITBOOL _fVertical:1;
BITBOOL _fAnimating:1;
BITBOOL _fMinAlways:1;
BITBOOL _fTheater :1;
BOOL _fShellView;
BRANDCONTEXT *_pbc;
int _yOrg;
static HDC s_hdc;
static BRANDCONTEXT s_bcWebSmall; // BrandContext for the small web view bitmap
static BRANDCONTEXT s_bcWebLarge; // BrandContext for the large web view bitmap
static BRANDCONTEXT s_bcWebMicro; // BrandContext for the micro web view bitmap
static BRANDCONTEXT s_bcShellSmall; // BrandContext for the small shell view bitmap
static BRANDCONTEXT s_bcShellLarge; // BrandContext for the large shell view bitmap
IWebBrowserApp * _pdie; // Used when Navigating a Browser Window with a URL String
IBrowserService * _pbs; // Only valid when we are in a Browser Windows Toolbar. (Not Toolband)
IWebBrowser2 * _pwb2; // Only valid when we are a Toolband (not toolbar).
DWORD _dwcpCookie; // ConnectionPoint cookie for DWebBrowserEvents from the Browser Window.
DWORD _dwCookieServiceBrandBand; // Service cookie for SID_SBrandBand
LONG _lAnimateCount; // Keep track of how many StartAnimation/StopAnimation were requested
// Helper functions
void _UpdateCompressedSize();
HRESULT _CreateBrandBand();
HRESULT _LoadBrandingBitmap();
void _DrawBranding(HDC hdc);
int _GetLinksExtent();
void _OnTimer(WPARAM id);
void _StartAnimation();
void _StopAnimation();
static void _InitGlobals();
static void _InitBrandContexts();
static void _InitBrandContext(BRANDCONTEXT* pbc, LPCTSTR pszBrandLeadIn, LPCTSTR pszBrandHeight,
LPCTSTR pszBrandBitmap, LPCTSTR pszBitmap, int idBrandBitmap);
HRESULT _ConnectToBrwsrWnd(IUnknown* punk);
HRESULT _ConnectToBrwsrConnectionPoint(BOOL fConnect);
static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
friend void CBrandBand_CleanUp();
friend void Brand_InitBrandContexts();
static void _GetBrandContextHeight(BRANDCONTEXT* pbc, LPCTSTR pszBrandLeadIn, LPCTSTR pszBrandHeight,
LPCTSTR pszBrandBitmap, LPCTSTR pszBitmap, int idBrandBitmap);
private:
};
#define SUPERCLASS CToolBand
#define BM_BANDINFOCHANGED (WM_USER + 1)
#ifdef DEBUG
extern unsigned long DbStreamTell(IStream *pstm);
#else
#define DbStreamTell(pstm) ((ULONG) 0)
#endif
extern HRESULT VariantClearLazy(VARIANTARG *pvarg);
#define ANIMATION_TIMER 5678
#define MICROBITMAPID() (IDB_IEMICROBRAND)
#define SMALLBITMAPID() (IDB_IESMBRAND)
#define LARGEBITMAPID() (IDB_IEBRAND)
BRANDCONTEXT CBrandBand::s_bcWebMicro = {NULL}; // BrandContext for the micro web view bitmap
BRANDCONTEXT CBrandBand::s_bcWebSmall = {NULL}; // BrandContext for the small web view bitmap
BRANDCONTEXT CBrandBand::s_bcWebLarge = {NULL}; // BrandContext for the large web view bitmap
BRANDCONTEXT CBrandBand::s_bcShellSmall = {NULL}; // BrandContext for the small shell view bitmap
BRANDCONTEXT CBrandBand::s_bcShellLarge = {NULL}; // BrandContext for the large shell view bitmap
// The heights of the bitmaps (each frame!) stored is this module's resources
// ** NOTE **
// If you change the animated brands that are stored in browseui:
// MAKE SURE THESE HEIGHTS are correct!!
// ** - dsheldon - **
#define BRANDHEIGHT_WEBLARGE 38
#define BRANDHEIGHT_WEBSMALL 26
#define BRANDHEIGHT_WEBMICRO 22
HDC CBrandBand::s_hdc = NULL;
BOOL g_fUseMicroBrand = TRUE;
UINT g_cySmBrand = 0;
static const TCHAR szRegKeyIE20[] = TEXT("SOFTWARE\\Microsoft\\Internet Explorer\\Main");
static const TCHAR szValueLargeBitmap[] = TEXT("BigBitmap");
static const TCHAR szValueSmallBitmap[] = TEXT("SmallBitmap");
static const TCHAR szValueBrandBitmap[] = TEXT("BrandBitmap");
static const TCHAR szValueBrandHeight[] = TEXT("BrandHeight");
static const TCHAR szValueBrandLeadIn[] = TEXT("BrandLeadIn");
static const TCHAR szValueSmBrandBitmap[] = TEXT("SmBrandBitmap");
static const TCHAR szValueSmBrandHeight[] = TEXT("SmBrandHeight");
static const TCHAR szValueSmBrandLeadIn[] = TEXT("SmBrandLeadIn");
static const TCHAR szValueSHLargeBitmap[] = TEXT("SHBigBitmap");
static const TCHAR szValueSHSmallBitmap[] = TEXT("SHSmallBitmap");
static const TCHAR szValueSHBrandBitmap[] = TEXT("SHBrandBitmap");
static const TCHAR szValueSHBrandHeight[] = TEXT("SHBrandHeight");
static const TCHAR szValueSHBrandLeadIn[] = TEXT("SHBrandLeadIn");
static const TCHAR szValueSHSmBrandBitmap[] = TEXT("SHSmBrandBitmap");
static const TCHAR szValueSHSmBrandHeight[] = TEXT("SHSmBrandHeight");
static const TCHAR szValueSHSmBrandLeadIn[] = TEXT("SHSmBrandLeadIn");
static const TCHAR szRegKeyCoolbar[] = TEXT("Software\\Microsoft\\Internet Explorer\\Toolbar");
// NOTE: szRegKeyCoolbar is duplicated from itbar.cpp!
void CBrandBand_CleanUp()
{
if (CBrandBand::s_hdc)
{
HDC hdcT;
HBITMAP hbmT, * pbmp = NULL;
// pick out any old bitmap to flush dc with
if (CBrandBand::s_bcWebLarge.hbm)
pbmp = &CBrandBand::s_bcWebLarge.hbm;
else if (CBrandBand::s_bcWebSmall.hbm)
pbmp = &CBrandBand::s_bcWebSmall.hbm;
// We need to get rid of the branding bitmap from the s_hdc
// before we delete it else we leak. Do this the hard way since
// we don't have a stock bitmap available to us.
if (pbmp)
{
hdcT = CreateCompatibleDC(NULL);
if (hdcT)
{
hbmT = (HBITMAP)SelectObject(hdcT, *pbmp);
SelectObject(CBrandBand::s_hdc, hbmT);
SelectObject(hdcT, hbmT);
DeleteDC(hdcT);
}
}
DeleteDC(CBrandBand::s_hdc);
}
// no palette to delete as we use the global one..
// delete the shared palette
if (CBrandBand::s_bcWebSmall.hbm)
DeleteObject(CBrandBand::s_bcWebSmall.hbm);
if (CBrandBand::s_bcWebLarge.hbm)
DeleteObject(CBrandBand::s_bcWebLarge.hbm);
if (!g_fUseMicroBrand) {
if (CBrandBand::s_bcShellSmall.hbm)
DeleteObject(CBrandBand::s_bcShellSmall.hbm);
if (CBrandBand::s_bcShellLarge.hbm)
DeleteObject(CBrandBand::s_bcShellLarge.hbm);
} else {
if (CBrandBand::s_bcWebMicro.hbm)
DeleteObject(CBrandBand::s_bcWebMicro.hbm);
}
}
/////////////////////////////////////////////////////////////////////////////
// CBrandBand
/////////////////////////////////////////////////////////////////////////////
HRESULT CBrandBand_CreateInstance( IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi)
{
// Aggregation checking is handled in class factory
HRESULT hr;
*ppunk = NULL;
CBrandBand * p = new CBrandBand();
if (p != NULL)
{
*ppunk = SAFECAST(p, IDeskBand *);
hr = S_OK;
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
CBrandBand::CBrandBand() : SUPERCLASS()
{
ASSERT(_fAnimating == FALSE);
ASSERT(_hwnd == NULL);
_pbc = &s_bcShellLarge;
}
CBrandBand::~CBrandBand()
{
ASSERT(!_pdie || !_pwb2 || !_pbs);
if (IsWindow(_hwnd))
{
DestroyWindow(_hwnd);
}
}
// IUnknown::QueryInterface
HRESULT CBrandBand::QueryInterface(REFIID riid, void **ppvObj)
{
if (IsEqualIID(riid, IID_IWinEventHandler))
{
*ppvObj = SAFECAST(this, IWinEventHandler*);
}
else if (IsEqualIID(riid, IID_IPersistStream))
{
*ppvObj = SAFECAST(this, IPersistStream*);
}
else if (IsEqualIID(riid, IID_IDispatch))
{
*ppvObj = SAFECAST(this, IDispatch*);
}
else
{
return SUPERCLASS::QueryInterface(riid, ppvObj);
}
AddRef();
return S_OK;
}
// IDockingWindow::SetSite
HRESULT CBrandBand::SetSite(IUnknown * punkSite)
{
if (_pdie || _pwb2 || _pbs)
_ConnectToBrwsrWnd(NULL); // On-connect from Browser Window.
// Make sure we proffer the service only once
// This is important since we get created multiple times,
IUnknown *punk = NULL;
// Check if we need to revoke our service, or if our service was already proffered by
// another instance of CBrandBand
if ((!punkSite && _dwCookieServiceBrandBand) ||
(punkSite && FAILED(IUnknown_QueryService(punkSite, SID_SBrandBand, IID_IUnknown, (void **)&punk))))
{
// Proffer or Revoke BrandBand service as appropriate
IUnknown_ProfferService(punkSite ? punkSite : _punkSite,
SID_SBrandBand,
punkSite ? SAFECAST(this, IServiceProvider *) : NULL,
&_dwCookieServiceBrandBand);
// Failure here does not require special handling
}
ATOMICRELEASE(punk);
SUPERCLASS::SetSite(punkSite);
if (punkSite)
{
_CreateBrandBand();
// This call will fail if the host doesn't have a Browser Window.
_ConnectToBrwsrWnd(punkSite);
}
return S_OK;
}
// IDeskBand::GetBandInfo
HRESULT CBrandBand::GetBandInfo(DWORD dwBandID, DWORD fViewMode, DESKBANDINFO* pdbi)
{
_dwBandID = dwBandID;
_fVertical = ((fViewMode & DBIF_VIEWMODE_VERTICAL) != 0);
_LoadBrandingBitmap();
pdbi->dwModeFlags = DBIMF_FIXEDBMP;
if (!_fMinAlways)
pdbi->dwModeFlags |= DBIMF_VARIABLEHEIGHT;
int cxWidth = _fTheater ? CX_FLOATERSHOWN : _GetLinksExtent();
pdbi->ptMinSize.x = max(s_bcWebSmall.cxBrandExtent, max(s_bcShellSmall.cxBrandExtent, cxWidth));
pdbi->ptMaxSize.x = max(s_bcWebLarge.cxBrandExtent, max(s_bcShellLarge.cxBrandExtent, cxWidth));
pdbi->ptMaxSize.y = max(s_bcWebLarge.cyBrand, s_bcShellLarge.cyBrand);
if (g_fUseMicroBrand)
pdbi->ptMinSize.y = s_bcWebMicro.cyBrand;
else
pdbi->ptMinSize.y = max(s_bcWebSmall.cyBrand, s_bcShellSmall.cyBrand);
pdbi->ptIntegral.y = -1;
return S_OK;
}
// IWinEventHandler::OnWinEvent
HRESULT CBrandBand::OnWinEvent(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres)
{
*plres = 0;
switch (uMsg)
{
case WM_WININICHANGE:
if (SHIsExplorerIniChange(wParam, lParam))
{
_InitBrandContexts();
InvalidateRect(_hwnd, NULL, TRUE);
}
*plres = SendMessage(_hwnd, uMsg, wParam, lParam);
break;
}
return S_OK;
}
// IWinEventHandler::IsWindowOwner
HRESULT CBrandBand::IsWindowOwner(HWND hwnd)
{
if (hwnd == _hwnd)
return S_OK;
return S_FALSE;
}
// IPersistStream::GetClassID
HRESULT CBrandBand::GetClassID(CLSID * pClassID)
{
*pClassID = CLSID_BrandBand;
return S_OK;
}
// IPersistStream::Load
HRESULT CBrandBand::Load(IStream *pstm)
{
return S_OK;
}
// IPersistStream::Load
HRESULT CBrandBand::Save(IStream *pstm, BOOL fClearDirty)
{
return S_OK;
}
#define ANIMATION_PERIOD 30
#define ANIMATION_PERIOD_FAST 15
// IDispatch::Invoke
HRESULT CBrandBand::Invoke
(
DISPID dispidMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS * pdispparams,
VARIANT * pvarResult,
EXCEPINFO * pexcepinfo,
UINT * puArgErr
)
{
ASSERT(pdispparams);
if (!pdispparams)
return E_INVALIDARG;
switch (dispidMember)
{
case DISPID_DOWNLOADBEGIN:
{
_StartAnimation();
break;
}
case DISPID_DOWNLOADCOMPLETE:
{
_StopAnimation();
break;
}
default:
return E_INVALIDARG;
}
return S_OK;
}
void CBrandBand::_InitGlobals()
{
if (!s_hdc) {
ENTERCRITICAL;
if (!s_hdc)
{
s_hdc = CreateCompatibleDC(NULL);
if (s_hdc && GetDeviceCaps(s_hdc, RASTERCAPS) & RC_PALETTE)
{
// share the global palette ....
ASSERT( g_hpalHalftone );
s_bcWebMicro.hpal = g_hpalHalftone;
s_bcWebSmall.hpal = s_bcShellSmall.hpal = g_hpalHalftone;
s_bcWebLarge.hpal = s_bcShellLarge.hpal = g_hpalHalftone;
}
}
LEAVECRITICAL;
}
}
HRESULT CBrandBand::_CreateBrandBand()
{
HRESULT hr;
ASSERT(_hwndParent); // Call us after SetSite()
if (!_hwndParent)
{
// The caller hasn't called SetSite(), so we can't
// create our window because we can't find out our parent's
// HWND.
return E_FAIL;
}
// create branding window
_hwnd = SHCreateWorkerWindow(WndProc, _hwndParent, 0, WS_CHILD, NULL, this);
if (_hwnd)
{
_InitGlobals();
hr = S_OK;
}
else
{
hr = E_OUTOFMEMORY;
TraceMsg(TF_ERROR, "CBrandBand::_CreateBrandBand() - Could not create Brand Band!");
}
return hr;
}
void Brand_InitBrandContexts()
{
CBrandBand::_InitGlobals();
CBrandBand::_InitBrandContexts();
}
void CBrandBand::_InitBrandContexts()
{
// note: these calls set g_fUseMicroBrand
_GetBrandContextHeight(&s_bcWebSmall, szValueSmBrandLeadIn, szValueSmBrandHeight,
szValueSmBrandBitmap, szValueSmallBitmap, SMALLBITMAPID());
_GetBrandContextHeight(&s_bcWebLarge, szValueBrandLeadIn, szValueBrandHeight,
szValueBrandBitmap, szValueLargeBitmap, LARGEBITMAPID());
// if no third party brands found
if (g_fUseMicroBrand) {
// init micro brand
_GetBrandContextHeight(&s_bcWebMicro, NULL, NULL,
NULL, NULL, MICROBITMAPID());
} else {
// init shell brands
_GetBrandContextHeight(&s_bcShellSmall, szValueSHSmBrandLeadIn, szValueSHSmBrandHeight,
szValueSHSmBrandBitmap, szValueSHSmallBitmap, SMALLBITMAPID());
_GetBrandContextHeight(&s_bcShellLarge, szValueSHBrandLeadIn, szValueSHBrandHeight,
szValueSHBrandBitmap, szValueSHLargeBitmap, LARGEBITMAPID());
}
}
/****************************************************************************
CBrandBand::_GetBrandContextHeight
Sets the cyBrand member of the supplied brand context. This function
uses the height information stored in the registry if it is available.
If an alternate source for bitmaps is found and the height information
is available in the registry, it is assumed we will not be using our
micro brand (g_fUseMicroBrand = FALSE).
Otherwise, it is assumed that no custom bitmaps are available and
the cyBrand will be set to constant values representing the height
of our standard branding.
Note that if it appears that there are custom bitmaps available but the
height cannot be read, we will attempt to read the custom bitmaps and
determine the height that way (by delegating to _InitBrandContext)
****************************************************************************/
void CBrandBand::_GetBrandContextHeight(BRANDCONTEXT* pbc, LPCTSTR pszBrandLeadIn, LPCTSTR pszBrandHeight,
LPCTSTR pszBrandBitmap, LPCTSTR pszBitmap, int idBrandBitmap)
{
HKEY hKey;
DWORD cbData;
DWORD dwType;
BOOL fThirdPartyBitmap = FALSE;
TCHAR szScratch[MAX_PATH];
szScratch[0] = 0;
// try to determine if there is a third party bitmap available for the specified
// brand... Check if the anitmated bitmap exists
if (pszBrandBitmap && ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, szRegKeyCoolbar, 0, KEY_QUERY_VALUE, &hKey))
{
// See if an alternate file was specified for the animated bmp
cbData = sizeof(szScratch);
if ((ERROR_SUCCESS == SHQueryValueEx(hKey, pszBrandBitmap, NULL, &dwType,
(LPBYTE)szScratch, &cbData)))
{
if (szScratch[0] != 0)
fThirdPartyBitmap = TRUE;
}
// It appears there are third party bitmaps
// try to find the height of the animated bitmap
if (pszBrandHeight && fThirdPartyBitmap)
{
cbData = sizeof(pbc->cyBrand);
if (ERROR_SUCCESS == SHQueryValueEx(hKey, pszBrandHeight, NULL, &dwType,
(LPBYTE)&pbc->cyBrand, &cbData))
{
// Third party brands probably exist
g_fUseMicroBrand = FALSE;
}
else
{
// In this case, we know there should be 3rd party bitmaps but no
// height was specified in the registry. We have to bite the bullet
// and load the bitmaps now: Delegate to _InitBrandContext()
_InitBrandContext(pbc, pszBrandLeadIn, pszBrandHeight,
pszBrandBitmap, pszBitmap, idBrandBitmap);
}
}
RegCloseKey(hKey);
}
if (!fThirdPartyBitmap && pszBitmap &&
ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, szRegKeyCoolbar, 0, KEY_QUERY_VALUE, &hKey))
{
// See if an alternate file was specified for the static bmp
cbData = sizeof(szScratch);
if ((ERROR_SUCCESS == SHQueryValueEx(hKey, pszBitmap, NULL, &dwType,
(LPBYTE)szScratch, &cbData)))
{
if (szScratch[0] != 0)
{
// In this case, we know there is a 3rd party static bitmap but no
// animated bitmap was specified in the registry. We have to bite the bullet
// and load the bitmaps now: Delegate to _InitBrandContext()
fThirdPartyBitmap = TRUE;
_InitBrandContext(pbc, pszBrandLeadIn, pszBrandHeight,
pszBrandBitmap, pszBitmap, idBrandBitmap);
}
}
RegCloseKey(hKey);
}
// If we didn't find any third party bitmaps, we need to set it the height
// to the size of the bitmaps in this module's resources
if (!fThirdPartyBitmap)
{
// Set the height based on which bitmap ID is requested
switch (idBrandBitmap)
{
case IDB_IEMICROBRAND:
pbc->cyBrand = BRANDHEIGHT_WEBMICRO;
break;
case IDB_IESMBRAND:
pbc->cyBrand = BRANDHEIGHT_WEBSMALL;
break;
case IDB_IEBRAND:
pbc->cyBrand = BRANDHEIGHT_WEBLARGE;
break;
default:
// bad ID passed in!
ASSERT(FALSE);
}
}
}
void CBrandBand::_InitBrandContext(BRANDCONTEXT* pbc, LPCTSTR pszBrandLeadIn, LPCTSTR pszBrandHeight,
LPCTSTR pszBrandBitmap, LPCTSTR pszBitmap, int idBrandBitmap)
{
ENTERCRITICAL;
HKEY hKey = NULL;
DWORD dwType = 0;
TCHAR szScratch[MAX_PATH];
DWORD dwcbData;
BOOL fBitmapInvalid = !pbc->hbm;
LPTSTR pszNewBitmap = NULL;
LPTSTR pszOldBitmap = pbc->pszBitmap;
HBITMAP hbmp = NULL;
BOOL fExternalAnimatedBitmap = FALSE;
BOOL fUseWindowsXPBranding = FALSE;
// process animated brand bitmap
// see if the location spec for the bitmap has been changed
if (pszBrandBitmap && ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, szRegKeyCoolbar, 0, KEY_QUERY_VALUE, &hKey))
{
dwcbData = SIZEOF(szScratch);
if ((ERROR_SUCCESS == SHQueryValueEx(hKey, pszBrandBitmap, NULL, &dwType,
(LPBYTE)szScratch, &dwcbData)))
{
pszNewBitmap = szScratch;
fExternalAnimatedBitmap = TRUE;
}
}
if (!(pszNewBitmap == pszOldBitmap || (pszNewBitmap && pszOldBitmap && !lstrcmpi(pszNewBitmap, pszOldBitmap))))
fBitmapInvalid = TRUE;
if (fBitmapInvalid) {
Str_SetPtr(&pbc->pszBitmap, pszNewBitmap);
if (pszNewBitmap) {
if (pszNewBitmap[0]) { // not empty string
hbmp = (HBITMAP) LoadImage(NULL, szScratch, IMAGE_BITMAP, 0, 0,
LR_DEFAULTSIZE | LR_CREATEDIBSECTION | LR_LOADFROMFILE);
}
}
if (!hbmp)
{
if (hKey != NULL)
{
RegCloseKey(hKey);
hKey = NULL;
}
HINSTANCE hInstDll = HINST_THISDLL;
INT iBitmapID = idBrandBitmap;
if (GetUIVersion() > 5)
{
BOOL bHighColor = (SHGetCurColorRes() > 8) ? TRUE : FALSE;
if (idBrandBitmap == MICROBITMAPID())
{
if (bHighColor)
iBitmapID = IDB_BRAND_BITMAP_MICRO;
else
iBitmapID = IDB_BRAND256_BITMAP_MICRO;
fUseWindowsXPBranding = TRUE;
}
else if (idBrandBitmap == SMALLBITMAPID())
{
if (bHighColor)
iBitmapID = IDB_BRAND_BITMAP_SMALL;
else
iBitmapID = IDB_BRAND256_BITMAP_SMALL;
fUseWindowsXPBranding = TRUE;
}
else if (idBrandBitmap == LARGEBITMAPID())
{
if (bHighColor)
iBitmapID = IDB_BRAND_BITMAP_LARGE;
else
iBitmapID = IDB_BRAND256_BITMAP_LARGE;
fUseWindowsXPBranding = TRUE;
}
if (fUseWindowsXPBranding)
{
hInstDll = GetModuleHandle (TEXT("shell32.dll"));
}
}
hbmp = (HBITMAP) LoadImage(hInstDll, MAKEINTRESOURCE(iBitmapID), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
} else
g_fUseMicroBrand = FALSE;
if (!hbmp) goto ErrorDone;
if (pbc->hbm) DeleteObject(pbc->hbm);
pbc->hbm = hbmp;
// set the background to be the first pixel
SelectObject(s_hdc, pbc->hbm);
pbc->clrBkAnim = GetPixel(s_hdc, 0, 0);
if (fUseWindowsXPBranding)
{
pbc->clrBkStat = pbc->clrBkAnim;
}
DIBSECTION dib;
GetObject(pbc->hbm, sizeof(DIBSECTION), &dib);
pbc->cxBrandExtent = dib.dsBm.bmWidth;
pbc->cyBrandExtent = dib.dsBm.bmHeight;
dwcbData = sizeof(DWORD);
// APPCOMPAT:: hkey is not setup when the second instance calls in
if (!hKey || (ERROR_SUCCESS != SHQueryValueEx(hKey, pszBrandHeight, NULL, &dwType,
(LPBYTE)&pbc->cyBrand, &dwcbData)))
pbc->cyBrand = pbc->cxBrandExtent;
#define EXTERNAL_IMAGE_OFFSET 4
#define INTERNAL_IMAGE_OFFSET 0
if (!hKey || (ERROR_SUCCESS != SHQueryValueEx(hKey, pszBrandLeadIn, NULL, &dwType,
(LPBYTE)&pbc->cyBrandLeadIn, &dwcbData)))
{
#ifndef UNIX
if (fExternalAnimatedBitmap)
// use old 4-image offset for back compat
pbc->cyBrandLeadIn = EXTERNAL_IMAGE_OFFSET;
else
pbc->cyBrandLeadIn = INTERNAL_IMAGE_OFFSET;
#else
// IEUNIX : We use a different branding bitmap.
pbc->cyBrandLeadIn = EXTERNAL_IMAGE_OFFSET;
#endif
}
pbc->cyBrandLeadIn *= pbc->cyBrand;
}
if (hKey)
RegCloseKey(hKey);
// process the static bitmap
pszNewBitmap = NULL;
pszOldBitmap = pbc->pszStaticBitmap;
hbmp = NULL;
// see if the location spec for the bitmap has been changed
dwcbData = SIZEOF(szScratch);
if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, szRegKeyCoolbar, pszBitmap, &dwType, szScratch, &dwcbData))
{
pszNewBitmap = szScratch;
}
if (!(pszNewBitmap == pszOldBitmap || (pszNewBitmap && pszOldBitmap && !lstrcmpi(pszNewBitmap, pszOldBitmap))))
fBitmapInvalid = TRUE;
if (fBitmapInvalid) {
Str_SetPtr(&pbc->pszStaticBitmap, pszNewBitmap);
if (pszNewBitmap) {
if (pszNewBitmap[0]) { // not empty string
hbmp = (HBITMAP) LoadImage(NULL, szScratch, IMAGE_BITMAP, 0, 0,
LR_DEFAULTSIZE | LR_CREATEDIBSECTION | LR_LOADFROMFILE);
}
}
if (hbmp) {
DIBSECTION dib;
HDC hdcOld = CreateCompatibleDC(s_hdc);
if (hdcOld)
{
SelectObject(s_hdc, pbc->hbm);
GetObject(hbmp, sizeof(DIBSECTION), &dib);
SelectObject(hdcOld, hbmp);
// Set background to color of first pixel
pbc->clrBkStat = GetPixel(hdcOld, 0, 0);
StretchBlt(s_hdc, 0, 0, pbc->cxBrandExtent, pbc->cyBrand, hdcOld, 0, 0,
dib.dsBm.bmWidth, dib.dsBm.bmHeight, SRCCOPY);
DeleteDC(hdcOld);
}
DeleteObject(hbmp);
// If there was a custom brand, we can't use our micro brand
g_fUseMicroBrand = FALSE;
}
if (pbc == &s_bcShellSmall)
g_cySmBrand = pbc->cyBrand;
}
ErrorDone:
LEAVECRITICAL;
}
void CBrandBand::_UpdateCompressedSize()
{
RECT rc;
BOOL fCompressed = FALSE;
BRANDCONTEXT *pbcOld = _pbc;
GetClientRect(_hwnd, &rc);
if (RECTHEIGHT(rc) < max(s_bcWebLarge.cyBrand, s_bcShellLarge.cyBrand)) {
if (g_fUseMicroBrand && RECTHEIGHT(rc) < s_bcWebSmall.cyBrand)
{
if (s_bcWebMicro.hbm == NULL)
{
_InitBrandContext(&s_bcWebMicro, NULL, NULL,
NULL, NULL, MICROBITMAPID());
}
_pbc = &s_bcWebMicro;
}
else
{
if (_fShellView)
{
if (s_bcShellSmall.hbm == NULL)
{
if (g_fUseMicroBrand)
{
// In this case, the shell and web bitmaps are always the same;
// load the web bitmap and use it for the shell also
if (s_bcWebSmall.hbm == NULL)
{
_InitBrandContext(&s_bcWebSmall, szValueSmBrandLeadIn, szValueSmBrandHeight,
szValueSmBrandBitmap, szValueSmallBitmap, SMALLBITMAPID());
}
s_bcShellSmall = s_bcWebSmall;
}
else
{
// We have different web and shell bitmaps; load the shell one
_InitBrandContext(&s_bcShellSmall, szValueSHSmBrandLeadIn, szValueSHSmBrandHeight,
szValueSHSmBrandBitmap, szValueSHSmallBitmap, SMALLBITMAPID());
}
}
_pbc = &s_bcShellSmall;
}
else
{
// We are in web view mode
if (s_bcWebSmall.hbm == NULL)
{
_InitBrandContext(&s_bcWebSmall, szValueSmBrandLeadIn, szValueSmBrandHeight,
szValueSmBrandBitmap, szValueSmallBitmap, SMALLBITMAPID());
}
_pbc = &s_bcWebSmall;
}
}
}
else
{
if (_fShellView)
{
if (s_bcShellLarge.hbm == NULL)
{
if (g_fUseMicroBrand)
{
// Shell and Web bitmaps are the same. Load the web one and copy it
if (s_bcWebLarge.hbm == NULL)
{
_InitBrandContext(&s_bcWebLarge, szValueBrandLeadIn, szValueBrandHeight,
szValueBrandBitmap, szValueLargeBitmap, LARGEBITMAPID());
}
s_bcShellLarge = s_bcWebLarge;
}
else
{
// Need to load the shell bitmap separately
_InitBrandContext(&s_bcShellLarge, szValueSHBrandLeadIn, szValueSHBrandHeight,
szValueSHBrandBitmap, szValueSHLargeBitmap, LARGEBITMAPID());
}
}
_pbc = &s_bcShellLarge;
}
else
{
// We're in web view
if (s_bcWebLarge.hbm == NULL)
{
_InitBrandContext(&s_bcWebLarge, szValueBrandLeadIn, szValueBrandHeight,
szValueBrandBitmap, szValueLargeBitmap, LARGEBITMAPID());
}
_pbc = &s_bcWebLarge;
}
}
if (_pbc != pbcOld) {
MSG msg;
_yOrg = 0;
InvalidateRect(_hwnd, NULL, TRUE);
if (!PeekMessage(&msg, _hwnd, BM_BANDINFOCHANGED, BM_BANDINFOCHANGED, PM_NOREMOVE))
PostMessage(_hwnd, BM_BANDINFOCHANGED, 0, 0);
}
}
HRESULT CBrandBand::_LoadBrandingBitmap()
{
if (_pbc->hbm)
return S_OK; // Nothing to do, already loaded.
_yOrg = 0;
_InitBrandContexts();
return(S_OK);
}
void CBrandBand::_DrawBranding(HDC hdc)
{
HPALETTE hpalPrev;
RECT rcPaint;
COLORREF clrBk = _fAnimating? _pbc->clrBkAnim : _pbc->clrBkStat;
int x, y, cx, cy;
int yOrg = 0;
DWORD dwRop = SRCCOPY;
if (_fAnimating)
yOrg = _yOrg;
if (_pbc->hpal)
{
// select in our palette so the branding will get mapped to
// whatever the current system palette is. Note we do not
// pass FALSE, so we will no actually select this palette into
// system palette FG. Otherwise the branding will flash the
// palette
hpalPrev = SelectPalette(hdc, _pbc->hpal, TRUE);
RealizePalette(hdc);
}
GetClientRect(_hwnd, &rcPaint);
x = rcPaint.left;
cx = RECTWIDTH(rcPaint);
y = rcPaint.top;
cy = RECTHEIGHT(rcPaint);
if (cx > _pbc->cxBrandExtent)
{
RECT rc = rcPaint;
int dx = ((cx - _pbc->cxBrandExtent) / 2) + 1;
rc.right = rc.left + dx;
SHFillRectClr(hdc, &rc, clrBk);
rc.right = rcPaint.right;
rc.left = rc.right - dx;
SHFillRectClr(hdc, &rc, clrBk);
}
if (cy > _pbc->cyBrand)
{
RECT rc = rcPaint;
int dy = ((cy - _pbc->cyBrand) / 2) + 1;
rc.bottom = rc.top + dy;
SHFillRectClr(hdc, &rc, clrBk);
rc.bottom = rcPaint.bottom;
rc.top = rc.bottom - dy;
SHFillRectClr(hdc, &rc, clrBk);
}
// center it
if (cx > _pbc->cxBrandExtent)
x += (cx - _pbc->cxBrandExtent) / 2;
if (cy > _pbc->cyBrand)
y += (cy - _pbc->cyBrand) / 2;
//
// To prevent the transform from flipping
// calculations should be based on the bm width
// when the DC is Right-To-Left mirrored and
// not to flip the IE logo bitmap [samera]
//
if (IS_WINDOW_RTL_MIRRORED(_hwnd))
{
// Actual width
cx = _pbc->cxBrandExtent;
// Don't flip the logo here
dwRop |= DONTMIRRORBITMAP;
}
ENTERCRITICAL;
SelectObject(s_hdc, _pbc->hbm);
BitBlt(hdc, x, y, cx, _pbc->cyBrand, s_hdc, 0, yOrg, dwRop);
LEAVECRITICAL;
if (_pbc->hpal)
{
// reselect in the old palette
SelectPalette(hdc, hpalPrev, TRUE);
RealizePalette(hdc);
}
}
int CBrandBand::_GetLinksExtent()
{
return 0x26;
}
void CBrandBand::_OnTimer(WPARAM id)
{
_yOrg += _pbc->cyBrand;
if (_yOrg >= _pbc->cyBrandExtent)
_yOrg = _pbc->cyBrandLeadIn;
RedrawWindow(_hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}
void CBrandBand::_StartAnimation()
{
// We need to be called on the UI thread, as we are not thread-safe.
ASSERT(GetWindowThreadProcessId(_hwnd, NULL) == GetCurrentThreadId());
if (++_lAnimateCount == 1)
{
// The timer does a invalidate of _hwnd which in cases
// of no toolbar showing caused the entire desktop to
// repaint and repaint and...
if (_hwnd)
{
if (GetUIVersion() > 5)
SetTimer(_hwnd, ANIMATION_TIMER, ANIMATION_PERIOD, NULL);
else
SetTimer(_hwnd, ANIMATION_TIMER, ANIMATION_PERIOD_FAST, NULL);
}
_yOrg = 0;
_fAnimating = TRUE;
IUnknown_Exec(_punkSite, &CGID_Theater, THID_ACTIVATE, 0, NULL, NULL);
}
}
void CBrandBand::_StopAnimation()
{
// We need to be called on the UI thread, as we are not thread-safe.
ASSERT(GetWindowThreadProcessId(_hwnd, NULL) == GetCurrentThreadId());
if (--_lAnimateCount == 0)
{
_fAnimating = FALSE;
KillTimer(_hwnd, ANIMATION_TIMER);
InvalidateRect(_hwnd, NULL, FALSE);
UpdateWindow(_hwnd);
IUnknown_Exec(_punkSite, &CGID_Theater, THID_DEACTIVATE, 0, NULL, NULL);
}
}
// The IUnknown parameter needs to point to an object that supports the
// IBrowserService and IWebBrowserApp interfaces.
HRESULT CBrandBand::_ConnectToBrwsrWnd(IUnknown * punk)
{
HRESULT hr = S_OK;
if (_pdie)
{
// Remove the tie from the AddressBand to the Browser Window
_ConnectToBrwsrConnectionPoint(FALSE);
ATOMICRELEASE(_pdie);
}
ATOMICRELEASE(_pwb2);
ATOMICRELEASE(_pbs);
if (punk)
{
// Tie the AddressBand to the Browser Window passed in.
IServiceProvider* psp = NULL;
hr = punk->QueryInterface(IID_IServiceProvider, (void **)&psp);
if (SUCCEEDED(hr))
{
// NOTE: We are either a Toolbar, in which case _pbs is valid
// and _pwb2 is NULL, or we are a Toolband and _pbs is
// NULL and _pwb2 is valid. Both will be NULL when the
// Toolband has yet to create a Browser Window.
if (FAILED(psp->QueryService(SID_STopLevelBrowser, IID_IBrowserService, (void**)&_pbs)))
hr = psp->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void**)&_pwb2);
hr = psp->QueryService(SID_SWebBrowserApp, IID_IWebBrowserApp, (void**)&_pdie);
psp->Release();
if (_pdie && (_pwb2 || _pbs))
_ConnectToBrwsrConnectionPoint(TRUE);
else
{
ATOMICRELEASE(_pdie);
ATOMICRELEASE(_pwb2);
ATOMICRELEASE(_pbs);
hr = E_FAIL;
}
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// Connect to Browser Window's ConnectionPoint that will provide events
// to let us keep up to date.
/////////////////////////////////////////////////////////////////////////////
HRESULT CBrandBand::_ConnectToBrwsrConnectionPoint(BOOL fConnect)
{
return ConnectToConnectionPoint(SAFECAST(this, IDeskBand*),
DIID_DWebBrowserEvents, fConnect, _pdie, &_dwcpCookie, NULL);
}
LRESULT CALLBACK CBrandBand::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CBrandBand * ptc= (CBrandBand *)GetWindowPtr0(hwnd); // GetWindowLong(hwnd, 0)
switch (uMsg)
{
case WM_TIMER:
ptc->_OnTimer(wParam);
break;
case WM_ERASEBKGND:
{
HDC hdc = (HDC)wParam;
RECT rc;
GetClientRect(hwnd, &rc);
SHFillRectClr(hdc, &rc, ptc->_fAnimating ? ptc->_pbc->clrBkAnim : ptc->_pbc->clrBkStat);
break;
}
case WM_PAINT:
ptc->_UpdateCompressedSize();
if (GetUpdateRect(hwnd, NULL, FALSE))
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
ptc->_DrawBranding(ps.hdc);
EndPaint(hwnd, &ps);
}
break;
case WM_SIZE:
InvalidateRect(ptc->_hwnd, NULL, TRUE);
ptc->_UpdateCompressedSize();
break;
case BM_BANDINFOCHANGED:
ptc->_BandInfoChanged();
break;
default:
return DefWindowProcWrap(hwnd, uMsg, wParam, lParam);
}
return 0;
}
HRESULT CBrandBand::Exec(const GUID *pguidCmdGroup,
DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
{
HRESULT hr = OLECMDERR_E_UNKNOWNGROUP; // assume failure
if (pguidCmdGroup) {
if (IsEqualGUID(CGID_PrivCITCommands, *pguidCmdGroup))
{
hr = S_OK;
switch (nCmdID)
{
case CITIDM_BRANDSIZE:
if (pvarargIn && pvarargIn->vt == VT_I4) {
BOOL fMin = BOOLIFY(pvarargIn->lVal);
if (fMin != BOOLIFY(_fMinAlways)) {
_fMinAlways = fMin;
_BandInfoChanged();
}
}
break;
case CITIDM_ONINTERNET:
switch (nCmdexecopt)
{
case CITE_SHELL:
_fShellView = TRUE;
if (_pbs)
{
LPITEMIDLIST pidl;
hr = _pbs->GetPidl(&pidl);
if (SUCCEEDED(hr))
{
// We may really be an IShellView for an internet NSE (like FTP)
// Find out if they want this feature
_fShellView = !IsBrowserFrameOptionsPidlSet(pidl, BFO_USE_IE_LOGOBANDING);
ILFree(pidl);
}
}
break;
case CITE_INTERNET:
_fShellView = FALSE;
break;
}
_UpdateCompressedSize();
break;
case CITIDM_THEATER:
switch(nCmdexecopt) {
case THF_ON:
_fTheater = TRUE;
break;
case THF_OFF:
_fTheater = FALSE;
break;
default:
goto Bail;
}
_BandInfoChanged();
break;
case CITIDM_GETDEFAULTBRANDCOLOR:
if (pvarargOut && pvarargOut->vt == VT_I4)
pvarargOut->lVal = g_fUseMicroBrand ? s_bcWebSmall.clrBkStat : s_bcShellSmall.clrBkStat;
break;
}
}
else if (IsEqualGUID(CGID_BrandCmdGroup, *pguidCmdGroup))
{
hr = S_OK;
switch (nCmdID)
{
case CBRANDIDM_STARTGLOBEANIMATION:
_StartAnimation();
break;
case CBRANDIDM_STOPGLOBEANIMATION:
_StopAnimation();
break;
default:
hr = OLECMDERR_E_NOTSUPPORTED;
break;
}
}
}
Bail:
return hr;
}
// IQueryService implementation
HRESULT CBrandBand::QueryService(REFGUID guidService, REFIID riid, void ** ppvObj)
{
HRESULT hres = E_NOTIMPL;
if (IsEqualIID(guidService, SID_SBrandBand))
{
hres = QueryInterface(riid, ppvObj);
}
else
{
hres = CToolBand::QueryService(guidService, riid, ppvObj);
}
return hres;
}