10768 lines
343 KiB
C++
10768 lines
343 KiB
C++
#include "priv.h"
|
|
#include "sccls.h"
|
|
#include <varutil.h>
|
|
|
|
#include "itbdrop.h"
|
|
#include <urlhist.h>
|
|
#include "autocomp.h"
|
|
#include "itbar.h"
|
|
#include "address.h"
|
|
#include <winbase.h>
|
|
#include "basebar.h"
|
|
#include "shbrowse.h"
|
|
#include "brand.h"
|
|
#include "resource.h"
|
|
#include "theater.h"
|
|
#include "browmenu.h"
|
|
#include "util.h"
|
|
#include "droptgt.h"
|
|
#include "legacy.h"
|
|
#include "apithk.h"
|
|
#include "shbrows2.h"
|
|
#include "stdenum.h"
|
|
#include "iehelpid.h"
|
|
#include <tb_ids.h>
|
|
#include "mediautil.h"
|
|
|
|
#define WANT_CBANDSITE_CLASS
|
|
#include "bandsite.h"
|
|
#include "schedule.h"
|
|
#include "uemapp.h"
|
|
|
|
#include "mluisupp.h"
|
|
|
|
#ifdef UNIX
|
|
extern "C" const GUID CLSID_MsgBand;
|
|
#endif
|
|
|
|
// The edit button hackery needs to be moved to shdocvw. This define identifies this code.
|
|
#define EDIT_HACK
|
|
|
|
// Offset of the comctl32 default bitmaps
|
|
#define OFFSET_HIST (MAX_TB_BUTTONS - 1 + 0) // 15
|
|
#define OFFSET_STD (MAX_TB_BUTTONS - 1 + 6) // 21
|
|
#define OFFSET_VIEW (MAX_TB_BUTTONS - 1 + 21) // 36
|
|
|
|
// This is the offset in the toolbar for the Shell glyphs and the Shell toolbar labels
|
|
#define SHELLTOOLBAR_OFFSET (MAX_TB_BUTTONS - 1 + 1) // 16
|
|
#define FONTGLYPH_OFFSET (MAX_TB_BUTTONS - 1 + 38) // 53
|
|
#define BRIEFCASEGLYPH_OFFSET (MAX_TB_BUTTONS - 1 + 34) // 49
|
|
#define RNAUIGLYPH_OFFSET (MAX_TB_BUTTONS - 1 + 36) // 51
|
|
#define WEBCHECKGLYPH_OFFSET (MAX_TB_BUTTONS - 1 + 42) // 57
|
|
#ifdef EDIT_HACK
|
|
#define EDITGLYPH_OFFSET (9)
|
|
#endif
|
|
|
|
#define IDT_UPDATETOOLBAR 0x1
|
|
#define TIMEOUT_UPDATETOOLBAR 400
|
|
|
|
const GUID CLSID_Separator = { 0x67077B90L, 0x4F9D, 0x11D0, 0xB8, 0x84, 0x00, 0xAA, 0x00, 0xB6, 0x01, 0x04 };
|
|
|
|
extern HRESULT VariantClearLazy(VARIANTARG *pvarg);
|
|
|
|
// How many CT_TABLE structures to allocated at a time.
|
|
#define TBBMPLIST_CHUNK 5
|
|
|
|
#define MAX_EXTERNAL_BAND_NAME_LEN 64
|
|
|
|
#define MAX_TB_COMPRESSED_WIDTH 42
|
|
// 16 is added to the the MAX_TB defines. This is added through the strings
|
|
// in the RC file. This is done so that the localization folks can increase
|
|
// or decrease the width of the toolbar buttons
|
|
#define MAX_TB_WIDTH_LORES 38
|
|
#define MAX_TB_WIDTH_HIRES 60
|
|
|
|
// Dimensions of Coolbar Glyphs ..
|
|
#define TB_SMBMP_CX 16
|
|
#define TB_SMBMP_CY 16
|
|
#define TB_BMP_CX 20
|
|
#define TB_BMP_CY 20
|
|
#define TB_BMP_CX_ALPHABITMAP 24
|
|
#define TB_BMP_CY_ALPHABITMAP 24
|
|
|
|
int g_iToolBarLargeIconWidth = TB_BMP_CX;
|
|
int g_iToolBarLargeIconHeight = TB_BMP_CY;
|
|
|
|
|
|
#define CX_SEPARATOR 6 // we override toolbar control's default separator width of 8
|
|
|
|
#define DM_TBSITE 0
|
|
#define DM_TBCMD 0
|
|
#define DM_TBREF TF_SHDREF
|
|
#define DM_LAYOUT 0
|
|
#define DM_ITBAR 0
|
|
|
|
#define TF_TBCUST 0x01000000
|
|
|
|
#if CBIDX_LAST != 5
|
|
#error Expected CBIDX_LAST to have value of 5
|
|
#endif
|
|
|
|
#if (FCIDM_EXTERNALBANDS_LAST - FCIDM_EXTERNALBANDS_FIRST + 1) < MAXEXTERNALBANDS
|
|
#error Insufficient range for FCIDM_EXTERNALBANDS_FIRST to FCIDM_EXTERNALBANDS_LAST
|
|
#endif
|
|
|
|
|
|
__inline UINT EXTERNALBAND_VBF_BIT(UINT uiBandExt)
|
|
{
|
|
ASSERT(uiBandExt < MAXEXTERNALBANDS);
|
|
|
|
// Formula: take 1, shift left by uiBandExt + 16
|
|
// => a bit in range (0x80000000, 0x00010000)
|
|
UINT uBit = 1 << (uiBandExt + 16);
|
|
ASSERT(uBit & VBF_EXTERNALBANDS);
|
|
|
|
return uBit;
|
|
}
|
|
|
|
__inline BOOL IS_EXTERNALBAND(int idBand)
|
|
{
|
|
return (InRange(idBand, CBIDX_EXTERNALFIRST, CBIDX_EXTERNALLAST));
|
|
}
|
|
|
|
__inline int MAP_TO_EXTERNAL(int idBand)
|
|
{
|
|
ASSERT(IS_EXTERNALBAND(idBand));
|
|
|
|
// CBIDX_LAST is one-based, mapping is zero-based
|
|
return (idBand - (1 + CBIDX_LAST));
|
|
}
|
|
|
|
|
|
// maximum number of menu items in the context menus for back and forward.
|
|
#define MAX_NAV_MENUITEMS 9
|
|
|
|
#define DEFAULT_SEARCH_GUID SRCID_SFileSearch //SRCID_SWebSearch
|
|
|
|
#define SZ_PROP_CUSTDLG TEXT("Itbar custom dialog hwnd")
|
|
|
|
#define REG_KEY_BANDSTATE TEXT("Software\\Microsoft\\Internet Explorer\\Toolbar")
|
|
|
|
// MHTML Editing
|
|
#define SZ_IE_DEFAULT_MHTML_EDITOR "Default MHTML Editor"
|
|
#define REGSTR_PATH_DEFAULT_MHTML_EDITOR TSZIEPATH TEXT("\\") TEXT(SZ_IE_DEFAULT_MHTML_EDITOR)
|
|
#define REGSTR_KEY_DEFAULT_MHTML_EDITOR TEXT(SZ_IE_DEFAULT_MHTML_EDITOR)
|
|
|
|
DWORD DoNetConnect(HWND hwnd);
|
|
DWORD DoNetDisconnect(HWND hwnd);
|
|
|
|
|
|
void _LoadToolbarGlyphs(HWND hwnd, IMLCACHE *pimlCache, int cx, int idBmp,
|
|
int iBitmapBaseIndex, BOOL bUseClassicGlyphs, HINSTANCE hInst);
|
|
|
|
BOOL _UseSmallIcons();
|
|
|
|
|
|
typedef struct tagTBBMP_LIST
|
|
{
|
|
HINSTANCE hInst;
|
|
UINT_PTR uiResID;
|
|
UINT uiOffset;
|
|
BITBOOL fNormal:1;
|
|
BITBOOL fHot:1;
|
|
BITBOOL fDisabled:1;
|
|
UINT uiCount;
|
|
} TBBMP_LIST;
|
|
|
|
typedef struct tagCMDMAP
|
|
{
|
|
GUID guidButtonGroup;
|
|
UINT nCmdID;
|
|
LPARAM lParam; // app's data
|
|
} CMDMAP;
|
|
|
|
typedef struct tagCMDMAPCUSTOMIZE
|
|
{
|
|
TBBUTTON btn;
|
|
CMDMAP cm;
|
|
} CMDMAPCUSTOMIZE;
|
|
|
|
typedef struct {
|
|
|
|
// the IOleCommandTarget info:
|
|
GUID guid;
|
|
UINT nCmdID;
|
|
UINT fButtonState;
|
|
} BUTTONSAVEINFO;
|
|
|
|
#define TBSI_VERSION 7
|
|
typedef struct {
|
|
int cVersion;
|
|
} TOOLBARSAVEINFO;
|
|
|
|
typedef struct {
|
|
HDSA hdsa;
|
|
BITBOOL fAdjust:1;
|
|
BITBOOL fDirty:1;
|
|
} CUSTOMIZEINFO, *LPCUSTOMIZEINFO;
|
|
|
|
//Current latest version.
|
|
#define CBS_VERSION 17
|
|
|
|
// NOTE: Be very careful changing COOLBARSAVE because _LoadUpgradeSettings makes
|
|
// assumptions about the layout of the structure. To avoid breaking that
|
|
// upgrade code, be sure you:
|
|
//
|
|
// - don't change the order of existing members
|
|
// - always add new members to the end of the structure.
|
|
// - update _LoadUpgradeSettings if appropriate
|
|
//
|
|
typedef struct tagCOOLBARSAVE
|
|
{
|
|
UINT cbVer;
|
|
UINT uiMaxTBWidth;
|
|
UINT uiMaxQLWidth;
|
|
#ifdef UNIX
|
|
BITBOOL fUnUsed : 28; // unused
|
|
#endif
|
|
BITBOOL fVertical : 1; // The bar is oriented vertically
|
|
BITBOOL fNoText :1; // "NoText"
|
|
BITBOOL fList : 1; // toolbar is TBSTYLE_LIST (text on right) + TBSTYLE_EX_MIXEDBUTTONS
|
|
BITBOOL fAutoHide : 1; // Auto hide toolbar in theater mode
|
|
BITBOOL fStatusBar : 1; // Status bar in theater mode
|
|
BITBOOL fSaveInShellIntegrationMode : 1; // Did we save in shell integration mode?
|
|
UINT uiVisible; // "Visible bands"
|
|
UINT cyRebar;
|
|
BANDSAVE bs[CBANDSMAX];
|
|
CLSID aclsidExternalBands[ MAXEXTERNALBANDS ]; // Check classid
|
|
CLSID clsidVerticalBar; //clsid of bar persisted within vertical band
|
|
CLSID clsidHorizontalBar;
|
|
} COOLBARSAVE, *LPCOOLBARSAVE;
|
|
|
|
//Flags for dwFlags passed to UpdateToolbarDisplay()
|
|
#define UTD_TEXTLABEL 0x00000001
|
|
#define UTD_VISIBLE 0x00000002
|
|
|
|
static const TCHAR c_szRegKeyCoolbar[] = TSZIEPATH TEXT("\\Toolbar");
|
|
static const TCHAR c_szValueTheater[] = TEXT("Theater");
|
|
|
|
typedef struct tagFOLDERSEARCHITEM
|
|
{
|
|
UINT idCmd;
|
|
GUID guidSearch;
|
|
int iIcon;
|
|
WCHAR wszUrl[MAX_URL_STRING];
|
|
WCHAR wszName[80]; // friendly name
|
|
}FOLDERSEARCHITEM, *LPFOLDERSEARCHITEM;
|
|
|
|
BOOL NavigateSearchBar(IWebBrowser2 *pwb2, LPCWSTR pwszUrl);
|
|
BOOL _GetSearchHKEY(LPGUID lpguidSearch, HKEY *phkey);
|
|
|
|
#define REG_SZ_STATIC TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FindExtensions\\Static")
|
|
#define REG_SZ_SEARCH_GUID TEXT("SearchGUID")
|
|
#define REG_SZ_SEARCH_URL TEXT("SearchGUID\\Url")
|
|
|
|
#define VIEW_OFFSET (SHELLGLYPHS_OFFSET + HIST_MAX + STD_MAX)
|
|
#define VIEW_ALLFOLDERS (VIEW_NETCONNECT + 14)
|
|
|
|
static const TBBUTTON c_tbExplorer[] =
|
|
{
|
|
// override default toolbar width for separators; iBitmap member of
|
|
// TBBUTTON struct is a union of bitmap index & separator width
|
|
|
|
{ 0, TBIDM_BACK , 0, BTNS_DROPDOWN | BTNS_SHOWTEXT, {0,0}, 0, 0 },
|
|
{ 1, TBIDM_FORWARD, 0, BTNS_DROPDOWN, {0,0}, 0, 1 },
|
|
|
|
{ 2, TBIDM_STOPDOWNLOAD, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 2 },
|
|
{ 3, TBIDM_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 3 },
|
|
{ 4, TBIDM_HOME, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 4 },
|
|
|
|
{ VIEW_PARENTFOLDER + VIEW_OFFSET, TBIDM_PREVIOUSFOLDER, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, VIEW_PARENTFOLDER + VIEW_OFFSET },
|
|
{ VIEW_NETCONNECT + VIEW_OFFSET, TBIDM_CONNECT, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, VIEW_NETCONNECT + VIEW_OFFSET },
|
|
{ VIEW_NETDISCONNECT + VIEW_OFFSET, TBIDM_DISCONNECT, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, VIEW_NETDISCONNECT + VIEW_OFFSET },
|
|
|
|
{ CX_SEPARATOR, 0, TBSTATE_ENABLED, BTNS_SEP, {0,0}, 0, -1 },
|
|
{ 5, TBIDM_SEARCH, TBSTATE_ENABLED, BTNS_SHOWTEXT, {0,0}, 0, 5 },
|
|
{ VIEW_ALLFOLDERS + VIEW_OFFSET, TBIDM_ALLFOLDERS, TBSTATE_ENABLED, BTNS_SHOWTEXT, {0,0}, 0, VIEW_ALLFOLDERS + VIEW_OFFSET },
|
|
{ 6, TBIDM_FAVORITES, TBSTATE_ENABLED, BTNS_SHOWTEXT, {0,0}, 0, 6 },
|
|
// IF YOU CHANGE THE ORDERING OF THIS, please change AddMediaBarButton to reflect this ordering.
|
|
{ 11, TBIDM_MEDIABAR, TBSTATE_ENABLED, BTNS_SHOWTEXT, {0,0}, 0, 11 },
|
|
{ 12, TBIDM_HISTORY, TBSTATE_ENABLED, 0/*BTNS_SHOWTEXT*/, {0,0}, 0, 12},
|
|
{ CX_SEPARATOR, 0, TBSTATE_ENABLED, BTNS_SEP, {0,0}, 0, -1 },
|
|
#ifndef DISABLE_FULLSCREEN
|
|
// IE UNIX : No theater mode for beta1
|
|
{ 14, TBIDM_THEATER, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 14 },
|
|
#endif
|
|
};
|
|
|
|
// these IDs are the array indices into c_tbExplorer above
|
|
// keep in sync, be aware there are ASSERTs to enforce them to be in sync
|
|
#define TBXID_BACK 0
|
|
#define TBXID_FORWARD 1
|
|
#define TBXID_STOPDOWNLOAD 2
|
|
#define TBXID_REFRESH 3
|
|
#define TBXID_HOME 4
|
|
#define TBXID_PREVIOUSFOLDER 5
|
|
#define TBXID_CONNECT 6
|
|
#define TBXID_DISCONNECT 7
|
|
#define TBXID_SEPARATOR1 8
|
|
#define TBXID_SEARCH 9
|
|
#define TBXID_ALLFOLDERS 10
|
|
#define TBXID_FAVORITES 11
|
|
#define TBXID_MEDIABAR 12
|
|
#define TBXID_HISTORY 13
|
|
#define TBXID_SEPARATOR2 14
|
|
#define TBXID_THEATER 15
|
|
|
|
|
|
static const BROWSER_RESTRICTIONS c_rest[] = {
|
|
REST_BTN_BACK,
|
|
REST_BTN_FORWARD,
|
|
REST_BTN_STOPDOWNLOAD,
|
|
REST_BTN_REFRESH,
|
|
REST_BTN_HOME,
|
|
REST_BROWSER_NONE, // no policy for up
|
|
REST_BROWSER_NONE, // no policy for map drive
|
|
REST_BROWSER_NONE, // no policy for disconnect drive
|
|
REST_BROWSER_NONE, // separator
|
|
REST_BTN_SEARCH,
|
|
REST_BTN_ALLFOLDERS,
|
|
REST_BTN_FAVORITES,
|
|
REST_BTN_MEDIABAR,
|
|
REST_BTN_HISTORY,
|
|
REST_BROWSER_NONE, // separator
|
|
#ifndef DISABLE_FULLSCREEN
|
|
REST_BTN_THEATER,
|
|
#endif
|
|
};
|
|
|
|
|
|
// init flags to avoid multiple inits of toolbar and buttons
|
|
#define TBBIF_REG_PATH TEXT("Software\\Microsoft\\Internet Explorer")
|
|
#define TBBIF_REG_KEY TEXT("AddButtons")
|
|
// defined flags as bitfield
|
|
#define TBBIF_NONE 0
|
|
#define TBBIF_XBAR 0x1 // reserved/used to distinguish pre IE6/RC1 where PersonalBar/xBar was configured
|
|
#define TBBIF_MEDIA 0x2
|
|
|
|
#define SUPERCLASS CBaseBar
|
|
|
|
class CInternetToolbar :
|
|
public CBaseBar,
|
|
public IDockingWindow,
|
|
public IObjectWithSite, // *not* CObjectWithSite (want _ptbSite)
|
|
public IExplorerToolbar,
|
|
public DWebBrowserEvents,
|
|
public IPersistStreamInit,
|
|
public IShellChangeNotify,
|
|
public ISearchItems
|
|
{
|
|
public:
|
|
// *** IUnknown ***
|
|
virtual STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj);
|
|
virtual STDMETHODIMP_(ULONG) AddRef(void) { return SUPERCLASS::AddRef(); };
|
|
virtual STDMETHODIMP_(ULONG) Release(void){ return SUPERCLASS::Release(); };
|
|
|
|
// *** IOleWindow methods ***
|
|
virtual STDMETHODIMP GetWindow(HWND * lphwnd) { return SUPERCLASS::GetWindow(lphwnd);};
|
|
virtual STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode) {return SUPERCLASS::ContextSensitiveHelp(fEnterMode);};
|
|
|
|
// *** IDockingWindow methods ***
|
|
virtual STDMETHODIMP ShowDW(BOOL fShow);
|
|
virtual STDMETHODIMP CloseDW(DWORD dwReserved);
|
|
virtual STDMETHODIMP ResizeBorderDW(LPCRECT prcBorder, IUnknown* punkToolbarSite, BOOL fReserved);
|
|
|
|
// *** IObjectWithSite methods ***
|
|
virtual STDMETHODIMP SetSite(IUnknown* punkSite);
|
|
// is E_NOTIMPL ok?
|
|
virtual STDMETHODIMP GetSite(REFIID riid, void** ppvSite) { ASSERT(0); return E_NOTIMPL; };
|
|
|
|
// *** IInputObjectSite methods ***
|
|
virtual STDMETHODIMP OnFocusChangeIS(IUnknown *punk, BOOL fSetFocus);
|
|
|
|
// *** IInputObject methods ***
|
|
virtual STDMETHODIMP TranslateAcceleratorIO(LPMSG lpMsg);
|
|
|
|
// *** IServiceProvider methods ***
|
|
virtual STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void** ppvObj);
|
|
|
|
// *** IExplorerToolbar method ***
|
|
virtual STDMETHODIMP SetCommandTarget(IUnknown* punkCmdTarget, const GUID* pguidButtonGroup, DWORD dwFlags);
|
|
virtual STDMETHODIMP AddStdBrowserButtons(void);
|
|
|
|
virtual STDMETHODIMP AddButtons(const GUID* pguidButtonGroup, UINT nButtons, const TBBUTTON * lpButtons);
|
|
virtual STDMETHODIMP AddString(const GUID * pguidButtonGroup, HINSTANCE hInst, UINT_PTR uiResID, LONG_PTR *pOffset);
|
|
virtual STDMETHODIMP GetButton(const GUID* pguidButtonGroup, UINT uiCommand, LPTBBUTTON lpButton);
|
|
virtual STDMETHODIMP GetState(const GUID* pguidButtonGroup, UINT uiCommand, UINT * pfState);
|
|
virtual STDMETHODIMP SetState(const GUID* pguidButtonGroup, UINT uiCommand, UINT fState);
|
|
virtual STDMETHODIMP AddBitmap(const GUID * pguidButtonGroup, UINT uiBMPType, UINT uiCount, TBADDBITMAP * ptb,
|
|
LRESULT * pOffset, COLORREF rgbMask);
|
|
virtual STDMETHODIMP GetBitmapSize(UINT * uiID);
|
|
virtual STDMETHODIMP SendToolbarMsg(const GUID * pguidButtonGroup, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT * plRes);
|
|
|
|
virtual STDMETHODIMP SetImageList( const GUID* pguidCmdGroup, HIMAGELIST himlNormal, HIMAGELIST himlHot, HIMAGELIST himlDisabled);
|
|
virtual STDMETHODIMP ModifyButton( const GUID * pguidButtonGroup, UINT uiCommand, LPTBBUTTON lpButton);
|
|
|
|
// IOleCommandTarget
|
|
virtual STDMETHODIMP QueryStatus(const GUID *pguidCmdGroup,
|
|
ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext);
|
|
virtual STDMETHODIMP Exec(const GUID *pguidCmdGroup,
|
|
DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn,
|
|
VARIANTARG *pvarargOut);
|
|
|
|
// IPersistStreamInit
|
|
STDMETHOD(GetClassID)(GUID *pguid);
|
|
STDMETHOD(Load)(IStream *pStm);
|
|
STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty);
|
|
STDMETHOD(InitNew)(void);
|
|
STDMETHOD(IsDirty)(void);
|
|
STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize);
|
|
|
|
/* IDispatch methods */
|
|
virtual STDMETHODIMP GetTypeInfoCount(UINT *pctinfo);
|
|
|
|
virtual STDMETHODIMP GetTypeInfo(UINT itinfo,LCID lcid,ITypeInfo **pptinfo);
|
|
|
|
virtual STDMETHODIMP GetIDsOfNames(REFIID riid,OLECHAR **rgszNames,UINT cNames,
|
|
LCID lcid, DISPID * rgdispid);
|
|
|
|
virtual STDMETHODIMP Invoke(DISPID dispidMember,REFIID riid,LCID lcid,WORD wFlags,
|
|
DISPPARAMS * pdispparams, VARIANT * pvarResult,
|
|
EXCEPINFO * pexcepinfo,UINT * puArgErr);
|
|
|
|
// IShellChangeNotify
|
|
virtual STDMETHODIMP OnChange(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
|
|
|
|
// CBaseBar overrides
|
|
virtual LRESULT v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
|
|
// *** ISearchItems methods ***
|
|
virtual STDMETHODIMP GetDefaultSearchUrl(LPWSTR pwzUrl, UINT cch);
|
|
|
|
CInternetToolbar();
|
|
protected:
|
|
virtual ~CInternetToolbar();
|
|
static LRESULT CALLBACK SizableWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
void _OnCommand(WPARAM wParam, LPARAM lParam);
|
|
BOOL _SendToToolband(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres);
|
|
LRESULT _OnNotify(LPNMHDR pnmh);
|
|
void _OnTooltipNeeded(LPTOOLTIPTEXT pnmTT);
|
|
void _QueryStatusTip(IOleCommandTarget *pct, LPTOOLTIPTEXT pnmTT, UINT uiCmd, const GUID* pguid);
|
|
|
|
BOOL _UpEnabled();
|
|
void _UpdateCommonButton(int iCmd, UINT nCmdID);
|
|
void _UpdateToolbar(BOOL fForce);
|
|
void _UpdateToolbarNow();
|
|
void _UpdateGroup(const GUID *pguidCmdGroup, int cnt, OLECMD rgcmds[], const GUID* pguidButton, const int buttonsInternal[]);
|
|
void _CSHSetStatusBar(BOOL fOn);
|
|
void _StartDownload();
|
|
void _StopDownload(BOOL fClosing);
|
|
void _SendDocCommand(UINT idCmd);
|
|
BOOL _CompressBands(BOOL fCompress, UINT uRowsNew, BOOL fForceUpdate);
|
|
void _TrackSliding(int x, int y);
|
|
HRESULT _DoNavigateA(LPSTR pszURL,int iNewSelection);
|
|
HRESULT _DoNavigateW(LPWSTR pwzURL,int iNewSelection);
|
|
HRESULT _DoNavigate(BSTR bstrURL,int iNewSelection);
|
|
void _Unadvise(void);
|
|
LRESULT _OnBeginDrag(NMREBAR* pnm);
|
|
|
|
void _InsertURL(LPTSTR pszURL);
|
|
|
|
void _ShowContextMenu(HWND hwnd, LPARAM lParam, LPRECT prcExclude);
|
|
BOOL _ShowBackForwardMenu(BOOL fForward, POINT pt, LPRECT prcExclude);
|
|
// search helper methods
|
|
BOOL _GetFolderSearchData();
|
|
void _SetSearchStuff();
|
|
BOOL _GetSearchUrl(LPWSTR pwszUrl, DWORD cch);
|
|
HRESULT _GetFolderSearches(IFolderSearches **ppfs);
|
|
|
|
|
|
void _ReloadButtons();
|
|
void _UpdateToolsStyle(BOOL fList);
|
|
void _InitBitmapDSA();
|
|
void _ReloadBitmapDSA();
|
|
void _InitForScreenSize();
|
|
void _InitToolbar();
|
|
BOOL _FoldersButtonAvailable();
|
|
void _AdminMarkDefaultButtons(PTBBUTTON ptbb, UINT cButtons);
|
|
void _MarkDefaultButtons(PTBBUTTON ptbb, UINT cButtons);
|
|
void _AddCommonButtons();
|
|
HRESULT _CreateBands();
|
|
BOOL _ShowBands(UINT fVisible);
|
|
HRESULT _ShowTools(PBANDSAVE pbs);
|
|
HRESULT _ShowAddressBand(PBANDSAVE pbs);
|
|
HRESULT _ShowExternalBand(PBANDSAVE pbs, int idBand );
|
|
HRESULT _ShowLinks(PBANDSAVE pbs);
|
|
HRESULT _ShowBrand(PBANDSAVE pbs);
|
|
HRESULT _ShowMenu(PBANDSAVE pbs);
|
|
void _ShowBandCommon(PBANDSAVE pbs, LPBANDITEMDATA pbid, BOOL fShow);
|
|
void _EnsureAllBandsShown();
|
|
HRESULT _GetMinRowHeight();
|
|
|
|
HBITMAP _LoadBackBitmap();
|
|
void _SetBackground();
|
|
void _CommonHandleFileSysChange(LONG lEvent, LPITEMIDLIST* ppidl);
|
|
LPITEMIDLIST _GetCurrentPidl(void);
|
|
int _ConvertHwndToID(HWND hwnd);
|
|
|
|
HRESULT _GetPersistedBand(const CLSID clsid, REFIID riid, void ** ppiface);
|
|
|
|
// Multiple command target
|
|
LRESULT _AddBitmapFromForeignModule(UINT uiGetMSG, UINT uiSetMSG, UINT uiCount, HINSTANCE hinst,
|
|
UINT_PTR nID, COLORREF rgbMask);
|
|
|
|
HRESULT _LoadDefaultSettings(void);
|
|
HRESULT _LoadUpgradeSettings(ULONG cbRead);
|
|
HRESULT _LoadDefaultWidths(void);
|
|
void _TryLoadIE3Settings();
|
|
HRESULT _UpdateToolbarDisplay(DWORD dwFlags, UINT uVisibleBands, BOOL fNoText, BOOL fPersist);
|
|
void _UpdateBrandSize();
|
|
void _ShowVisible(DWORD dwVisible, BOOL fPersist);
|
|
void _BuildSaveStruct(COOLBARSAVE* pcs);
|
|
void _RestoreSaveStruct(COOLBARSAVE* pcs);
|
|
void _GetVisibleBrowserBar(UINT idBar, CLSID *pclsidOut);
|
|
VOID _UpdateLocking();
|
|
|
|
LPBANDITEMDATA _AddNewBand(IDeskBand* pdb, DWORD dwID);
|
|
|
|
void _TheaterModeLayout(BOOL fEnter);
|
|
|
|
HBITMAP _bmpBack; // this is the state we think the itbar is in
|
|
static BMPCACHE s_bmpBackShell; // this is the state of the shell bmp cache
|
|
static BMPCACHE s_bmpBackInternet; // this is the state of the internet bmp cache
|
|
static IMLCACHE s_imlTBGlyphs;
|
|
|
|
HWND _hwndMenu;
|
|
HWND _hwndAddressBand;
|
|
|
|
IDockingWindowSite* _ptbsite;
|
|
IOleCommandTarget* _ptbsitect;
|
|
IBrowserService* _pbs;
|
|
IBrowserService2* _pbs2;
|
|
IServiceProvider* _psp;
|
|
IBandProxy * _pbp;
|
|
|
|
BITBOOL _fCreatedBandProxy:1;
|
|
BITBOOL _fBackEnabled:1;
|
|
BITBOOL _fForwardEnabled:1;
|
|
BITBOOL _fEditEnabled:1;
|
|
BITBOOL _fShow:1;
|
|
BITBOOL _fAnimating:1;
|
|
BITBOOL _fCompressed:1;
|
|
BITBOOL _fUserNavigated :1;
|
|
BITBOOL _fAutoCompInitialized :1;
|
|
BITBOOL _fDirty:1;
|
|
BITBOOL _fUsingDefaultBands:1;
|
|
BITBOOL _fTransitionToHTML:1;
|
|
BITBOOL _fInitialPidlIsWeb:1;
|
|
BITBOOL _fTheater: 1; // are we in theater mode? claim no border space
|
|
BITBOOL _fAutoHide :1;
|
|
BITBOOL _fRebarDragging :1;
|
|
BITBOOL _fShellView:1; // are we in shell view or web view?
|
|
BITBOOL _fNoShowMenu:1; // can show menu band?
|
|
BITBOOL _fUpdateToolbarTimer:1;
|
|
BITBOOL _fNeedUpdateToolbar:1;
|
|
BITBOOL _fNavigateComplete:1;
|
|
BITBOOL _fLoading:1; // are we still loading the bar?
|
|
BITBOOL _fDestroyed:1; // Did we destroy our member varibles and are shutting down? If so, don't use the varibles. (Stress bug w/messages coming in)
|
|
BITBOOL _fLockedToolbar:1;
|
|
|
|
UINT _nVisibleBands; // bitmask of which bands are visible: VBF_*
|
|
|
|
IWebBrowser2* _pdie;
|
|
DWORD _dwcpCookie; // DIID_DWebBrowserEvents2
|
|
int _xCapture;
|
|
int _yCapture;
|
|
// for multiple command target support
|
|
HDSA _hdsaTBBMPs;
|
|
UINT _uiMaxTBWidth;
|
|
UINT _uiTBTextRows;
|
|
UINT _uiTBDefaultTextRows;
|
|
// search stuff
|
|
HDPA _hdpaFSI; // folder search items
|
|
GUID _guidCurrentSearch;
|
|
GUID _guidDefaultSearch;
|
|
|
|
COOLBARSAVE _cs; //Coolbar layout info from registry!
|
|
BOOL _fDontSave; // force ourselves not to persist out the state.
|
|
|
|
struct EXTERNALBANDINFO {
|
|
CLSID clsid; // CLSID of the band
|
|
LPWSTR pwszName; // Band name
|
|
LPWSTR pwszHelp; // Band help text
|
|
};
|
|
EXTERNALBANDINFO _rgebi[ MAXEXTERNALBANDS ];
|
|
|
|
void _LoadExternalBandInfo();
|
|
|
|
TBBUTTON _tbExplorer[ARRAYSIZE(c_tbExplorer)];
|
|
int _iButtons;
|
|
|
|
|
|
#ifdef EDIT_HACK
|
|
// Variables for customizing the edit button glyph
|
|
HIMAGELIST _himlEdit; // Monochrome Image list for the edit button
|
|
HIMAGELIST _himlEditHot; // Hot image list for edit button
|
|
int _iEditIcon; // index of current edit icon
|
|
int _cxEditGlyph; // cx of glyph size
|
|
int _cyEditGlyph; // cx of glyph size
|
|
|
|
// Functions for managing a custom edit glyph
|
|
void _InitEditButtonStyle();
|
|
void _SetEditGlyph(int iIcon);
|
|
void _RefreshEditGlyph();
|
|
void _UpdateEditButton();
|
|
static HIMAGELIST _CreateGrayScaleImagelist(HBITMAP hbmpImage, HBITMAP hbmpMask);
|
|
static BSTR _GetEditProgID(IHTMLDocument2* pHTMLDocument);
|
|
|
|
//
|
|
// We can have multiple edit verbs associated with a document. The following class
|
|
// maintains a list of verbs.
|
|
//
|
|
#define FCIDM_EDITFIRST 2000
|
|
#define FCIDM_EDITLAST 2100
|
|
#define SZ_EDITVERB_PROP TEXT("CEditVerb_This")
|
|
#define IL_EDITBUTTON 2 // Index of image list used for the edit button
|
|
#define IL_SEARCHBUTTON 3 // || search button
|
|
|
|
// MSAA Menu Info declarations.
|
|
// These will eventually be incorporated into oleacc.h - but for the
|
|
// moment, we declare them privately...
|
|
#define MSAA_MENU_SIG 0xAA0DF00DL
|
|
|
|
class CEditVerb
|
|
{
|
|
public:
|
|
CEditVerb();
|
|
~CEditVerb();
|
|
|
|
// Functions for managing the verbs
|
|
BOOL Add(LPTSTR pszProgID);
|
|
UINT GetSize() { return _nElements; }
|
|
void RemoveAll();
|
|
|
|
// Functions to access the default edit verb
|
|
int GetIcon() { return (_nElements && _pVerb[_nDefault].fShowIcon) ? _GetVerb(_nDefault).iIcon : -1; }
|
|
BOOL GetToolTip(LPTSTR pszToolTip, UINT cchMax, BOOL fStripAmpersands = TRUE);
|
|
BOOL GetMenuText(LPTSTR pszText, UINT cchMax) { return GetToolTip(pszText, cchMax, FALSE); }
|
|
void Edit(LPCTSTR pszUrl) { _Edit(pszUrl, _nDefault); }
|
|
|
|
// Pop-up menu
|
|
BOOL ShowEditMenu(POINT pt, HWND hwnd, LPTSTR pszUrl);
|
|
|
|
// Get default editor from the registry
|
|
void InitDefaultEditor(HKEY hkey = NULL);
|
|
|
|
protected:
|
|
struct MSAAMenuInfo
|
|
{
|
|
DWORD m_MSAASig; // Must be MSAA_MENU_SIG
|
|
DWORD m_CharLen; // Length in characters of text, excluding terminating NUL
|
|
LPWSTR m_pWStr; // Menu text, in UNICODE, with terminating UNICODE-NUL.
|
|
};
|
|
|
|
struct EDITVERB
|
|
{
|
|
MSAAMenuInfo m_MSAA; // MSAA info - must be first element.
|
|
HKEY hkeyProgID; // Key the we shellexec
|
|
BITBOOL fUseOpenVerb:1; // use open verb instead of edit
|
|
BITBOOL fInit:1; // true if the data below has beed initialized
|
|
BITBOOL fShowIcon:1; // true if icon should show up on button
|
|
int iIcon; // cached icon index
|
|
UINT idCmd; // menu id
|
|
LPTSTR pszDesc; // executable name or document name
|
|
LPTSTR pszMenuText; // Menu text
|
|
LPTSTR pszExe; // Path of the exe used to edit
|
|
};
|
|
|
|
EDITVERB* _Add(HKEY hkeyProgID, BOOL fPermitOpenVerb, BOOL fCheckForOfficeApp, BOOL fShowIcon);
|
|
EDITVERB& _GetVerb(UINT nIndex);
|
|
void _FetchInfo(UINT nIndex);
|
|
void _Edit(LPCTSTR pszUrl, UINT nIndex);
|
|
LPCTSTR _GetDescription(EDITVERB& rVerb);
|
|
void _SetMSAAMenuInfo(EDITVERB& rVerb);
|
|
void _ClearMSAAMenuInfo(EDITVERB& rVerb);
|
|
void _FormatMenuText(UINT nIndex);
|
|
BOOL _IsUnique(EDITVERB& rNewVerb);
|
|
BOOL _IsHtmlStub(LPCWSTR pszPath);
|
|
LPCTSTR _GetExePath(EDITVERB& rVerb);
|
|
LPCTSTR _GetDefaultEditor();
|
|
void _InitDefaultMHTMLEditor();
|
|
|
|
static LRESULT CALLBACK _WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
|
|
// Member data
|
|
UINT _nElements; // number of edit verbs
|
|
UINT _nDefault; // Default edit verb
|
|
EDITVERB* _pVerb; // array of edit verbs
|
|
WNDPROC _lpfnOldWndProc; // former wndProc
|
|
LPWSTR _pszDefaultEditor; // Friendly name of default HTML editor
|
|
BOOL _fInitEditor; // if we checked for a default editor
|
|
};
|
|
CEditVerb _aEditVerb;
|
|
|
|
#endif
|
|
|
|
// internal bandsite class
|
|
class CBrowserToolsBand;
|
|
class CITBandSite : public CBandSite
|
|
{
|
|
CITBandSite();
|
|
|
|
virtual STDMETHODIMP Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut);
|
|
virtual STDMETHODIMP AddBand(IUnknown *punk);
|
|
virtual STDMETHODIMP HasFocusIO();
|
|
|
|
protected:
|
|
virtual void v_SetTabstop(LPREBARBANDINFO prbbi);
|
|
BOOL _SetMinDimensions();
|
|
friend class CInternetToolbar;
|
|
friend class CBrowserToolsBand;
|
|
|
|
virtual HRESULT _OnContextMenu(WPARAM wParm, LPARAM lParam);
|
|
virtual HRESULT _Initialize(HWND hwndParent);
|
|
|
|
};
|
|
CITBandSite _bs;
|
|
|
|
|
|
#define TOOLSBANDCLASS CInternetToolbar::CBrowserToolsBand
|
|
class CBrowserToolsBand : public CToolbarBand
|
|
{
|
|
CMDMAP* _GetCmdMapByIndex(int nIndex) { return _GetCmdMap(nIndex, TRUE);};
|
|
CMDMAP* _GetCmdMapByID(int id) { return _GetCmdMap(id, FALSE);};
|
|
LRESULT _ToolsCustNotify (LPNMHDR pnmh); // Handle TBCustomization Notify
|
|
BOOL _SaveRestoreToolbar(BOOL fSave);
|
|
void _FreeCustomizeInfo();
|
|
void _FreeCmdMap(CMDMAP*);
|
|
BOOL _RemoveAllButtons();
|
|
int _CommandFromIndex(UINT uIndex);
|
|
HRESULT _ConvertCmd(const GUID* pguidButtonGroup, UINT id, GUID* pguidOut, UINT * pid);
|
|
void _OnDeletingButton(TBNOTIFY* ptbn);
|
|
LONG_PTR _AddString(LPWSTR pwstr);
|
|
void _PreProcessButtonString(TBBUTTON *ptbn, DWORD dwFlags);
|
|
void _PreProcessExternalTBButton(TBBUTTON *ptbn);
|
|
UINT _ProcessExternalButtons(PTBBUTTON ptbb, UINT cButtons);
|
|
void _GetButtons(IOleCommandTarget* pct, const GUID* pguid, HDSA hdsa);
|
|
void _RecalcButtonWidths();
|
|
void _AddMediaBarButton();
|
|
|
|
void _UpdateTextSettings(INT_PTR ids);
|
|
static BOOL_PTR CALLBACK _BtnAttrDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
static void _PopulateComboBox(HWND hwnd, const int iResource[], UINT cResources);
|
|
static void _SetComboSelection(HWND hwnd, int iCurOption);
|
|
void _SetDialogSelections(HWND hDlg, BOOL fSmallIcons);
|
|
static void _PopulateDialog(HWND hDlg);
|
|
void _OnBeginCustomize(LPNMTBCUSTOMIZEDLG pnm);
|
|
|
|
BOOL _BuildButtonDSA();
|
|
CMDMAPCUSTOMIZE* _GetCmdMapCustomize(GUID* guid, UINT nCmdID);
|
|
|
|
virtual STDMETHODIMP Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut);
|
|
|
|
virtual STDMETHODIMP GetClassID(CLSID *pClassID) {return E_NOTIMPL;};
|
|
virtual STDMETHODIMP Load(IStream *pStm) {return E_NOTIMPL;};
|
|
virtual STDMETHODIMP Save(IStream *pStm, BOOL fClearDirty) {return E_NOTIMPL;};
|
|
|
|
// *** IUnknown ***
|
|
virtual STDMETHODIMP_(ULONG) AddRef(void) { return CToolBand::AddRef(); };
|
|
virtual STDMETHODIMP_(ULONG) Release(void){ return CToolBand::Release(); };
|
|
virtual STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj);
|
|
|
|
// *** IDeskBand methods ***
|
|
virtual STDMETHODIMP GetBandInfo(DWORD dwBandID, DWORD fViewMode, DESKBANDINFO* pdbi);
|
|
|
|
// *** IWinEventHandler methods ***
|
|
virtual STDMETHODIMP OnWinEvent(HWND hwnd, UINT dwMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres);
|
|
|
|
// *** IDockingWindow methods ***
|
|
virtual STDMETHODIMP CloseDW(DWORD dwReserved) { return S_OK;};
|
|
|
|
// *** IInputObject methods ***
|
|
virtual STDMETHODIMP TranslateAcceleratorIO(LPMSG lpMsg);
|
|
|
|
protected:
|
|
IOleCommandTarget* _CommandTargetFromCmdMap(CMDMAP* pcm);
|
|
LRESULT _OnToolbarDropDown(TBNOTIFY *ptbn);
|
|
virtual LRESULT _OnNotify(LPNMHDR pnmh);
|
|
LRESULT _OnContextMenu(LPARAM lParam, WPARAM wParam);
|
|
CMDMAP* _GetCmdMap(int i, BOOL fByIndex);
|
|
void _OnEndCustomize();
|
|
LRESULT _TryShowBackForwardMenu(DWORD dwItemSpec, LPPOINT ppt, LPRECT prcExclude);
|
|
CBrowserToolsBand();
|
|
void _FreeBtnsAdded();
|
|
|
|
friend class CInternetToolbar;
|
|
friend class CITBandSite;
|
|
|
|
GUID _guidCurrentButtonGroup;
|
|
IOleCommandTarget* _pctCurrentButtonGroup;
|
|
LPTBBUTTON _pbtnsAdded;
|
|
int _cBtnsAdded;
|
|
DWORD _nNextCommandID;
|
|
CUSTOMIZEINFO *_pcinfo;
|
|
BITBOOL _fCustomize :1;
|
|
BITBOOL _fNeedFreeCmdMapsAdded :1;
|
|
};
|
|
|
|
CBrowserToolsBand _btb;
|
|
|
|
friend class CBrowserToolsBand;
|
|
friend class CITBandSite;
|
|
friend void CInternetToolbar_CleanUp();
|
|
friend void CInternetToolbar_Preload();
|
|
friend void ITBar_LoadToolbarGlyphs(HWND hwnd);
|
|
};
|
|
|
|
//
|
|
// Gets the stream corresponding to the type of the given pidl
|
|
// If the stream already doesn't exist, then it returns NULL.
|
|
|
|
HRESULT _GetStreamName(DWORD dwITBS, LPTSTR pszName, DWORD cchSize)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
ASSERT(pszName);
|
|
|
|
switch (dwITBS)
|
|
{
|
|
case ITBS_WEB:
|
|
StrCpyN(pszName, TEXT("WebBrowser"), cchSize);
|
|
break;
|
|
|
|
case ITBS_SHELL:
|
|
StrCpyN(pszName, TEXT("ShellBrowser"), cchSize);
|
|
break;
|
|
|
|
case ITBS_EXPLORER:
|
|
StrCpyN(pszName, TEXT("Explorer"), cchSize);
|
|
break;
|
|
|
|
default:
|
|
hr = E_FAIL;
|
|
break;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
pszName[0] = '\0';
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// Gets the stream corresponding to the type of the given pidl
|
|
// If the stream already doesn't exist, then it returns NULL.
|
|
|
|
IStream *GetRegStream(BOOL fInternet, LPCTSTR pszValue, DWORD grfMode)
|
|
{
|
|
IStream *pstm = NULL;
|
|
HKEY hkToolbar;
|
|
|
|
if (RegCreateKey(HKEY_CURRENT_USER, c_szRegKeyCoolbar, &hkToolbar) == ERROR_SUCCESS)
|
|
{
|
|
TCHAR szStreamName[MAX_PATH];
|
|
|
|
if (SUCCEEDED(_GetStreamName(fInternet, szStreamName, ARRAYSIZE(szStreamName))))
|
|
pstm = OpenRegStream(hkToolbar, szStreamName, pszValue, grfMode);
|
|
|
|
RegCloseKey(hkToolbar);
|
|
}
|
|
|
|
return(pstm);
|
|
}
|
|
|
|
|
|
//
|
|
// Gets the stream corresponding to the type of the given pidl
|
|
// If the stream already doesn't exist, then it returns NULL.
|
|
|
|
IStream *GetITBarStream(BOOL fInternet, DWORD grfMode)
|
|
{
|
|
return GetRegStream(fInternet, TEXT("ITBarLayout"), grfMode);
|
|
}
|
|
|
|
|
|
IMLCACHE CInternetToolbar::s_imlTBGlyphs = {NULL};
|
|
BMPCACHE CInternetToolbar::s_bmpBackShell = {NULL};
|
|
BMPCACHE CInternetToolbar::s_bmpBackInternet = {NULL};
|
|
BOOL g_fSmallIcons = FALSE;
|
|
|
|
void IMLCACHE_CleanUp(IMLCACHE * pimlCache, DWORD dwFlags)
|
|
{
|
|
for (int i = 0; i < CIMLISTS; i++)
|
|
{
|
|
if (pimlCache->arhimlPendingDelete[i])
|
|
ImageList_Destroy(pimlCache->arhimlPendingDelete[i]);
|
|
|
|
if ((dwFlags & IML_DESTROY) && pimlCache->arhiml[i])
|
|
ImageList_Destroy(pimlCache->arhiml[i]);
|
|
}
|
|
}
|
|
|
|
// DO NOT change the numbering of the following bitmap specs.
|
|
// If you want to add new sizes, add them _after_ ITB_1616_HOT_HICOLOR
|
|
|
|
#define ITB_2020_NORMAL 0
|
|
#define ITB_2020_HOT 1
|
|
#define ITB_1616_NORMAL 2
|
|
#define ITB_1616_HOT 3
|
|
#define ITB_2020_NORMAL_HICOLOR 4
|
|
#define ITB_2020_HOT_HICOLOR 5
|
|
#define ITB_1616_NORMAL_HICOLOR 6
|
|
#define ITB_1616_HOT_HICOLOR 7
|
|
|
|
void ITBar_LoadToolbarGlyphs(HWND hwnd)
|
|
{
|
|
int cx, idBmpType;
|
|
int iBitmapBaseIndex;
|
|
BOOL bUseClassicGlyphs = SHUseClassicToolbarGlyphs();
|
|
HINSTANCE hInst;
|
|
|
|
g_fSmallIcons = _UseSmallIcons();
|
|
|
|
if (bUseClassicGlyphs)
|
|
{
|
|
g_iToolBarLargeIconWidth = TB_BMP_CX;
|
|
g_iToolBarLargeIconHeight = TB_BMP_CY;
|
|
|
|
iBitmapBaseIndex = IDB_SHSTD;
|
|
hInst = HINST_THISDLL;
|
|
}
|
|
else
|
|
{
|
|
g_iToolBarLargeIconWidth = TB_BMP_CX_ALPHABITMAP;
|
|
g_iToolBarLargeIconHeight = TB_BMP_CY_ALPHABITMAP;
|
|
|
|
iBitmapBaseIndex = IDB_TB_SH_BASE;
|
|
hInst = GetModuleHandle(TEXT("shell32.dll"));
|
|
}
|
|
|
|
if (g_fSmallIcons)
|
|
{
|
|
cx = TB_SMBMP_CX;
|
|
idBmpType = ITB_1616_NORMAL;
|
|
}
|
|
else
|
|
{
|
|
cx = g_iToolBarLargeIconWidth;
|
|
idBmpType = ITB_2020_NORMAL;
|
|
}
|
|
|
|
if (SHGetCurColorRes() > 8)
|
|
idBmpType += DELTA_HICOLOR;
|
|
|
|
_LoadToolbarGlyphs(hwnd, &CInternetToolbar::s_imlTBGlyphs, cx, idBmpType,
|
|
iBitmapBaseIndex, bUseClassicGlyphs, hInst);
|
|
}
|
|
|
|
|
|
void CInternetToolbar_Preload()
|
|
{
|
|
ENTERCRITICAL;
|
|
ITBar_LoadToolbarGlyphs(NULL);
|
|
Brand_InitBrandContexts();
|
|
LEAVECRITICAL;
|
|
}
|
|
|
|
|
|
void CInternetToolbar_CleanUp()
|
|
{
|
|
TraceMsg(DM_ITBAR, "CInternetToolbar_CleanUp: Destroying shared GDI objects");
|
|
if (CInternetToolbar::s_bmpBackInternet.hbmp)
|
|
DeleteObject(CInternetToolbar::s_bmpBackInternet.hbmp);
|
|
if (CInternetToolbar::s_bmpBackShell.hbmp)
|
|
DeleteObject(CInternetToolbar::s_bmpBackShell.hbmp);
|
|
|
|
IMLCACHE_CleanUp(&CInternetToolbar::s_imlTBGlyphs, IML_DESTROY);
|
|
}
|
|
|
|
STDAPI CInternetToolbar_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
|
|
{
|
|
// aggregation checking is handled in class factory
|
|
|
|
CInternetToolbar *pitbar = new CInternetToolbar();
|
|
if (pitbar)
|
|
{
|
|
*ppunk = SAFECAST(pitbar, IDockingWindow *);
|
|
return S_OK;
|
|
}
|
|
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
LRESULT CInternetToolbar::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if ( uMsg == WM_SYSCOLORCHANGE )
|
|
{
|
|
// refresh the back drop incase the colours have changed
|
|
_SetBackground();
|
|
}
|
|
|
|
return SUPERCLASS::v_WndProc( hwnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
void CInternetToolbar::_LoadExternalBandInfo()
|
|
{
|
|
#ifdef DEBUG
|
|
int i;
|
|
// Should have been zero-initialized
|
|
for (i = 0; i < ARRAYSIZE(_rgebi); i++)
|
|
{
|
|
|
|
ASSERT(IsEqualGUID(_rgebi[i].clsid, GUID_NULL));
|
|
ASSERT(_rgebi[i].pwszName == NULL);
|
|
ASSERT(_rgebi[i].pwszHelp == NULL);
|
|
}
|
|
#endif
|
|
|
|
if ((!SHRegGetBoolUSValue(TEXT("SOFTWARE\\Microsoft\\Internet Explorer\\Main"), TEXT("Enable Browser Extensions"), FALSE, TRUE))
|
|
|| (GetSystemMetrics(SM_CLEANBOOT)!=0))
|
|
{
|
|
return;
|
|
}
|
|
|
|
HKEY hkey;
|
|
DWORD dwClsidIndex = 0;
|
|
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_KEY_BANDSTATE, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
|
|
{
|
|
TCHAR tszReg[MAX_PATH];
|
|
StrCpy(tszReg, TEXT("CLSID\\"));
|
|
const int cchClsidPrefix = 6; // 6 = strlen("CLSID\\")
|
|
LPTSTR ptszClsid = tszReg + cchClsidPrefix;
|
|
DWORD cchClsid;
|
|
for (DWORD dwIndex = 0;
|
|
cchClsid = ARRAYSIZE(tszReg) - cchClsidPrefix,
|
|
dwClsidIndex < ARRAYSIZE(_rgebi) &&
|
|
RegEnumValue( hkey, dwIndex, ptszClsid, &cchClsid, NULL, NULL, NULL, NULL ) == ERROR_SUCCESS;
|
|
dwIndex++)
|
|
{
|
|
CLSID clsid;
|
|
|
|
// We want to ignore the radio toolband {8E718888-423F-11D2-876E-00A0C9082467}
|
|
// without affecting its existing registration. Makes uninstall easier.
|
|
if (GUIDFromString( ptszClsid, &clsid )
|
|
&& StrCmpI(ptszClsid, TEXT("{8E718888-423F-11D2-876E-00A0C9082467}")))
|
|
{
|
|
HKEY hkeyClsid;
|
|
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, tszReg, 0, KEY_READ, &hkeyClsid) == ERROR_SUCCESS)
|
|
{
|
|
// Don't save the CLSID until we're sure it worked
|
|
_rgebi[dwClsidIndex].clsid = clsid;
|
|
|
|
WCHAR wszBuf[MAX_PATH];
|
|
|
|
// Get the name; use SHLoadRegUIString so the app can localize
|
|
SHLoadRegUIStringW( hkeyClsid, L"", wszBuf, ARRAYSIZE(wszBuf) );
|
|
Str_SetPtrW( &_rgebi[dwClsidIndex].pwszName, wszBuf);
|
|
|
|
// Get the help; use SHLoadRegUIString so the app can localize
|
|
SHLoadRegUIStringW( hkeyClsid, L"HelpText", wszBuf, ARRAYSIZE(wszBuf) );
|
|
Str_SetPtrW( &_rgebi[dwClsidIndex].pwszHelp, wszBuf);
|
|
|
|
RegCloseKey(hkeyClsid);
|
|
|
|
dwClsidIndex++;
|
|
}
|
|
}
|
|
}
|
|
RegCloseKey( hkey );
|
|
}
|
|
}
|
|
|
|
CInternetToolbar::CInternetToolbar() : CBaseBar(), _yCapture(-1), _iButtons(-1)
|
|
#ifdef EDIT_HACK
|
|
, _iEditIcon(-1), _cxEditGlyph(-1), _cyEditGlyph(-1)
|
|
#endif
|
|
{
|
|
DllAddRef();
|
|
|
|
if (GetSystemMetrics(SM_CXSCREEN) < 650)
|
|
_uiMaxTBWidth = MAX_TB_WIDTH_LORES;
|
|
else
|
|
_uiMaxTBWidth = MAX_TB_WIDTH_HIRES;
|
|
|
|
ASSERT(_fLoading == FALSE);
|
|
ASSERT(_hwnd == NULL);
|
|
ASSERT(_btb._guidCurrentButtonGroup == CLSID_NULL);
|
|
_btb._nNextCommandID = 1000;
|
|
|
|
DWORD dwResult = FALSE, dwType, dwcbData = sizeof(dwResult), dwDefault = TRUE;
|
|
SHRegGetUSValue(c_szRegKeyCoolbar, TEXT("Locked"), &dwType, &dwResult, &dwcbData, FALSE, &dwDefault, sizeof(dwDefault));
|
|
SHSetValue(HKEY_CURRENT_USER, c_szRegKeyCoolbar, TEXT("Locked"), REG_DWORD, &dwResult, sizeof(dwResult));
|
|
_fLockedToolbar = dwResult;
|
|
|
|
_LoadExternalBandInfo();
|
|
}
|
|
|
|
void CInternetToolbar::_Unadvise(void)
|
|
{
|
|
if(_dwcpCookie)
|
|
{
|
|
ConnectToConnectionPoint(NULL, DIID_DWebBrowserEvents2, FALSE, _pdie, &_dwcpCookie, NULL);
|
|
}
|
|
}
|
|
|
|
int CALLBACK DeleteDPAPtrCB(void *pItem, void *pData)
|
|
{
|
|
if ( pItem )
|
|
{
|
|
ASSERT( ::LocalSize(pItem) == sizeof(FOLDERSEARCHITEM) );
|
|
LocalFree(pItem);
|
|
pItem = NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
CInternetToolbar::~CInternetToolbar()
|
|
{
|
|
ATOMICRELEASE(_pdie);
|
|
|
|
if(_pbp && _fCreatedBandProxy)
|
|
{
|
|
_pbp->SetSite(NULL);
|
|
}
|
|
|
|
if (IsWindow(_hwnd))
|
|
{
|
|
DestroyWindow(_hwnd);
|
|
}
|
|
|
|
ATOMICRELEASE(_pbp);
|
|
|
|
ASSERT(!_ptbsite && !_ptbsitect && !_psp && !_pbs && !_pbs2);
|
|
SetSite(NULL);
|
|
|
|
if ( _hdpaFSI )
|
|
{
|
|
DPA_DestroyCallback(_hdpaFSI, DeleteDPAPtrCB, NULL);
|
|
_hdpaFSI = NULL;
|
|
}
|
|
|
|
for (int i = 0; i < ARRAYSIZE(_rgebi); i++)
|
|
{
|
|
Str_SetPtrW( &_rgebi[i].pwszName, NULL);
|
|
Str_SetPtrW( &_rgebi[i].pwszHelp, NULL);
|
|
}
|
|
|
|
TraceMsg(TF_SHDLIFE, "dtor CInternetToolbar %x", this);
|
|
DllRelease();
|
|
}
|
|
|
|
#define IID_DWebBrowserEvents DIID_DWebBrowserEvents
|
|
|
|
|
|
HRESULT CInternetToolbar::QueryInterface(REFIID riid, void ** ppvObj)
|
|
{
|
|
static const QITAB qit[] = {
|
|
// perf: last tuned 980728
|
|
QITABENTMULTI(CInternetToolbar, IDispatch, DWebBrowserEvents), // IID_IDispatch
|
|
QITABENT(CInternetToolbar, IExplorerToolbar), // IID_IDispatch
|
|
QITABENT(CInternetToolbar, IObjectWithSite), // IID_IObjectWithSite
|
|
QITABENT(CInternetToolbar, IPersistStreamInit), // IID_IPersistStreamInit
|
|
QITABENT(CInternetToolbar, IDockingWindow), // IID_IDockingWindow
|
|
QITABENT(CInternetToolbar, DWebBrowserEvents), // IID_DWebBrowserEvents
|
|
QITABENT(CInternetToolbar, IShellChangeNotify), // rare IID_IShellChangeNotify
|
|
QITABENT(CInternetToolbar, ISearchItems), // rare IID_ISearchItems
|
|
{ 0 },
|
|
};
|
|
|
|
HRESULT hres = QISearch(this, qit, riid, ppvObj);
|
|
if (FAILED(hres))
|
|
hres = SUPERCLASS::QueryInterface(riid, ppvObj);
|
|
|
|
return hres;
|
|
}
|
|
|
|
/* IDispatch methods */
|
|
HRESULT CInternetToolbar::GetTypeInfoCount(UINT *pctinfo)
|
|
{
|
|
return(E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT CInternetToolbar::GetTypeInfo(UINT itinfo,LCID lcid,ITypeInfo **pptinfo)
|
|
{
|
|
return(E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT CInternetToolbar::GetIDsOfNames(REFIID riid,OLECHAR **rgszNames,UINT cNames,
|
|
LCID lcid, DISPID * rgdispid)
|
|
{
|
|
return(E_NOTIMPL);
|
|
}
|
|
|
|
#if 0
|
|
// NOTE - StevePro changed it so this code isnt called
|
|
// this is a goodness, because it calls SHVerbExists() which
|
|
// is a TCHAR API, that is actually compiled as an ANSI API
|
|
// and since we are UNICODE it just always fails.
|
|
// leaving this in so that we know about the issue of
|
|
// frontpad.exe possibly needing to be disabled.
|
|
BOOL _ShowEditForExtension(LPCTSTR pszExtension)
|
|
{
|
|
TCHAR szBuf[MAX_PATH];
|
|
if (SHVerbExists(pszExtension, TEXT("edit"), szBuf))
|
|
{
|
|
// don't show it if it's just our own
|
|
if (StrStrI(szBuf, TEXT("frontpad.exe")))
|
|
{
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
#ifdef EDIT_HACK
|
|
//+-------------------------------------------------------------------------
|
|
// This function scans the html document for META tags that indicate the
|
|
// program that was used to create the HTML page. Examples are:
|
|
//
|
|
// <meta name="ProgID" content="word.document" >
|
|
// <meta name="ProgID" content="excel.sheet" >
|
|
//
|
|
// If a match is found, the content of the first match is returned. This
|
|
// progid is used to edit the document.
|
|
//--------------------------------------------------------------------------
|
|
BSTR CInternetToolbar::_GetEditProgID(IHTMLDocument2* pHTMLDocument)
|
|
{
|
|
BSTR bstrProgID = NULL;
|
|
|
|
//
|
|
// First get all document elements. Note that this is very fast in
|
|
// ie5 because the collection directly accesses the internal tree.
|
|
//
|
|
IHTMLElementCollection * pAllCollection;
|
|
if (SUCCEEDED(pHTMLDocument->get_all(&pAllCollection)))
|
|
{
|
|
IHTMLMetaElement* pMetaElement;
|
|
IHTMLBodyElement* pBodyElement;
|
|
IHTMLFrameSetElement* pFrameSetElement;
|
|
IDispatch* pDispItem;
|
|
|
|
//
|
|
// Now we scan the document for meta tags. Since these must reside in
|
|
// in the head, and since Trident always creates a body tag, we can
|
|
// stop looking when we hit the body.
|
|
//
|
|
// Note, the alternative of using pAllCollection->tags to return the
|
|
// collection of meta tags is likely more expensive because it will
|
|
// walk the whole tree (unless Trident optimizes this).
|
|
//
|
|
long lItemCnt;
|
|
VARIANT vEmpty;
|
|
V_VT(&vEmpty) = VT_EMPTY;
|
|
|
|
VARIANT vIndex;
|
|
V_VT(&vIndex) = VT_I4;
|
|
|
|
EVAL(SUCCEEDED(pAllCollection->get_length(&lItemCnt)));
|
|
|
|
for (long lItem = 0; lItem < lItemCnt; lItem++)
|
|
{
|
|
V_I4(&vIndex) = lItem;
|
|
|
|
if (S_OK == pAllCollection->item(vIndex, vEmpty, &pDispItem))
|
|
{
|
|
//
|
|
// First see if it's a meta tag
|
|
//
|
|
if (SUCCEEDED(pDispItem->QueryInterface(IID_PPV_ARG(IHTMLMetaElement, &pMetaElement))))
|
|
{
|
|
BSTR bstrName = NULL;
|
|
|
|
//
|
|
// We have a META element, check its NAME and CONTENT
|
|
//
|
|
if ( SUCCEEDED(pMetaElement->get_name(&bstrName)) && (bstrName != NULL) &&
|
|
(StrCmpIW(bstrName, OLESTR("ProgId")) == 0) &&
|
|
SUCCEEDED(pMetaElement->get_content(&bstrProgID)) && (bstrProgID != NULL)
|
|
)
|
|
{
|
|
// We got the ProgID, so terminate the search;
|
|
lItem = lItemCnt;
|
|
}
|
|
|
|
if (bstrName != NULL)
|
|
SysFreeString(bstrName);
|
|
|
|
pMetaElement->Release();
|
|
}
|
|
//
|
|
// Next check for the body tag
|
|
//
|
|
else if (SUCCEEDED(pDispItem->QueryInterface(IID_PPV_ARG(IHTMLBodyElement, &pBodyElement))))
|
|
{
|
|
// Found the body tag, so terminate the search
|
|
lItem = lItemCnt;
|
|
pBodyElement->Release();
|
|
}
|
|
//
|
|
// Finally, check for a frameset tag
|
|
//
|
|
else if (SUCCEEDED(pDispItem->QueryInterface(IID_PPV_ARG(IHTMLFrameSetElement, &pFrameSetElement))))
|
|
{
|
|
// Found a frameset tag, so terminate the search
|
|
lItem = lItemCnt;
|
|
pFrameSetElement->Release();
|
|
}
|
|
pDispItem->Release();
|
|
}
|
|
}
|
|
// Make sure that these don't have to be cleared (should not have been modified)
|
|
ASSERT(vEmpty.vt == VT_EMPTY);
|
|
ASSERT(vIndex.vt == VT_I4);
|
|
|
|
pAllCollection->Release();
|
|
}
|
|
|
|
return bstrProgID;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Returns grey-scale image from the icon passed in.
|
|
//--------------------------------------------------------------------------
|
|
HIMAGELIST CInternetToolbar::_CreateGrayScaleImagelist(HBITMAP hbmpImage, HBITMAP hbmpMask)
|
|
{
|
|
// Determine the button dimensions
|
|
int cx = g_fSmallIcons ? TB_SMBMP_CX : g_iToolBarLargeIconWidth;
|
|
int cy = g_fSmallIcons ? TB_SMBMP_CY : g_iToolBarLargeIconHeight;
|
|
|
|
// Start with a 24 bit color image list
|
|
HIMAGELIST himlEdit = ImageList_Create(cx, cy, ILC_COLOR24 | ILC_MASK, 1, 1);
|
|
if (NULL == himlEdit)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
ImageList_Add(himlEdit, hbmpImage, hbmpMask);
|
|
|
|
// Get the dib section from the image list
|
|
IMAGEINFO ii;
|
|
if (ImageList_GetImageInfo(himlEdit, 0, &ii))
|
|
{
|
|
DIBSECTION ds = {0};
|
|
if (GetObject(ii.hbmImage, sizeof(ds), &ds))
|
|
{
|
|
//
|
|
// Map each pixel to a monochrome equivalent.
|
|
//
|
|
BYTE* pBits = (BYTE*)ds.dsBm.bmBits;
|
|
BYTE* pScan = pBits;
|
|
int xWid = ds.dsBm.bmWidth;
|
|
int yHei = ds.dsBm.bmHeight;
|
|
long cbScan = ((xWid * 24 + 31) & ~31) / 8;
|
|
|
|
for (int y=0; y < yHei; ++y)
|
|
{
|
|
for (int x=0; x < xWid; ++x)
|
|
{
|
|
//
|
|
// Map to equivalent gray color by setting r,g,b to the same value.
|
|
// Using the average of r,g,b can be too dark, and using the max
|
|
// of r,g,b can be too bright. So, as a simple algorithm we use
|
|
// the average of the two schemes. This is cheaper than using true
|
|
// intensity matching.
|
|
//
|
|
BYTE nMax = max(max(pScan[0], pScan[1]), pScan[2]);
|
|
BYTE nAve = ((UINT)pScan[0] + pScan[1] + pScan[2])/3;
|
|
pScan[0] = pScan[1] = pScan[2] = ((UINT)nMax + nAve)/2;
|
|
|
|
// Increment to next pixel
|
|
pScan += 3;
|
|
}
|
|
|
|
// Increment to the next scan line
|
|
pBits += cbScan;
|
|
pScan = pBits;
|
|
}
|
|
}
|
|
}
|
|
return himlEdit;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Returns image and mask bitmaps for the desired image list item
|
|
//--------------------------------------------------------------------------
|
|
BOOL MyImageList_GetBitmaps
|
|
(
|
|
HIMAGELIST himl, // image list to use
|
|
int iImage, // image to copy
|
|
int x, // x-offset to draw in bitmap
|
|
int y, // x-offset to draw in bitmap
|
|
int cx, // width of bitmap
|
|
int cy, // height of bitmap
|
|
HBITMAP* phbmpImage, // returned color bitmap
|
|
HBITMAP* phbmpMask // returned mask bitmap
|
|
)
|
|
{
|
|
ASSERT(phbmpImage);
|
|
ASSERT(phbmpMask);
|
|
|
|
BOOL fRet = FALSE;
|
|
HDC hdc = GetDC(NULL);
|
|
|
|
if (hdc)
|
|
{
|
|
HDC hdcDst = CreateCompatibleDC(hdc);
|
|
if (hdcDst)
|
|
{
|
|
HBITMAP hbmpImage = CreateCompatibleBitmap(hdc, cx, cy);
|
|
if (hbmpImage)
|
|
{
|
|
HBITMAP hbmpMask = CreateBitmap(cx, cy, 1, 1, NULL);
|
|
if (hbmpMask)
|
|
{
|
|
// Draw mask bitmap
|
|
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcDst, hbmpMask);
|
|
PatBlt(hdcDst, 0, 0, cx, cy, WHITENESS);
|
|
ImageList_Draw(himl, iImage, hdcDst, x, y, ILD_MASK);
|
|
|
|
// Draw image bitmap
|
|
SelectObject(hdcDst, hbmpImage);
|
|
ImageList_Draw(himl, iImage, hdcDst, x, y, ILD_NORMAL);
|
|
|
|
SelectObject(hdcDst, hbmpOld);
|
|
|
|
*phbmpImage = hbmpImage;
|
|
*phbmpMask = hbmpMask;
|
|
fRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DeleteObject(hbmpImage);
|
|
}
|
|
}
|
|
DeleteDC(hdcDst);
|
|
}
|
|
ReleaseDC(NULL, hdc);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
extern HBITMAP CreateMirroredBitmap( HBITMAP hbmOrig);
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Creates a special image list for the edit button and configures the edit
|
|
// button to use it. If the hIcon is -1, the edit button is reset to use
|
|
// it's default glyph.
|
|
//--------------------------------------------------------------------------
|
|
void CInternetToolbar::_SetEditGlyph
|
|
(
|
|
int iIcon // new edit button glyph, index into shell image cache
|
|
)
|
|
{
|
|
// If no toolbar, we just need to see if we need to free the old image lists.
|
|
if (_btb._hwnd == NULL)
|
|
{
|
|
if (iIcon == -1)
|
|
{
|
|
if (_himlEdit)
|
|
{
|
|
ImageList_Destroy(_himlEdit);
|
|
_himlEdit = NULL;
|
|
}
|
|
if (_himlEditHot)
|
|
{
|
|
ImageList_Destroy(_himlEditHot);
|
|
_himlEditHot = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Can't set the glyph if no toolbar!
|
|
ASSERT(FALSE);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Determine the button dimensions
|
|
int cx = g_fSmallIcons ? TB_SMBMP_CX : g_iToolBarLargeIconWidth;
|
|
int cy = g_fSmallIcons ? TB_SMBMP_CY : g_iToolBarLargeIconHeight;
|
|
|
|
|
|
UINT uiCmd = -1;
|
|
// Dochost merges under one of two clsids, so have to check both
|
|
if (FAILED(_btb._ConvertCmd(&CLSID_InternetButtons, DVIDM_EDITPAGE, NULL, &uiCmd)) &&
|
|
FAILED(_btb._ConvertCmd(&CLSID_MSOButtons, DVIDM_EDITPAGE, NULL, &uiCmd)))
|
|
{
|
|
// The edit button is not on toolbar, so free the edit glyphs
|
|
iIcon = -1;
|
|
}
|
|
|
|
// If the current icon is already set, we are done
|
|
if ((_iEditIcon == iIcon) && (_cxEditGlyph == cx) && (_cyEditGlyph == cy))
|
|
{
|
|
if (_himlEdit)
|
|
{
|
|
// Set up the new image lists
|
|
SendMessage(_btb._hwnd, TB_SETIMAGELIST, IL_EDITBUTTON, (LPARAM)_himlEdit);
|
|
if (_himlEditHot)
|
|
{
|
|
SendMessage(_btb._hwnd, TB_SETHOTIMAGELIST, IL_EDITBUTTON, (LPARAM)_himlEditHot);
|
|
}
|
|
|
|
// Redirect the edit button to the new image list
|
|
TBBUTTONINFO tbi = {0};
|
|
tbi.cbSize = sizeof(tbi);
|
|
tbi.dwMask = TBIF_IMAGE;
|
|
tbi.iImage = MAKELONG(0, IL_EDITBUTTON);
|
|
|
|
SendMessage(_btb._hwnd, TB_SETBUTTONINFO, uiCmd, (LPARAM)&tbi);
|
|
}
|
|
return;
|
|
}
|
|
|
|
_iEditIcon = iIcon;
|
|
_cxEditGlyph = cx;
|
|
_cyEditGlyph = cy;
|
|
|
|
if (-1 == iIcon)
|
|
{
|
|
if (_himlEdit)
|
|
{
|
|
if (uiCmd != -1)
|
|
{
|
|
// Reset to the original edit glyph
|
|
TBBUTTONINFO tbi = {0};
|
|
tbi.cbSize = sizeof(tbi);
|
|
tbi.dwMask = TBIF_IMAGE;
|
|
tbi.iImage = EDITGLYPH_OFFSET;
|
|
SendMessage(_btb._hwnd, TB_SETBUTTONINFO, uiCmd, (LPARAM)&tbi);
|
|
}
|
|
|
|
// Destroy the custom edit glyphs. Note that we have to reset the primary image list
|
|
// or the image sizes are messed up.
|
|
SendMessage(_btb._hwnd, TB_SETIMAGELIST, IL_EDITBUTTON, (LPARAM)NULL);
|
|
ImageList_Destroy(_himlEdit);
|
|
_himlEdit = NULL;
|
|
}
|
|
|
|
if (_himlEditHot)
|
|
{
|
|
SendMessage(_btb._hwnd, TB_SETHOTIMAGELIST, IL_EDITBUTTON, (LPARAM)NULL);
|
|
ImageList_Destroy(_himlEditHot);
|
|
_himlEditHot = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Get the image bitmaps
|
|
HBITMAP hbmpImage = NULL;
|
|
HBITMAP hbmpMask = NULL;
|
|
BOOL bMirrored = IS_WINDOW_RTL_MIRRORED(_btb._hwnd);
|
|
HIMAGELIST himlSmall;
|
|
int cxSmall;
|
|
int cySmall;
|
|
|
|
if (Shell_GetImageLists(NULL, &himlSmall) &&
|
|
ImageList_GetIconSize(himlSmall, &cxSmall, &cySmall) &&
|
|
MyImageList_GetBitmaps(himlSmall, iIcon, (cx - cxSmall)/2, (cy - cySmall)/2,
|
|
cx, cy, &hbmpImage, &hbmpMask))
|
|
{
|
|
|
|
if (bMirrored)
|
|
{
|
|
HBITMAP hbmpTemp;
|
|
|
|
hbmpTemp = CreateMirroredBitmap(hbmpImage);
|
|
if (hbmpTemp)
|
|
{
|
|
DeleteObject(hbmpImage);
|
|
hbmpImage = hbmpTemp;
|
|
}
|
|
hbmpTemp = CreateMirroredBitmap(hbmpMask);
|
|
if (hbmpTemp)
|
|
{
|
|
DeleteObject(hbmpMask);
|
|
hbmpMask = hbmpTemp;
|
|
}
|
|
}
|
|
// Create a monochrome glyph for the edit button
|
|
HIMAGELIST himlEdit = _CreateGrayScaleImagelist(hbmpImage, hbmpMask);
|
|
SendMessage(_btb._hwnd, TB_SETIMAGELIST, IL_EDITBUTTON, (LPARAM)himlEdit);
|
|
if (_himlEdit)
|
|
{
|
|
ImageList_Destroy(_himlEdit);
|
|
}
|
|
_himlEdit = himlEdit;
|
|
|
|
// Create a hot glyph for the edit button
|
|
HIMAGELIST himlEditHot = ImageList_Create(cx, cy, ILC_COLORDDB | ILC_MASK, 1, 1);
|
|
int nIndex = ImageList_Add(himlEditHot, hbmpImage, hbmpMask);
|
|
|
|
SendMessage(_btb._hwnd, TB_SETHOTIMAGELIST, IL_EDITBUTTON, (LPARAM)himlEditHot);
|
|
if (_himlEditHot)
|
|
{
|
|
ImageList_Destroy(_himlEditHot);
|
|
}
|
|
_himlEditHot = himlEditHot;
|
|
|
|
// Redirect the edit button to the new image list
|
|
if (_himlEdit)
|
|
{
|
|
TBBUTTONINFO tbi = {0};
|
|
tbi.cbSize = sizeof(tbi);
|
|
tbi.dwMask = TBIF_IMAGE;
|
|
tbi.iImage = MAKELONG(nIndex, IL_EDITBUTTON);
|
|
|
|
SendMessage(_btb._hwnd, TB_SETBUTTONINFO, uiCmd, (LPARAM)&tbi);
|
|
}
|
|
|
|
DeleteObject(hbmpImage);
|
|
DeleteObject(hbmpMask);
|
|
|
|
}
|
|
else
|
|
{
|
|
// Couldn't create images so use the default edit glyph
|
|
_SetEditGlyph(-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Initializes the edit button to display a drop-down menu if there are
|
|
// multiple verbs. Also optionally displays a custion glyph.
|
|
//--------------------------------------------------------------------------
|
|
void CInternetToolbar::_InitEditButtonStyle()
|
|
{
|
|
// If we have or want a custon edit glyph, load it
|
|
_SetEditGlyph(_aEditVerb.GetIcon());
|
|
|
|
UINT uiCmd;
|
|
|
|
// Dochost merges under one of two clsids, so have to check both
|
|
if (SUCCEEDED(_btb._ConvertCmd(&CLSID_InternetButtons, DVIDM_EDITPAGE, NULL, &uiCmd)) ||
|
|
SUCCEEDED(_btb._ConvertCmd(&CLSID_MSOButtons, DVIDM_EDITPAGE, NULL, &uiCmd)))
|
|
{
|
|
ASSERT(uiCmd != -1);
|
|
|
|
// If multiple verbs, make the button a split button
|
|
TBBUTTONINFO tbi = {0};
|
|
tbi.cbSize = sizeof(tbi);
|
|
tbi.dwMask = TBIF_STYLE | TBIF_STATE;
|
|
tbi.fsState = 0;
|
|
|
|
if (_aEditVerb.GetSize() > 1)
|
|
{
|
|
tbi.fsStyle |= BTNS_DROPDOWN;
|
|
}
|
|
|
|
if (_aEditVerb.GetSize() > 0)
|
|
{
|
|
tbi.fsState = TBSTATE_ENABLED;
|
|
}
|
|
SendMessage(_btb._hwnd, TB_SETBUTTONINFO, uiCmd, (LPARAM)&tbi);
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// If the edit button is displaying a custon glyph, this function reloads
|
|
// the glyph.
|
|
//--------------------------------------------------------------------------
|
|
void CInternetToolbar::_RefreshEditGlyph()
|
|
{
|
|
// If we have a custon edit glyph, reload it
|
|
if (_himlEdit)
|
|
{
|
|
// Refresh the edit glyph
|
|
_iEditIcon = -1;
|
|
_InitEditButtonStyle();
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Updates the edit button based on the document type currently loaded
|
|
//--------------------------------------------------------------------------
|
|
void CInternetToolbar::_UpdateEditButton()
|
|
{
|
|
_aEditVerb.RemoveAll();
|
|
_fEditEnabled = FALSE;
|
|
BOOL fNoEditSpecified = FALSE;
|
|
|
|
//
|
|
// First add editors associated with the url
|
|
//
|
|
BSTR bstrUrl = NULL;
|
|
_pdie->get_LocationURL(&bstrUrl);
|
|
if (bstrUrl)
|
|
{
|
|
LPTSTR pszExt;
|
|
//
|
|
// Find the cache file associated with the url. The file extension for this entry
|
|
// is based off of the mime type. (Note that get_mimeType on the document
|
|
// returns a frindly name that is hard to translate back to an actual mimetype.
|
|
// So we use the file extension instead.)
|
|
//
|
|
WCHAR szCacheFileName[MAX_PATH];
|
|
*szCacheFileName = 0;
|
|
if (FAILED(URLToCacheFile(bstrUrl, szCacheFileName, ARRAYSIZE(szCacheFileName))))
|
|
{
|
|
// If we can't get a file associated with the url, probably want to disable the edit button
|
|
// because most apps need a file to edit.
|
|
SysFreeString(bstrUrl);
|
|
return;
|
|
}
|
|
|
|
pszExt = PathFindExtension(szCacheFileName);
|
|
|
|
// bug 79055 - The cache has a bug where some html entries are not
|
|
// given a file extension. Too risky to fix for 5.x, so we'll just
|
|
// assume .htm for http if no extension is present.
|
|
if (L'\0' == *pszExt && GetUrlScheme(bstrUrl) == URL_SCHEME_HTTP)
|
|
{
|
|
StrCpyN(szCacheFileName, L".htm", ARRAYSIZE(szCacheFileName));
|
|
pszExt = szCacheFileName;
|
|
}
|
|
|
|
if (*pszExt)
|
|
{
|
|
_aEditVerb.Add(pszExt);
|
|
|
|
// If ".html", use the ".htm" editors too
|
|
if (StrCmpI(pszExt, L".html") == 0 )
|
|
{
|
|
// This is an html document, so add the .htm editors
|
|
if (!_aEditVerb.Add(TEXT(".htm")) && StrCmpI(pszExt, L".html") != 0)
|
|
{
|
|
_aEditVerb.Add(TEXT(".html"));
|
|
}
|
|
}
|
|
}
|
|
|
|
SysFreeString(bstrUrl);
|
|
}
|
|
|
|
//
|
|
// See if the feature to search the doc for the progid is enabled
|
|
//
|
|
static int fCheckDocForProgID = -1;
|
|
if (fCheckDocForProgID == -1)
|
|
{
|
|
fCheckDocForProgID = SHRegGetBoolUSValue(REGSTR_PATH_MAIN,
|
|
TEXT("CheckDocumentForProgID"), FALSE, TRUE) ? 1 : 0;
|
|
}
|
|
|
|
// Check for a meta tag that specifies a progid for editing this document
|
|
if (fCheckDocForProgID)
|
|
{
|
|
//
|
|
// Next see if this is an html document with a progid
|
|
//
|
|
IWebBrowser2* pWB2 = NULL;
|
|
IDispatch * pDispatch = NULL;
|
|
IHTMLDocument2 * pHTMLDocument = NULL;
|
|
|
|
// Get the html document currently loaded
|
|
if (_psp &&
|
|
SUCCEEDED(_psp->QueryService(SID_SWebBrowserApp, IID_PPV_ARG(IWebBrowser2, &pWB2))) &&
|
|
SUCCEEDED(pWB2->get_Document(&pDispatch)) &&
|
|
SUCCEEDED(pDispatch->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pHTMLDocument))))
|
|
{
|
|
//
|
|
// Check the current document for a META tag specifying the program to use to
|
|
// edit this file.
|
|
//
|
|
BSTR bstrProgID = _GetEditProgID(pHTMLDocument);
|
|
if (bstrProgID)
|
|
{
|
|
if (lstrcmpi(bstrProgID, TEXT("NoEdit")) == 0)
|
|
{
|
|
fNoEditSpecified = TRUE;
|
|
}
|
|
else
|
|
{
|
|
USES_CONVERSION;
|
|
_aEditVerb.Add(W2T(bstrProgID));
|
|
SysFreeString(bstrProgID);
|
|
}
|
|
}
|
|
}
|
|
|
|
SAFERELEASE(pWB2);
|
|
SAFERELEASE(pDispatch);
|
|
SAFERELEASE(pHTMLDocument);
|
|
}
|
|
|
|
|
|
if (!fNoEditSpecified)
|
|
{
|
|
_fEditEnabled = (_aEditVerb.GetSize() > 0);
|
|
}
|
|
|
|
// Update edit glyph, drop-down style, & enabled state
|
|
_InitEditButtonStyle();
|
|
}
|
|
#endif //EDIT_HACK
|
|
|
|
HRESULT CInternetToolbar::Invoke(DISPID dispidMember,REFIID riid,LCID lcid,WORD wFlags,
|
|
DISPPARAMS * pdispparams, VARIANT * pvarResult,
|
|
EXCEPINFO * pexcepinfo,UINT * puArgErr)
|
|
{
|
|
if(!pdispparams)
|
|
return E_INVALIDARG;
|
|
|
|
switch(dispidMember)
|
|
{
|
|
|
|
case DISPID_NAVIGATECOMPLETE2:
|
|
{
|
|
//
|
|
// Notify the brand and theater mode objects about whether we're in shell or
|
|
// web mode. Wait til now to do it (rather than doing it in SetCommandTarget)
|
|
// because they might want to ask the browser about the new pidl, which isn't
|
|
// yet filled in at SetCommandTarget time.
|
|
//
|
|
DWORD nCmdexecopt = _fShellView ? CITE_SHELL : CITE_INTERNET;
|
|
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_BRAND);
|
|
if (pbid)
|
|
{
|
|
IUnknown_Exec(pbid->pdb, &CGID_PrivCITCommands, CITIDM_ONINTERNET, nCmdexecopt, NULL, NULL);
|
|
}
|
|
|
|
if (_fTheater)
|
|
{
|
|
IUnknown_Exec(_ptbsite, &CGID_Theater, THID_ONINTERNET, nCmdexecopt, NULL, NULL);
|
|
}
|
|
|
|
// If notification is not from a frame, set the _fNavigateComplete flag
|
|
for (DWORD i = 0; i < pdispparams->cArgs; i++)
|
|
{
|
|
if (pdispparams->rgvarg[i].vt == VT_DISPATCH)
|
|
{
|
|
// See who's sending us this event
|
|
IBrowserService* pbs = NULL;
|
|
HRESULT hr = IUnknown_QueryService(pdispparams->rgvarg[i].pdispVal, SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &pbs));
|
|
if (pbs)
|
|
{
|
|
// We don't really need this interface, just its address
|
|
pbs->Release();
|
|
}
|
|
if (SUCCEEDED(hr) && pbs == _pbs)
|
|
{
|
|
// Notification did not come from a frame,
|
|
_fNavigateComplete = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DISPID_BEFORENAVIGATE:
|
|
{
|
|
BOOL fWeb = FALSE;
|
|
|
|
ASSERT((pdispparams->rgvarg[5].vt == VT_BSTR) &&
|
|
(pdispparams->rgvarg[5].bstrVal != NULL));
|
|
|
|
PARSEDURL pu = { 0 };
|
|
USES_CONVERSION;
|
|
|
|
pu.cbSize = sizeof(pu);
|
|
ParseURL(W2T(pdispparams->rgvarg[5].bstrVal), &pu);
|
|
|
|
if ((URL_SCHEME_UNKNOWN != pu.nScheme) && (URL_SCHEME_FILE != pu.nScheme))
|
|
fWeb = TRUE;
|
|
|
|
UINT uiState = 0;
|
|
GetState(&CLSID_CommonButtons, TBIDM_STOPDOWNLOAD, &uiState);
|
|
|
|
if ((uiState & TBSTATE_HIDDEN) && fWeb)
|
|
{
|
|
|
|
_fTransitionToHTML = TRUE;
|
|
uiState &= ~TBSTATE_HIDDEN;
|
|
SetState(&CLSID_CommonButtons, TBIDM_STOPDOWNLOAD, uiState);
|
|
}
|
|
|
|
// Default to the edit button hidden
|
|
_fEditEnabled = FALSE;
|
|
}
|
|
break;
|
|
|
|
case DISPID_DOWNLOADBEGIN:// This is when we just started to navigate? No bits?
|
|
_StartDownload();
|
|
break;
|
|
|
|
case DISPID_DOWNLOADCOMPLETE: // we be done
|
|
_fTransitionToHTML = FALSE;
|
|
_StopDownload(FALSE);
|
|
break;
|
|
|
|
case DISPID_DOCUMENTCOMPLETE: // This is where we have all the bits
|
|
{
|
|
//
|
|
// Sometimes we get a premature document complete (for framesets). We can catch this
|
|
// by checking to see if we have received a DISPID_NAVIGATECOMPLETE2 event
|
|
// for the top window. We have to update the edit button here instead of in
|
|
// navigate complete because otherwise the document is not in the interactive
|
|
// state and our metatag search sees the previous document.
|
|
//
|
|
// REARCHITECT: Is it possible that this event came from a frame and the document is not
|
|
// interactive yet? Trident posts an interactive event right before calling us so
|
|
// we're probably ok. We don't want to wait for the document complete for the top window
|
|
// in framesets because it can take too long. Really need to sink DISPID_READYSTATECHANGE
|
|
// and wait for the document to go interactive.
|
|
//
|
|
if (_fNavigateComplete)
|
|
{
|
|
_fNavigateComplete = FALSE;
|
|
_UpdateEditButton();
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DISPID_COMMANDSTATECHANGE:
|
|
BOOL fEnable;
|
|
|
|
if(!pdispparams || (pdispparams->cArgs != 2) ||
|
|
(pdispparams->rgvarg[0].vt != VT_BOOL) ||
|
|
(pdispparams->rgvarg[1].vt != VT_I4))
|
|
return E_INVALIDARG;
|
|
|
|
fEnable = (BOOL) pdispparams->rgvarg[0].boolVal;
|
|
UINT uiCmd;
|
|
|
|
switch (pdispparams->rgvarg[1].lVal)
|
|
{
|
|
case CSC_UPDATECOMMANDS:
|
|
// corresponds to OLECMDID_UPDATECOMMANDS from Exec()
|
|
_UpdateToolbar(FALSE);
|
|
break;
|
|
|
|
case CSC_NAVIGATEBACK:
|
|
_fBackEnabled = fEnable;
|
|
_btb._ConvertCmd(&CLSID_CommonButtons, TBIDM_BACK, NULL, &uiCmd);
|
|
SendMessage(_btb._hwnd, TB_ENABLEBUTTON, uiCmd, MAKELONG(fEnable, 0));
|
|
break;
|
|
|
|
case CSC_NAVIGATEFORWARD:
|
|
_fForwardEnabled = fEnable;
|
|
_btb._ConvertCmd(&CLSID_CommonButtons, TBIDM_FORWARD, NULL, &uiCmd);
|
|
SendMessage(_btb._hwnd, TB_ENABLEBUTTON, uiCmd, MAKELONG(fEnable, 0));
|
|
break;
|
|
|
|
default:
|
|
return(E_INVALIDARG);
|
|
}
|
|
|
|
// FEATURE need to handle the case of navigation failure and
|
|
// do some cleanup
|
|
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// *** IInputObjectSite methods ***
|
|
|
|
HRESULT CInternetToolbar::OnFocusChangeIS(IUnknown *punk, BOOL fSetFocus)
|
|
{
|
|
return IUnknown_OnFocusChangeIS(_ptbsite, SAFECAST(this, IInputObject*), fSetFocus);
|
|
}
|
|
|
|
|
|
//*** CInternetToolbar::IInputObject::* {
|
|
|
|
HRESULT CInternetToolbar::TranslateAcceleratorIO(LPMSG lpMsg)
|
|
{
|
|
LPBANDITEMDATA pbid;
|
|
|
|
if (_fShow)
|
|
{
|
|
if (lpMsg->message == WM_KEYDOWN)
|
|
{
|
|
switch (lpMsg->wParam)
|
|
{
|
|
case VK_F4:
|
|
Laddrband:
|
|
if (_nVisibleBands & VBF_ADDRESS)
|
|
{
|
|
pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
|
|
if (EVAL(pbid))
|
|
{
|
|
HRESULT hrT;
|
|
|
|
hrT = IUnknown_TranslateAcceleratorIO(pbid->pdb, lpMsg);
|
|
ASSERT(hrT == S_OK);
|
|
}
|
|
}
|
|
return S_OK; // (even if we just eat it)
|
|
}
|
|
}
|
|
else if(lpMsg->message == WM_SYSCHAR)
|
|
{
|
|
static CHAR szAccel[2] = "\0";
|
|
CHAR szChar [2] = "\0";
|
|
|
|
if ('\0' == szAccel[0])
|
|
MLLoadStringA(IDS_ADDRBAND_ACCELLERATOR, szAccel, ARRAYSIZE(szAccel));
|
|
|
|
szChar[0] = (CHAR)lpMsg->wParam;
|
|
|
|
if (lstrcmpiA(szChar,szAccel) == 0)
|
|
{
|
|
goto Laddrband;
|
|
}
|
|
}
|
|
return _bs.TranslateAcceleratorIO(lpMsg);
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
// }
|
|
|
|
HRESULT CInternetToolbar::SetSite(IUnknown* punkSite)
|
|
{
|
|
ATOMICRELEASE(_ptbsite);
|
|
ATOMICRELEASE(_ptbsitect);
|
|
ATOMICRELEASE(_pbs);
|
|
ATOMICRELEASE(_pbs2);
|
|
ATOMICRELEASE(_psp);
|
|
|
|
_Unadvise();
|
|
|
|
ATOMICRELEASE(_pdie);
|
|
|
|
ASSERT(_ptbsite==NULL);
|
|
ASSERT(_ptbsitect==NULL);
|
|
ASSERT(_pbs==NULL);
|
|
ASSERT(_pbs2==NULL);
|
|
ASSERT(_pdie==NULL);
|
|
|
|
if (_pbp && _fCreatedBandProxy)
|
|
_pbp->SetSite(punkSite);
|
|
|
|
if (punkSite)
|
|
{
|
|
punkSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &_ptbsite));
|
|
punkSite->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &_ptbsitect));
|
|
punkSite->QueryInterface(IID_PPV_ARG(IBrowserService2, &_pbs2));
|
|
punkSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &_psp));
|
|
|
|
if (_psp)
|
|
{
|
|
_psp->QueryService(SID_SWebBrowserApp, IID_PPV_ARG(IWebBrowser2, &_pdie));
|
|
_psp->QueryService(SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &_pbs));
|
|
ASSERT(_pdie);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
SetClient(NULL);
|
|
}
|
|
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//***
|
|
//
|
|
void CInternetToolbar::_UpdateGroup(const GUID *pguidCmdGroup, int cnt,
|
|
OLECMD rgcmds[], const GUID* pguidButton, const int buttonsInternal[])
|
|
{
|
|
|
|
if (!IsEqualGUID(*pguidButton, CLSID_CommonButtons) &&
|
|
!IsEqualGUID(*pguidButton, _btb._guidCurrentButtonGroup))
|
|
return; // we don't have any buttons at this time, so no use checking
|
|
|
|
if (_ptbsitect)
|
|
{
|
|
_ptbsitect->QueryStatus(pguidCmdGroup, cnt, rgcmds, NULL);
|
|
|
|
// make sure stop is enabled while we are animating
|
|
if (_fAnimating && pguidCmdGroup == NULL && rgcmds[0].cmdID == OLECMDID_STOP)
|
|
{
|
|
rgcmds[0].cmdf = OLECMDF_ENABLED;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < cnt; i++)
|
|
{
|
|
// do nothing if command is not available or not in our table
|
|
if (rgcmds[i].cmdf & OLECMDF_SUPPORTED)
|
|
{
|
|
UINT idBut;
|
|
if (SUCCEEDED(_btb._ConvertCmd(pguidButton, buttonsInternal[i], NULL, (UINT*)&idBut)))
|
|
{
|
|
SendMessage(_btb._hwnd, TB_ENABLEBUTTON, idBut,
|
|
(rgcmds[i].cmdf & OLECMDF_ENABLED) ? TRUE : FALSE);
|
|
|
|
SendMessage(_btb._hwnd, TB_CHECKBUTTON, idBut,
|
|
(rgcmds[i].cmdf & OLECMDF_LATCHED) ? TRUE : FALSE);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void CInternetToolbar::_UpdateToolbar(BOOL fForce)
|
|
{
|
|
if (fForce || SHIsChildOrSelf(GetForegroundWindow(), _hwnd) == S_OK)
|
|
{
|
|
if (!_fUpdateToolbarTimer)
|
|
{
|
|
SetTimer(_hwnd, IDT_UPDATETOOLBAR, TIMEOUT_UPDATETOOLBAR, NULL);
|
|
_fUpdateToolbarTimer = TRUE;
|
|
_UpdateToolbarNow();
|
|
}
|
|
else
|
|
{
|
|
_fNeedUpdateToolbar = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL CInternetToolbar::_UpEnabled()
|
|
{
|
|
OLECMD rgcmd = { FCIDM_PREVIOUSFOLDER, 0 };
|
|
_ptbsitect->QueryStatus(&CGID_ShellBrowser, 1, &rgcmd, NULL);
|
|
|
|
return (rgcmd.cmdf & OLECMDF_ENABLED);
|
|
}
|
|
|
|
void CInternetToolbar::_UpdateCommonButton(int iCmd, UINT nCmdID)
|
|
{
|
|
switch (nCmdID)
|
|
{
|
|
case TBIDM_THEATER:
|
|
SendMessage(_btb._hwnd, TB_CHECKBUTTON, iCmd, _fTheater);
|
|
break;
|
|
|
|
case TBIDM_PREVIOUSFOLDER:
|
|
case TBIDM_BACK:
|
|
case TBIDM_FORWARD:
|
|
{
|
|
BOOL fEnabled;
|
|
|
|
switch (nCmdID)
|
|
{
|
|
case TBIDM_PREVIOUSFOLDER: fEnabled = _UpEnabled(); break;
|
|
case TBIDM_BACK: fEnabled = _fBackEnabled; break;
|
|
case TBIDM_FORWARD: fEnabled = _fForwardEnabled; break;
|
|
}
|
|
|
|
SendMessage(_btb._hwnd, TB_ENABLEBUTTON, iCmd, MAKELONG(fEnabled, 0));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CInternetToolbar::_UpdateToolbarNow()
|
|
{
|
|
_fNeedUpdateToolbar = FALSE;
|
|
|
|
{
|
|
// MUST not be static (due to ConvertCmd overwrite)
|
|
OLECMD rgcmds[] = {
|
|
{ OLECMDID_STOP, 0 }, // NOTE: must be first
|
|
{ OLECMDID_REFRESH, 0 },
|
|
};
|
|
|
|
static const int buttonsInternal[] = { // MUST be in same order as above array
|
|
TBIDM_STOPDOWNLOAD,
|
|
TBIDM_REFRESH,
|
|
};
|
|
_UpdateGroup(NULL, ARRAYSIZE(buttonsInternal), rgcmds, &CLSID_CommonButtons, buttonsInternal);
|
|
}
|
|
|
|
{
|
|
OLECMD rgcmds[] = {
|
|
{ SBCMDID_SEARCHBAR, 0 },
|
|
{ SBCMDID_FAVORITESBAR, 0 },
|
|
{ SBCMDID_HISTORYBAR, 0 },
|
|
{ SBCMDID_EXPLORERBAR, 0 },
|
|
{ SBCMDID_MEDIABAR, 0 },
|
|
};
|
|
static const int buttonsInternal[] = { // MUST be in same order as above array
|
|
TBIDM_SEARCH,
|
|
TBIDM_FAVORITES,
|
|
TBIDM_HISTORY,
|
|
TBIDM_ALLFOLDERS,
|
|
TBIDM_MEDIABAR,
|
|
};
|
|
|
|
_UpdateGroup(&CGID_Explorer, ARRAYSIZE(buttonsInternal), rgcmds, &CLSID_CommonButtons, buttonsInternal);
|
|
}
|
|
|
|
int nButtons = (int) SendMessage(_btb._hwnd, TB_BUTTONCOUNT, 0, 0L);
|
|
|
|
for (int nIndex = 0; nIndex < nButtons; nIndex++)
|
|
{
|
|
CMDMAP* pcm = _btb._GetCmdMapByIndex(nIndex);
|
|
if (pcm)
|
|
{
|
|
int iCmd = _btb._CommandFromIndex(nIndex);
|
|
if (IsEqualGUID(pcm->guidButtonGroup, CLSID_CommonButtons))
|
|
{
|
|
_UpdateCommonButton(iCmd, pcm->nCmdID);
|
|
}
|
|
else
|
|
{
|
|
// NOTE (andrewgu): ie5.5 b#106047 - the two conditions below used to be ASSERTs,
|
|
// the second one was faulting under stress. if either one of these checks fails,
|
|
// the button is stale.
|
|
if (IsEqualGUID(pcm->guidButtonGroup, _btb._guidCurrentButtonGroup) &&
|
|
NULL != _btb._pctCurrentButtonGroup)
|
|
{
|
|
OLECMD ocButton;
|
|
ocButton.cmdID = pcm->nCmdID;
|
|
ocButton.cmdf = 0;
|
|
|
|
if (SUCCEEDED(_btb._pctCurrentButtonGroup->QueryStatus(&pcm->guidButtonGroup, 1, &ocButton, NULL)))
|
|
{
|
|
SendMessage(_btb._hwnd, TB_ENABLEBUTTON, iCmd,
|
|
(ocButton.cmdf & OLECMDF_ENABLED) ? TRUE : FALSE);
|
|
|
|
SendMessage(_btb._hwnd, TB_CHECKBUTTON, iCmd,
|
|
(ocButton.cmdf & OLECMDF_LATCHED) ? TRUE : FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_btb._hwnd)
|
|
{
|
|
_btb._BandInfoChanged();
|
|
}
|
|
}
|
|
|
|
void CInternetToolbar::_StartDownload()
|
|
{
|
|
UINT uiCmd;
|
|
if (SUCCEEDED(_btb._ConvertCmd(&CLSID_CommonButtons, TBIDM_STOPDOWNLOAD, NULL, &uiCmd)))
|
|
{
|
|
SendMessage(_btb._hwnd, TB_ENABLEBUTTON, uiCmd, MAKELONG(TRUE, 0));
|
|
|
|
_fAnimating = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Parameters:
|
|
// fClosing -- TRUE only if we are calling this from CloseDW member.
|
|
// In that case, we can skip all UI-update code.
|
|
//
|
|
void CInternetToolbar::_StopDownload(BOOL fClosing)
|
|
{
|
|
_fAnimating = FALSE;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::CloseDW(DWORD dwReserved)
|
|
{
|
|
_fDestroyed = TRUE; // Stop using the member variables, they are invalid.
|
|
_StopDownload(TRUE);
|
|
|
|
ASSERT(!_btb._pcinfo);
|
|
ATOMICRELEASE(_btb._pctCurrentButtonGroup);
|
|
|
|
_btb._FreeBtnsAdded();
|
|
|
|
if (_btb._hwnd)
|
|
{
|
|
_btb._RemoveAllButtons();
|
|
|
|
SendMessage(_btb._hwnd, TB_SETIMAGELIST, 0, NULL);
|
|
SendMessage(_btb._hwnd, TB_SETHOTIMAGELIST, 0, NULL);
|
|
|
|
DSA_Destroy(_hdsaTBBMPs);
|
|
_hdsaTBBMPs = NULL; // So we don't try to re-destroy in _InitBitmapDSA()
|
|
}
|
|
#ifdef EDIT_HACK
|
|
_SetEditGlyph(-1);
|
|
#endif
|
|
|
|
_bs._Close();
|
|
|
|
SUPERCLASS::CloseDW(dwReserved);
|
|
|
|
_btb._hwnd = NULL;
|
|
|
|
// We advise during ShowDW, so unadvise here. Also, we hit a stress
|
|
// case where it seems that an event came in after closedw but before
|
|
// one of the other _Unadvise calls. This event percolated down to
|
|
// a reference to _hdsaCT which we freed above, causing a GPF.
|
|
//
|
|
_Unadvise();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CInternetToolbar::CITBandSite::v_SetTabstop(LPREBARBANDINFO prbbi)
|
|
{
|
|
// Don't set tabstops for all bands in the browser case. A band
|
|
// can still make itself a tabstop by setting WS_TABSTOP.
|
|
return;
|
|
}
|
|
|
|
BOOL CInternetToolbar::CITBandSite::_SetMinDimensions()
|
|
{
|
|
INT_PTR fRedraw = SendMessage(_hwnd, WM_SETREDRAW, FALSE, 0);
|
|
|
|
int icBands = (int) SendMessage( _hwnd, RB_GETBANDCOUNT, 0, 0 );
|
|
for (int i = 0; i < icBands; i++)
|
|
{
|
|
REBARBANDINFO rbbi;
|
|
rbbi.cbSize = sizeof(REBARBANDINFO);
|
|
rbbi.fMask = RBBIM_ID | RBBIM_CHILDSIZE;
|
|
if (SendMessage(_hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
|
|
{
|
|
LPBANDITEMDATA pbid = (LPBANDITEMDATA)_GetBandItemDataStructByID(rbbi.wID);
|
|
if (EVAL(pbid) && IS_VALID_HANDLE(pbid->hwnd, WND))
|
|
{
|
|
rbbi.cxMinChild = pbid->ptMinSize.x;
|
|
rbbi.cyMinChild = pbid->ptMinSize.y;
|
|
}
|
|
else
|
|
{
|
|
rbbi.cxMinChild = 0;
|
|
rbbi.cyMinChild = 0;
|
|
}
|
|
|
|
SendMessage(_hwnd, RB_SETBANDINFO, i, (LPARAM) &rbbi);
|
|
}
|
|
}
|
|
|
|
SendMessage(_hwnd, WM_SETREDRAW, fRedraw, 0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL HimlCacheDirty(IMLCACHE* pimlCache, BOOL fSmallIcons)
|
|
{
|
|
|
|
if (fSmallIcons != pimlCache->fSmallIcons)
|
|
return TRUE;
|
|
|
|
COLORREF cr3D = GetSysColor(COLOR_3DFACE);
|
|
|
|
if (cr3D != pimlCache->cr3D)
|
|
return TRUE;
|
|
|
|
if (SHUseClassicToolbarGlyphs() != pimlCache->fUseClassicGlyphs)
|
|
return TRUE;
|
|
|
|
for (int i = 0; i < CIMLISTS; i++)
|
|
if (!pimlCache->arhiml[i])
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
#define SZ_REGKEY_SMALLICONS REGSTR_PATH_EXPLORER TEXT("\\SmallIcons")
|
|
#define SZ_REGVALUE_SMALLICONS TEXT("SmallIcons")
|
|
|
|
BOOL _DefaultToSmallIcons()
|
|
{
|
|
// We default to small icons if:
|
|
//
|
|
// This is NT 5, or the policy says to use small icons, or this is any
|
|
// of the Whistler servers (server, adv server, dtc)
|
|
|
|
return ((GetUIVersion() == 5) || SHRestricted2(REST_SMALLICONS, NULL, 0) ||
|
|
(IsOS(OS_WHISTLERORGREATER) && IsOS(OS_ANYSERVER)));
|
|
}
|
|
|
|
BOOL _UseSmallIcons()
|
|
{
|
|
BOOL fDefaultToSmall = _DefaultToSmallIcons();
|
|
|
|
return SHRegGetBoolUSValue(SZ_REGKEY_SMALLICONS, SZ_REGVALUE_SMALLICONS,
|
|
FALSE, fDefaultToSmall);
|
|
}
|
|
|
|
|
|
BOOL _UseMapNetDrvBtns()
|
|
{
|
|
#define SZ_REGKEY_ADVFOLDER TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced")
|
|
#define SZ_REGVALUE_MAPNETDRV TEXT("MapNetDrvBtn")
|
|
|
|
DWORD dwData = 0;
|
|
if (GetUIVersion() >= 4)
|
|
{
|
|
DWORD cbData = sizeof(dwData);
|
|
DWORD dwDefault = 0;
|
|
DWORD cbDefault = sizeof(dwDefault);
|
|
|
|
SHRegGetUSValue(SZ_REGKEY_ADVFOLDER, SZ_REGVALUE_MAPNETDRV, NULL,
|
|
&dwData, &cbData, FALSE, &dwDefault, cbDefault);
|
|
}
|
|
return dwData;
|
|
}
|
|
|
|
HIMAGELIST _LoadThemedToolbarGlyphs(int idBmpType, int iTemperature, int cx, COLORREF crMask, UINT uFlags, BOOL bUseClassicGlyphs, HINSTANCE hInst);
|
|
|
|
void _LoadToolbarGlyphs(HWND hwnd, IMLCACHE *pimlCache, int cx, int idBmpType,
|
|
int iBitmapBaseIndex, BOOL bUseClassicGlyphs, HINSTANCE hInst)
|
|
{
|
|
// set uMsg and uFlags for first iteration of loop (default state)
|
|
UINT uMsg = TB_SETIMAGELIST;
|
|
UINT uFlags = LR_CREATEDIBSECTION;
|
|
int i;
|
|
HBITMAP hBMP;
|
|
BOOL fSmallIcons = g_fSmallIcons;
|
|
|
|
if (HimlCacheDirty(pimlCache, fSmallIcons))
|
|
{
|
|
COLORREF cr3D = GetSysColor(COLOR_3DFACE);
|
|
COLORREF crMask = RGB( 255, 0, 255 );
|
|
|
|
#ifdef UNIX
|
|
if (SHGetCurColorRes() < 2 )
|
|
{
|
|
crMask = CLR_NONE;
|
|
}
|
|
#endif
|
|
|
|
ENTERCRITICAL;
|
|
|
|
if (!HimlCacheDirty(pimlCache, fSmallIcons) )
|
|
goto DontReload;
|
|
|
|
for (i = 0; i < CIMLISTS; i++)
|
|
{
|
|
if ((!pimlCache->arhiml[i]) || (cr3D != pimlCache->cr3D) ||
|
|
(fSmallIcons != pimlCache->fSmallIcons) || (bUseClassicGlyphs != pimlCache->fUseClassicGlyphs))
|
|
{
|
|
TraceMsg(DM_ITBAR, "_LoadToolbarGlyphs: Loading New Images");
|
|
|
|
if (pimlCache->arhimlPendingDelete[i])
|
|
ImageList_Destroy(pimlCache->arhimlPendingDelete[i]);
|
|
|
|
pimlCache->arhimlPendingDelete[i] = pimlCache->arhiml[i];
|
|
|
|
pimlCache->arhiml[i] = _LoadThemedToolbarGlyphs(idBmpType, i, cx, crMask, uFlags, bUseClassicGlyphs, hInst);
|
|
|
|
if (pimlCache->arhiml[i])
|
|
{
|
|
// add shell glyphs
|
|
int idShellBmp = iBitmapBaseIndex + idBmpType;
|
|
hBMP = (HBITMAP) LoadImage (hInst, MAKEINTRESOURCE(idShellBmp + i), IMAGE_BITMAP,
|
|
0, 0, uFlags);
|
|
|
|
ImageList_AddMasked(pimlCache->arhiml[i], (HBITMAP)hBMP, crMask);
|
|
|
|
DeleteObject(hBMP);
|
|
}
|
|
}
|
|
}
|
|
pimlCache->cr3D = cr3D;
|
|
pimlCache->fSmallIcons = fSmallIcons;
|
|
pimlCache->fUseClassicGlyphs = bUseClassicGlyphs;
|
|
DontReload:
|
|
LEAVECRITICAL;
|
|
}
|
|
|
|
if (hwnd)
|
|
{
|
|
ASSERT(IS_VALID_HANDLE(hwnd, WND));
|
|
|
|
for (i = 0; i < CIMLISTS; i++)
|
|
{
|
|
SendMessage(hwnd, uMsg, 0, (LPARAM) pimlCache->arhiml[i]);
|
|
|
|
// set uMsg and uFlags for last iteration of loop (hot state)
|
|
uMsg = TB_SETHOTIMAGELIST;
|
|
uFlags = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef THEME_BUTTONS
|
|
BOOL _GetThemeSetting(HKEY hkey, PDWORD pdwSetting)
|
|
{
|
|
ASSERT(pdwSetting);
|
|
BOOL fRet = FALSE;
|
|
DWORD dwType, dwcbData = sizeof(*pdwSetting);
|
|
*pdwSetting = 0;
|
|
if (ERROR_SUCCESS==SHGetValue(hkey,
|
|
c_szRegKeyCoolbar, TEXT("UseTheme"), &dwType, pdwSetting, &dwcbData))
|
|
{
|
|
// We going to assume that the data type and size is correct. This way, we can break
|
|
// into an error state.
|
|
fRet = TRUE;
|
|
// Acceptable values:
|
|
// 0: use IE6 icons
|
|
// 1: use IE5.5 icons
|
|
// 2: use themed icons
|
|
// other values are reserved.
|
|
if (*pdwSetting > 2)
|
|
{
|
|
*pdwSetting = 0;
|
|
}
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
HIMAGELIST _LoadThemedToolbarGlyphs(int idBmpType, int iTemperature, int cx, COLORREF crMask,
|
|
UINT uFlags, BOOL bUseClassicGlyphs, HINSTANCE hInst)
|
|
{
|
|
HIMAGELIST himl = NULL;
|
|
// Restriction goes here.
|
|
|
|
HKEY hkey = HKEY_CURRENT_USER;
|
|
DWORD dwSetting = 0;
|
|
if (!_GetThemeSetting(hkey, &dwSetting))
|
|
{
|
|
hkey = HKEY_LOCAL_MACHINE;
|
|
_GetThemeSetting(hkey, &dwSetting);
|
|
}
|
|
|
|
DWORD dwType, dwcbData;
|
|
if (dwSetting==2)
|
|
{
|
|
TCHAR szPath[MAX_PATH];
|
|
TCHAR szItem[] = TEXT("ITBx");
|
|
szItem[3] = TEXT('0') + idBmpType + iTemperature;
|
|
|
|
dwcbData = sizeof(szPath);
|
|
if ((ERROR_SUCCESS==SHGetValue(hkey,
|
|
c_szRegKeyCoolbar, szItem, &dwType, szPath, &dwcbData))
|
|
&& (dwType==REG_SZ))
|
|
{
|
|
int nBmpIndex = PathParseIconLocation(szPath);
|
|
|
|
WCHAR szExpPath[MAX_PATH];
|
|
SHExpandEnvironmentStrings(szPath, szExpPath, ARRAYSIZE(szExpPath));
|
|
|
|
// If no resource id, assume it's a bmp file
|
|
if (nBmpIndex==0)
|
|
{
|
|
himl = CreateImageList(NULL,
|
|
szExpPath, cx, 0, crMask,
|
|
IMAGE_BITMAP, uFlags | LR_LOADFROMFILE,
|
|
!bUseClassicGlyphs);
|
|
}
|
|
|
|
// Otherwise, see if it's a resouce
|
|
if (!himl)
|
|
{
|
|
HINSTANCE hInst = LoadLibraryEx(szExpPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
|
if (hInst)
|
|
{
|
|
himl = CreateImageList(hInst,
|
|
MAKEINTRESOURCE(nBmpIndex), cx, 0, crMask,
|
|
IMAGE_BITMAP, uFlags, !bUseClassicGlyphs);
|
|
FreeLibrary(hInst);
|
|
}
|
|
}
|
|
|
|
if (himl)
|
|
{
|
|
// You just can't trust anyone these days. If the graphics aren't the expected
|
|
// size, or there aren't the expected number, we're going to use the defaults
|
|
|
|
// ISSUE: 16 is a magic number. Do we have a constant anywhere? I can't find it.
|
|
int ecx, ecy;
|
|
if (!(ImageList_GetIconSize(himl, &ecx, &ecy)
|
|
&& (ecx==ecy)
|
|
&& (ecy==cx)
|
|
&& (ImageList_GetImageCount(himl)==16)))
|
|
{
|
|
ImageList_Destroy(himl);
|
|
himl = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!himl)
|
|
{
|
|
// dwSetting must be 1 to get IE6 icons. If dwSetting isn't set to 1, then default
|
|
// either to the new Whistler icons or the default IE icons (as appropriate)
|
|
int iResource;
|
|
|
|
if (dwSetting == 1)
|
|
{
|
|
iResource = IDB_IE6_TOOLBAR;
|
|
}
|
|
else
|
|
{
|
|
if (bUseClassicGlyphs)
|
|
{
|
|
iResource = IDB_IETOOLBAR;
|
|
}
|
|
else
|
|
{
|
|
iResource = IDB_TB_IE_BASE;
|
|
}
|
|
}
|
|
|
|
iResource += (idBmpType + iTemperature);
|
|
|
|
himl = CreateImageList(hInst,
|
|
MAKEINTRESOURCE(iResource), cx, 0, crMask,
|
|
IMAGE_BITMAP, uFlags, !bUseClassicGlyphs);
|
|
}
|
|
return himl;
|
|
}
|
|
|
|
#else
|
|
HIMAGELIST _LoadThemedToolbarGlyphs(int idBmpType, int iTemperature, int cx, COLORREF crMask,
|
|
UINT uFlags, BOOL bUseClassicGlyphs, HINSTANCE hInst)
|
|
{
|
|
HIMAGELIST himl = NULL;
|
|
int iResource;
|
|
if (bUseClassicGlyphs)
|
|
{
|
|
iResource = IDB_IETOOLBAR;
|
|
}
|
|
else
|
|
{
|
|
iResource = IDB_TB_IE_BASE;
|
|
}
|
|
iResource += (idBmpType + iTemperature);
|
|
|
|
himl = CreateImageList(hInst,
|
|
MAKEINTRESOURCE(iResource), cx, 0, crMask,
|
|
IMAGE_BITMAP, uFlags, !bUseClassicGlyphs);
|
|
return himl;
|
|
}
|
|
|
|
#endif
|
|
|
|
void CInternetToolbar::_InitBitmapDSA()
|
|
{
|
|
DSA_Destroy(_hdsaTBBMPs);
|
|
_hdsaTBBMPs = DSA_Create(sizeof(TBBMP_LIST), TBBMPLIST_CHUNK);
|
|
|
|
if (_hdsaTBBMPs)
|
|
{
|
|
TBBMP_LIST tbl = { HINST_COMMCTRL, 0, 0, TRUE, TRUE, FALSE };
|
|
|
|
tbl.uiResID = IDB_STD_SMALL_COLOR;
|
|
tbl.uiOffset = OFFSET_STD;
|
|
DSA_AppendItem(_hdsaTBBMPs, &tbl);
|
|
tbl.uiResID = IDB_STD_LARGE_COLOR;
|
|
DSA_AppendItem(_hdsaTBBMPs, &tbl);
|
|
|
|
tbl.uiResID = IDB_VIEW_SMALL_COLOR;
|
|
tbl.uiOffset = OFFSET_VIEW;
|
|
DSA_AppendItem(_hdsaTBBMPs, &tbl);
|
|
tbl.uiResID = IDB_VIEW_LARGE_COLOR;
|
|
DSA_AppendItem(_hdsaTBBMPs, &tbl);
|
|
|
|
tbl.uiResID = IDB_HIST_SMALL_COLOR;
|
|
tbl.uiOffset = OFFSET_HIST;
|
|
DSA_AppendItem(_hdsaTBBMPs, &tbl);
|
|
tbl.uiResID = IDB_HIST_LARGE_COLOR;
|
|
DSA_AppendItem(_hdsaTBBMPs, &tbl);
|
|
}
|
|
}
|
|
|
|
|
|
void CInternetToolbar::_ReloadBitmapDSA()
|
|
{
|
|
if (_hdsaTBBMPs)
|
|
{
|
|
INT i = 6;
|
|
TBBMP_LIST * pTBBs = NULL;
|
|
int nCount = DSA_GetItemCount(_hdsaTBBMPs);
|
|
// We want to skip the first 6 entries in the DSA, which are added by InitBitmapDSA
|
|
for (int nIndex = 6; nIndex < nCount; nIndex++)
|
|
{
|
|
pTBBs = (TBBMP_LIST*)DSA_GetItemPtr(_hdsaTBBMPs, nIndex);
|
|
if (pTBBs)
|
|
{
|
|
HIMAGELIST himl = NULL;
|
|
if (pTBBs->fNormal)
|
|
{
|
|
himl = (HIMAGELIST)SendMessage(_btb._hwnd, TB_GETIMAGELIST, 0, 0L);
|
|
if (himl
|
|
&& (pTBBs->uiOffset==ImageList_GetImageCount(himl)))
|
|
{
|
|
LRESULT lOffset = _AddBitmapFromForeignModule(TB_GETIMAGELIST, TB_SETIMAGELIST, pTBBs->uiCount, pTBBs->hInst, pTBBs->uiResID, RGB(192,192,192));
|
|
ASSERT(pTBBs->uiOffset==lOffset);
|
|
}
|
|
}
|
|
if (pTBBs->fHot)
|
|
{
|
|
himl = (HIMAGELIST)SendMessage(_btb._hwnd, TB_GETHOTIMAGELIST, 0, 0L);
|
|
if (himl
|
|
&& (pTBBs->uiOffset==ImageList_GetImageCount(himl)))
|
|
{
|
|
LRESULT lOffset = _AddBitmapFromForeignModule(TB_GETHOTIMAGELIST, TB_SETHOTIMAGELIST, pTBBs->uiCount, pTBBs->hInst, pTBBs->uiResID, RGB(192,192,192));
|
|
ASSERT(pTBBs->uiOffset==lOffset);
|
|
}
|
|
}
|
|
if (pTBBs->fDisabled)
|
|
{
|
|
himl = (HIMAGELIST)SendMessage(_btb._hwnd, TB_GETDISABLEDIMAGELIST, 0, 0L);
|
|
if (himl
|
|
&& (pTBBs->uiOffset==ImageList_GetImageCount(himl)))
|
|
{
|
|
LRESULT lOffset = _AddBitmapFromForeignModule(TB_GETDISABLEDIMAGELIST, TB_SETDISABLEDIMAGELIST, pTBBs->uiCount, pTBBs->hInst, pTBBs->uiResID, RGB(192,192,192));
|
|
ASSERT(pTBBs->uiOffset==lOffset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CInternetToolbar::_InitForScreenSize()
|
|
{
|
|
TCHAR szScratch[16];
|
|
if (GetSystemMetrics(SM_CXSCREEN) < 650)
|
|
{
|
|
MLLoadString(IDS_TB_WIDTH_EXTRA_LORES, szScratch, ARRAYSIZE(szScratch));
|
|
_uiMaxTBWidth = MAX_TB_WIDTH_LORES;
|
|
}
|
|
else
|
|
{
|
|
MLLoadString(IDS_TB_WIDTH_EXTRA_HIRES, szScratch, ARRAYSIZE(szScratch));
|
|
_uiMaxTBWidth = MAX_TB_WIDTH_HIRES;
|
|
}
|
|
_uiMaxTBWidth += StrToInt(szScratch) * WIDTH_FACTOR;
|
|
}
|
|
|
|
|
|
// removes all buttons marked hidden. returns the number
|
|
// of buttons left
|
|
int RemoveHiddenButtons(TBBUTTON* ptbn, int iCount)
|
|
{
|
|
int i;
|
|
int iTotal = 0;
|
|
TBBUTTON* ptbn1 = ptbn;
|
|
for (i = 0; i < iCount; i++, ptbn1++)
|
|
{
|
|
if (!(ptbn1->fsState & TBSTATE_HIDDEN))
|
|
{
|
|
if (ptbn1 != ptbn)
|
|
{
|
|
*ptbn = *ptbn1;
|
|
}
|
|
ptbn++;
|
|
iTotal++;
|
|
}
|
|
}
|
|
return iTotal;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
void _AssertRestrictionOrderIsCorrect()
|
|
{
|
|
COMPILETIME_ASSERT(ARRAYSIZE(c_tbExplorer) == ARRAYSIZE(c_rest));
|
|
|
|
for (UINT i = 0; i < ARRAYSIZE(c_tbExplorer); i++)
|
|
{
|
|
// If any of these rip, it means that c_rest and c_tbExplorer have
|
|
// gotten out of sync. Need to fix up c_rest to match c_tbExplorer.
|
|
switch (c_tbExplorer[i].idCommand)
|
|
{
|
|
case TBIDM_BACK: ASSERT(c_rest[i] == REST_BTN_BACK); break;
|
|
case TBIDM_FORWARD: ASSERT(c_rest[i] == REST_BTN_FORWARD); break;
|
|
case TBIDM_STOPDOWNLOAD: ASSERT(c_rest[i] == REST_BTN_STOPDOWNLOAD); break;
|
|
case TBIDM_REFRESH: ASSERT(c_rest[i] == REST_BTN_REFRESH); break;
|
|
case TBIDM_HOME: ASSERT(c_rest[i] == REST_BTN_HOME); break;
|
|
case TBIDM_SEARCH: ASSERT(c_rest[i] == REST_BTN_SEARCH); break;
|
|
case TBIDM_HISTORY: ASSERT(c_rest[i] == REST_BTN_HISTORY); break;
|
|
case TBIDM_FAVORITES: ASSERT(c_rest[i] == REST_BTN_FAVORITES); break;
|
|
case TBIDM_ALLFOLDERS: ASSERT(c_rest[i] == REST_BTN_ALLFOLDERS); break;
|
|
case TBIDM_THEATER: ASSERT(c_rest[i] == REST_BTN_THEATER); break;
|
|
case TBIDM_MEDIABAR: ASSERT(c_rest[i] == REST_BTN_MEDIABAR); break;
|
|
default: ASSERT(c_rest[i] == REST_BROWSER_NONE); break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
__inline BOOL CInternetToolbar::_FoldersButtonAvailable()
|
|
{
|
|
return (GetUIVersion() >= 4);
|
|
}
|
|
|
|
void CInternetToolbar::_AdminMarkDefaultButtons(PTBBUTTON ptbb, UINT cButtons)
|
|
{
|
|
// We only have policies for web buttons.
|
|
ASSERT(!_fShellView);
|
|
|
|
// Caller should have checked this.
|
|
ASSERT(SHRestricted2(REST_SPECIFYDEFAULTBUTTONS, NULL, 0));
|
|
|
|
|
|
// SHRestricted2 returns 0 if it can't find the policy. Assert that
|
|
// this lines up with RESTOPT_BTN_STATE_DEFAULT.
|
|
COMPILETIME_ASSERT(RESTOPT_BTN_STATE_DEFAULT == 0);
|
|
|
|
for (UINT i = 0; i < cButtons; i++)
|
|
{
|
|
if (c_rest[i] != 0)
|
|
{
|
|
DWORD dwRest = SHRestricted2(c_rest[i], NULL, 0);
|
|
ptbb[i].fsState = SHBtnStateFromRestriction(dwRest, ptbb[i].fsState);
|
|
}
|
|
}
|
|
|
|
// Folders button is not available on non-integrated platforms, so
|
|
// set state to hidden even if policy specifies that it should be shown.
|
|
ASSERT(c_tbExplorer[TBXID_ALLFOLDERS].idCommand == TBIDM_ALLFOLDERS);
|
|
if (!_FoldersButtonAvailable())
|
|
ptbb[TBXID_ALLFOLDERS].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
|
|
void CInternetToolbar::_MarkDefaultButtons(PTBBUTTON ptbb, UINT cButtons)
|
|
{
|
|
if (SHRestricted(REST_NONLEGACYSHELLMODE))
|
|
{
|
|
ASSERT(ptbb[TBXID_BACK].idCommand == TBIDM_BACK);
|
|
ptbb[TBXID_BACK].fsState |= TBSTATE_HIDDEN;
|
|
ASSERT(ptbb[TBXID_FORWARD].idCommand == TBIDM_FORWARD);
|
|
ptbb[TBXID_FORWARD].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
|
|
if (_fShellView)
|
|
{
|
|
ASSERT(c_tbExplorer[TBXID_STOPDOWNLOAD].idCommand == TBIDM_STOPDOWNLOAD);
|
|
ptbb[TBXID_STOPDOWNLOAD].fsState |= TBSTATE_HIDDEN;
|
|
ASSERT(c_tbExplorer[TBXID_REFRESH].idCommand == TBIDM_REFRESH);
|
|
ptbb[TBXID_REFRESH].fsState |= TBSTATE_HIDDEN;
|
|
ASSERT(c_tbExplorer[TBXID_HOME].idCommand == TBIDM_HOME);
|
|
ptbb[TBXID_HOME].fsState |= TBSTATE_HIDDEN;
|
|
|
|
ASSERT(c_tbExplorer[TBXID_SEARCH].idCommand == TBIDM_SEARCH);
|
|
ASSERT(c_tbExplorer[TBXID_HISTORY].idCommand == TBIDM_HISTORY);
|
|
ASSERT(c_tbExplorer[TBXID_SEPARATOR2].idCommand == 0); // (a separator)
|
|
|
|
if (GetUIVersion() < 5)
|
|
{
|
|
ptbb[TBXID_SEARCH].fsState |= TBSTATE_HIDDEN;
|
|
ptbb[TBXID_HISTORY].fsState |= TBSTATE_HIDDEN;
|
|
ptbb[TBXID_SEPARATOR2].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
else
|
|
{
|
|
if (GetUIVersion() > 5)
|
|
{
|
|
ptbb[TBXID_HISTORY].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
|
|
if (SHRestricted(REST_NOSHELLSEARCHBUTTON))
|
|
{
|
|
ptbb[TBXID_SEARCH].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
ASSERT(c_tbExplorer[TBXID_CONNECT].idCommand == TBIDM_CONNECT);
|
|
ASSERT(c_tbExplorer[TBXID_DISCONNECT].idCommand == TBIDM_DISCONNECT);
|
|
if (SHRestricted(REST_NONETCONNECTDISCONNECT))
|
|
{
|
|
ptbb[TBXID_CONNECT].fsState |= TBSTATE_HIDDEN;
|
|
ptbb[TBXID_DISCONNECT].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
}
|
|
|
|
ASSERT(c_tbExplorer[TBXID_FAVORITES].idCommand == TBIDM_FAVORITES);
|
|
ptbb[TBXID_FAVORITES].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
|
|
ASSERT(c_tbExplorer[TBXID_PREVIOUSFOLDER].idCommand == TBIDM_PREVIOUSFOLDER);
|
|
if (!_fShellView)
|
|
ptbb[TBXID_PREVIOUSFOLDER].fsState |= TBSTATE_HIDDEN;
|
|
|
|
ASSERT(c_tbExplorer[TBXID_CONNECT].idCommand == TBIDM_CONNECT);
|
|
ASSERT(c_tbExplorer[TBXID_DISCONNECT].idCommand == TBIDM_DISCONNECT);
|
|
if (!_fShellView || !_UseMapNetDrvBtns())
|
|
{
|
|
ptbb[TBXID_CONNECT].fsState |= TBSTATE_HIDDEN;
|
|
ptbb[TBXID_DISCONNECT].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
|
|
// If this TBIDM_ALLFOLDERS assertion rips, remember to fix up _AdminMarkDefaultButtons too.
|
|
ASSERT(c_tbExplorer[TBXID_ALLFOLDERS].idCommand == TBIDM_ALLFOLDERS);
|
|
if (!_fShellView || GetUIVersion() < 5)
|
|
ptbb[TBXID_ALLFOLDERS].fsState |= TBSTATE_HIDDEN;
|
|
|
|
ASSERT(c_tbExplorer[TBXID_THEATER].idCommand == TBIDM_THEATER);
|
|
ptbb[TBXID_THEATER].fsState |= TBSTATE_HIDDEN;
|
|
|
|
ASSERT(c_tbExplorer[TBXID_MEDIABAR].idCommand == TBIDM_MEDIABAR);
|
|
if (_fShellView || SHRestricted2W(REST_No_LaunchMediaBar, NULL, 0) || !CMediaBarUtil::IsWMP7OrGreaterCapable())
|
|
{
|
|
ptbb[TBXID_MEDIABAR].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
|
|
ASSERT(c_tbExplorer[TBXID_PREVIOUSFOLDER].idCommand == TBIDM_PREVIOUSFOLDER);
|
|
if (!_fShellView)
|
|
{
|
|
ptbb[TBXID_PREVIOUSFOLDER].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
}
|
|
|
|
void CInternetToolbar::_AddCommonButtons()
|
|
{
|
|
TBBUTTON tbExplorer[ARRAYSIZE(c_tbExplorer)];
|
|
|
|
memcpy(tbExplorer, c_tbExplorer, sizeof(TBBUTTON) * ARRAYSIZE(c_tbExplorer));
|
|
|
|
if (IS_BIDI_LOCALIZED_SYSTEM())
|
|
{
|
|
if (!SHUseClassicToolbarGlyphs())
|
|
{
|
|
tbExplorer[0].iBitmap = 1;
|
|
tbExplorer[1].iBitmap = 0;
|
|
}
|
|
}
|
|
|
|
_MarkDefaultButtons(tbExplorer, ARRAYSIZE(c_tbExplorer));
|
|
|
|
#ifdef DEBUG
|
|
_AssertRestrictionOrderIsCorrect();
|
|
#endif
|
|
|
|
if (!_fShellView && SHRestricted2(REST_SPECIFYDEFAULTBUTTONS, NULL, 0))
|
|
_AdminMarkDefaultButtons(tbExplorer, ARRAYSIZE(c_tbExplorer));
|
|
|
|
int iButtons = RemoveHiddenButtons(tbExplorer, ARRAYSIZE(tbExplorer));
|
|
|
|
for (int i = 0; i < iButtons; i++)
|
|
{
|
|
if (!(tbExplorer[i].fsStyle & BTNS_SEP))
|
|
{
|
|
CMDMAP* pcm = (CMDMAP*)LocalAlloc(LPTR, sizeof(CMDMAP));
|
|
if (pcm)
|
|
{
|
|
pcm->guidButtonGroup = CLSID_CommonButtons;
|
|
pcm->nCmdID = tbExplorer[i].idCommand;
|
|
|
|
tbExplorer[i].idCommand = _btb._nNextCommandID++;
|
|
tbExplorer[i].dwData = (LPARAM)pcm;
|
|
}
|
|
}
|
|
}
|
|
|
|
SendMessage(_btb._hwnd, TB_ADDBUTTONS, iButtons, (LPARAM) tbExplorer);
|
|
|
|
_btb._RecalcButtonWidths();
|
|
}
|
|
|
|
#define IS_LIST_STYLE(hwnd) (BOOLIFY(GetWindowLong(hwnd, GWL_STYLE) & TBSTYLE_LIST))
|
|
|
|
void CInternetToolbar::_UpdateToolsStyle(BOOL fList)
|
|
{
|
|
if (BOOLIFY(fList) != IS_LIST_STYLE(_btb._hwnd))
|
|
{
|
|
_fDirty = TRUE;
|
|
|
|
// toggle TBSTYLE_LIST
|
|
SHSetWindowBits(_btb._hwnd, GWL_STYLE, TBSTYLE_LIST, fList ? TBSTYLE_LIST : 0);
|
|
// toggle TBSTYLE_EX_MIXEDBUTTONS
|
|
SendMessage(_btb._hwnd, TB_SETEXTENDEDSTYLE, TBSTYLE_EX_MIXEDBUTTONS, fList ? TBSTYLE_EX_MIXEDBUTTONS : 0);
|
|
}
|
|
}
|
|
|
|
void CInternetToolbar::_InitToolbar()
|
|
{
|
|
TCHAR szShellTBText[1024]; // This should be enough
|
|
ZeroMemory(szShellTBText, sizeof(szShellTBText));
|
|
int nRows = _fCompressed ? 0 : _uiTBTextRows;
|
|
DWORD dwStyle = TBSTYLE_EX_DRAWDDARROWS | TBSTYLE_EX_HIDECLIPPEDBUTTONS;
|
|
|
|
if (IsOS(OS_WHISTLERORGREATER))
|
|
dwStyle |= TBSTYLE_EX_DOUBLEBUFFER;
|
|
|
|
// this tells the toolbar what version we are
|
|
SendMessage(_btb._hwnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
|
|
SendMessage(_btb._hwnd, TB_SETEXTENDEDSTYLE, dwStyle, dwStyle);
|
|
SendMessage(_btb._hwnd, TB_SETMAXTEXTROWS, nRows, 0L);
|
|
SendMessage(_btb._hwnd, TB_SETDROPDOWNGAP, GetSystemMetrics(SM_CXEDGE) / 2, 0);
|
|
SendMessage(_btb._hwnd, CCM_SETVERSION, COMCTL32_VERSION, 0);
|
|
|
|
_UpdateToolsStyle(_cs.fList);
|
|
_fDirty = FALSE; // _UpdateToolsStyle unfortunately sets this early on; but we can assume we're not dirty now.
|
|
|
|
ITBar_LoadToolbarGlyphs(_btb._hwnd);
|
|
_InitBitmapDSA();
|
|
|
|
_InitForScreenSize();
|
|
|
|
SendMessage(_btb._hwnd, TB_ADDSTRING, (WPARAM)MLGetHinst(), IDS_IE_TB_LABELS);
|
|
|
|
_AddCommonButtons();
|
|
|
|
INT_PTR nRet = SendMessage(_btb._hwnd, TB_ADDSTRING, (WPARAM)MLGetHinst(), IDS_SHELL_TB_LABELS);
|
|
|
|
#ifdef DEBUG
|
|
if (nRet != SHELLTOOLBAR_OFFSET)
|
|
TraceMsg(TF_ERROR, "CInternetToolbar::_InitToolbar -- nRet != SHELLTOOLBAR_OFFSET");
|
|
#endif
|
|
}
|
|
|
|
HRESULT CInternetToolbar::_ShowTools(PBANDSAVE pbs)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_TOOLS);
|
|
|
|
if (!pbid)
|
|
{
|
|
ASSERT(!_btb._hwnd);
|
|
|
|
_btb._hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL,
|
|
WS_CHILD | TBSTYLE_FLAT |
|
|
TBSTYLE_TOOLTIPS |
|
|
WS_CLIPCHILDREN |
|
|
WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN |
|
|
CCS_NORESIZE,
|
|
0, 0, 0, 0, _bs._hwnd, (HMENU) FCIDM_TOOLBAR, HINST_THISDLL, NULL);
|
|
|
|
if (_btb._hwnd)
|
|
{
|
|
_InitToolbar();
|
|
pbid = _AddNewBand((IDeskBand*)&_btb, CBIDX_TOOLS);
|
|
}
|
|
|
|
if (!pbid)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
pbs = NULL;
|
|
}
|
|
|
|
_ShowBandCommon(pbs, pbid, _nVisibleBands & VBF_TOOLS);
|
|
return hr;
|
|
}
|
|
|
|
void CInternetToolbar::_ShowBandCommon(PBANDSAVE pbs, LPBANDITEMDATA pbid, BOOL fShow)
|
|
{
|
|
REBARBANDINFO rbbi;
|
|
|
|
pbid->fShow = BOOLIFY(fShow);
|
|
if (pbid->pdb)
|
|
{
|
|
pbid->pdb->ShowDW(pbid->fShow);
|
|
}
|
|
|
|
INT_PTR i = BandIDtoIndex(_bs._hwnd, pbid->dwBandID);
|
|
|
|
if (pbs)
|
|
{
|
|
rbbi.cbSize = sizeof(REBARBANDINFO);
|
|
rbbi.fMask = RBBIM_SIZE | RBBIM_STYLE;
|
|
|
|
// we just want to change the RBBS_BREAK bit
|
|
// assert that our caller doesn't expect to set any other bits
|
|
// ASSERT(!(pbs->fStyle & ~RBBS_BREAK)); <--- I hit this assert all the time
|
|
|
|
// get old style
|
|
SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM)&rbbi);
|
|
|
|
rbbi.fStyle = (rbbi.fStyle & ~RBBS_BREAK) | (pbs->fStyle & RBBS_BREAK);
|
|
rbbi.cx = pbs->cx;
|
|
|
|
SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM)&rbbi);
|
|
}
|
|
|
|
|
|
if ( pbid->dwModeFlags & DBIMF_BREAK )
|
|
{
|
|
rbbi.cbSize = sizeof(REBARBANDINFO);
|
|
rbbi.fMask = RBBIM_STYLE;
|
|
if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
|
|
{
|
|
// in theater mode we don't allow bands to have breaks
|
|
if ((rbbi.fStyle & RBBS_BREAK ) && _fTheater)
|
|
{
|
|
rbbi.fStyle &= ~RBBS_BREAK;
|
|
SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM) &rbbi);
|
|
}
|
|
}
|
|
}
|
|
|
|
SendMessage(_bs._hwnd, RB_SHOWBAND, i, pbid->fShow);
|
|
}
|
|
|
|
|
|
HRESULT CInternetToolbar::_GetPersistedBand(const CLSID clsid, REFIID riid, void ** ppiface)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
TCHAR szStreamName[MAX_PATH];
|
|
|
|
if (SUCCEEDED(_GetStreamName(_fInitialPidlIsWeb, szStreamName, ARRAYSIZE(szStreamName))))
|
|
{
|
|
static BOOL fBrowserOnly = (WhichPlatform() != PLATFORM_INTEGRATED);
|
|
TCHAR szKey[MAX_PATH];
|
|
TCHAR szGUID[MAX_PATH];
|
|
|
|
wnsprintf(szKey, ARRAYSIZE(szKey), TEXT("Software\\Microsoft\\Internet Explorer\\Toolbar\\%s"), szStreamName);
|
|
SHStringFromGUID(clsid, szGUID, ARRAYSIZE(szGUID));
|
|
|
|
if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, szKey, szGUID, NULL, NULL, NULL))
|
|
{
|
|
// Was the stream saved by an Integrated shell and we are in browser only mode?
|
|
if ((_cs.fSaveInShellIntegrationMode) && fBrowserOnly)
|
|
{
|
|
// Yes, so we need to ignore the stream.
|
|
}
|
|
else
|
|
{
|
|
IStream * pstm = GetRegStream(_fInitialPidlIsWeb, szGUID, STGM_READ);
|
|
if (pstm)
|
|
{
|
|
hr = _bs.LoadFromStreamBS(pstm, riid, ppiface);
|
|
pstm->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, riid, ppiface);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IPersistStreamInit * ppsi;
|
|
((IUnknown *) *ppiface)->QueryInterface(IID_PPV_ARG(IPersistStreamInit, &ppsi));
|
|
if (ppsi)
|
|
{
|
|
ppsi->InitNew();
|
|
ppsi->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CInternetToolbar::_ShowExternalBand( PBANDSAVE pbs, int idBand )
|
|
{
|
|
HRESULT hr;
|
|
if (IS_EXTERNALBAND(idBand))
|
|
{
|
|
int idBandExt = MAP_TO_EXTERNAL(idBand);
|
|
|
|
if (!IsEqualCLSID(_rgebi[idBandExt].clsid, GUID_NULL))
|
|
{
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID( idBand );
|
|
BOOL fIsVisible = _nVisibleBands & EXTERNALBAND_VBF_BIT(idBandExt);
|
|
if (!pbid && fIsVisible)
|
|
{
|
|
IDeskBand *pitbBand;
|
|
hr = _GetPersistedBand(_rgebi[idBandExt].clsid, IID_PPV_ARG(IDeskBand, &pitbBand));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pbid = _AddNewBand( pitbBand, idBand );
|
|
pitbBand->Release();
|
|
}
|
|
if (!pbid)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
pbs = NULL;
|
|
if (!pbid)
|
|
return S_OK;
|
|
}
|
|
_ShowBandCommon(pbs, pbid, fIsVisible );
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CInternetToolbar::_ShowAddressBand(PBANDSAVE pbs)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
|
|
if (!pbid)
|
|
{
|
|
if (_nVisibleBands & VBF_ADDRESS)
|
|
{
|
|
IDeskBand *pitbAddressBand;
|
|
|
|
hr = _GetPersistedBand(CLSID_AddressBand, IID_PPV_ARG(IDeskBand, &pitbAddressBand));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pbid = _AddNewBand(pitbAddressBand, CBIDX_ADDRESS);
|
|
if (pbid)
|
|
{
|
|
_hwndAddressBand = pbid->hwnd;
|
|
|
|
if (!pbs)
|
|
{
|
|
for (int i = 0; i < CBANDSMAX; i++)
|
|
{
|
|
if (_cs.bs[i].wID == CBIDX_ADDRESS)
|
|
{
|
|
pbs = _cs.bs + i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pitbAddressBand->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
if (!pbid)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
pbs = NULL;
|
|
|
|
|
|
_ShowBandCommon(pbs, pbid, _nVisibleBands & VBF_ADDRESS);
|
|
return S_OK;
|
|
}
|
|
|
|
LPBANDITEMDATA CInternetToolbar::_AddNewBand(IDeskBand* pdb, DWORD dwID)
|
|
{
|
|
if (SUCCEEDED(_bs._AddBandByID(pdb, dwID)))
|
|
{
|
|
return _bs._GetBandItemDataStructByID(dwID);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
HRESULT CInternetToolbar::_ShowLinks(PBANDSAVE pbs)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_LINKS);
|
|
if (!pbid)
|
|
{
|
|
IDeskBand* pdbLinks = NULL;
|
|
|
|
// Check if custom link band GUID is present in the registry,
|
|
// and if so, do a full CoCreateInstance using this GUID.
|
|
// Otherwise, just do the normal internal call to the link's band factory.
|
|
|
|
if (_nVisibleBands & VBF_LINKS)
|
|
{
|
|
if (!_fInitialPidlIsWeb ||
|
|
FAILED(CreateFromRegKey(c_szRegKeyCoolbar, TEXT("QuickLinksCLSID"), IID_PPV_ARG(IDeskBand, &pdbLinks))))
|
|
{
|
|
hr = _GetPersistedBand(CLSID_QuickLinks, IID_PPV_ARG(IDeskBand, &pdbLinks));
|
|
IUnknown_Exec(pdbLinks, &CLSID_QuickLinks, QLCMD_SINGLELINE, 1, NULL, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
if (pdbLinks)
|
|
{
|
|
// mark it so ISFBand knows it's qlinks (for UAssist)
|
|
VARIANTARG v;
|
|
#ifdef DEBUG
|
|
{
|
|
// n.b. we overwrite old persisted guys (which should be -1)
|
|
IUnknown_Exec(pdbLinks, &CGID_ISFBand, ISFBID_PRIVATEID, 0, NULL, &v);
|
|
ASSERT(v.lVal == -1 || v.lVal == CSIDL_FAVORITES);
|
|
}
|
|
#endif
|
|
v.vt = VT_I4;
|
|
v.lVal = CSIDL_FAVORITES; // close enough for our purposes...
|
|
IUnknown_Exec(pdbLinks, &CGID_ISFBand, ISFBID_PRIVATEID, 0, &v, NULL);
|
|
pbid = _AddNewBand(pdbLinks, CBIDX_LINKS);
|
|
|
|
if (pbid && !pbs)
|
|
{
|
|
for (int i = 0; i < CBANDSMAX; i++)
|
|
{
|
|
if (_cs.bs[i].wID == CBIDX_LINKS)
|
|
{
|
|
pbs = _cs.bs + i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
pdbLinks->Release();
|
|
}
|
|
|
|
if (!pbid)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
pbs = NULL;
|
|
|
|
_ShowBandCommon(pbs, pbid, _nVisibleBands & VBF_LINKS);
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::_ShowMenu(PBANDSAVE pbs)
|
|
{
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_MENU);
|
|
if (!pbid)
|
|
{
|
|
CFavoritesCallback* pfcb = new CFavoritesCallback();
|
|
if (pfcb)
|
|
{
|
|
IShellMenu* psm;
|
|
if (SUCCEEDED(CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellMenu, &psm))))
|
|
{
|
|
VARIANTARG var;
|
|
|
|
if (SUCCEEDED(IUnknown_Exec(_pbs2, &CGID_Explorer, SBCMDID_GETCURRENTMENU, 0, NULL, &var)) &&
|
|
var.vt == VT_INT_PTR && var.byref)
|
|
{
|
|
IDeskBand* pdbMenu;
|
|
if (SUCCEEDED(psm->Initialize(pfcb, -1, ANCESTORDEFAULT, SMINIT_HORIZONTAL | SMINIT_TOPLEVEL)) &&
|
|
SUCCEEDED(psm->SetMenu((HMENU)var.byref, GetParent(_hwnd), SMSET_DONTOWN)) &&
|
|
SUCCEEDED(psm->QueryInterface(IID_PPV_ARG(IDeskBand, &pdbMenu))))
|
|
{
|
|
pbid = _AddNewBand(pdbMenu, CBIDX_MENU);
|
|
if (pbid)
|
|
{
|
|
// Tell the menuband we're not a real bar/bandsite/band
|
|
IUnknown_Exec(pbid->pdb, &CGID_MenuBand, MBANDCID_NOTAREALSITE, TRUE, NULL, NULL);
|
|
|
|
_bs.SetBandState(CBIDX_MENU, BSSF_NOTITLE, BSSF_NOTITLE);
|
|
_hwndMenu = pbid->hwnd;
|
|
}
|
|
|
|
pdbMenu->Release();
|
|
}
|
|
}
|
|
psm->Release();
|
|
}
|
|
pfcb->Release();
|
|
}
|
|
|
|
if (!pbid)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
pbs = NULL;
|
|
|
|
|
|
_ShowBandCommon(pbs, pbid, _nVisibleBands & VBF_MENU);
|
|
return S_OK;
|
|
}
|
|
|
|
HBITMAP CInternetToolbar::_LoadBackBitmap()
|
|
{
|
|
if (SHIsLowMemoryMachine(ILMM_IE4))
|
|
return NULL;
|
|
|
|
if (_fInitialPidlIsWeb)
|
|
{
|
|
static LPTSTR s_pszBitmapInternet = NULL;
|
|
return LoadToolbarBackBmp(&s_pszBitmapInternet, &s_bmpBackInternet, _fInitialPidlIsWeb);
|
|
}
|
|
else
|
|
{
|
|
static LPTSTR s_pszBitmapShell = NULL;
|
|
return LoadToolbarBackBmp(&s_pszBitmapShell, &s_bmpBackShell, _fInitialPidlIsWeb);
|
|
}
|
|
}
|
|
|
|
void CInternetToolbar::_SetBackground()
|
|
{
|
|
REBARBANDINFO rbbi;
|
|
HBITMAP hbmp;
|
|
|
|
// Theater mode doesn't allow bitmap customization, so don't bother loading one from the cache
|
|
if (_fTheater)
|
|
hbmp = NULL;
|
|
else
|
|
hbmp = _LoadBackBitmap();
|
|
|
|
// don't bother updating the bkcolor if we know we'll just set it to CLR_NONE below (otherwise rebar invalidates)
|
|
if (!hbmp)
|
|
SendMessage(_bs._hwnd, RB_SETBKCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
|
|
|
|
// If we think we have a bitmap, or the cache thinks we have a bitmap, we have some work to do
|
|
if (_bmpBack || hbmp)
|
|
{
|
|
BOOL fRemove = (NULL!=_bmpBack && NULL==hbmp);
|
|
|
|
if (hbmp)
|
|
SendMessage(_bs._hwnd, RB_SETBKCOLOR, 0, (LPARAM)CLR_NONE);
|
|
_bmpBack = hbmp;
|
|
|
|
rbbi.cbSize = sizeof(REBARBANDINFO);
|
|
|
|
INT_PTR fRedraw = SendMessage(_bs._hwnd, WM_SETREDRAW, FALSE, 0);
|
|
|
|
INT icBands = (INT) SendMessage( _bs._hwnd, RB_GETBANDCOUNT, 0, 0 );
|
|
for (int i = 0; i < icBands; i++)
|
|
{
|
|
rbbi.fMask = RBBIM_ID | RBBIM_CHILD | RBBIM_BACKGROUND;
|
|
if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
|
|
{
|
|
if (rbbi.wID != CBIDX_BRAND && rbbi.hbmBack != hbmp)
|
|
{
|
|
rbbi.fMask = RBBIM_BACKGROUND;
|
|
rbbi.hbmBack = hbmp;
|
|
SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM) &rbbi);
|
|
InvalidateRect(rbbi.hwndChild, NULL, TRUE);
|
|
}
|
|
}
|
|
}
|
|
SendMessage(_bs._hwnd, WM_SETREDRAW, fRedraw, 0);
|
|
|
|
// When removing the background bitmap, we need to invalidate *outside*
|
|
// of the WM_SETREDRAW so we actually erase the background properly
|
|
//
|
|
if (fRemove)
|
|
InvalidateRect(_bs._hwnd, NULL, TRUE);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT CInternetToolbar::_ShowBrand(PBANDSAVE pbs)
|
|
{
|
|
REBARBANDINFO rbbi;
|
|
LPBANDITEMDATA pbid;
|
|
INT_PTR i;
|
|
HRESULT hr = S_OK;
|
|
BOOL fCreated = FALSE;
|
|
|
|
pbid = _bs._GetBandItemDataStructByID(CBIDX_BRAND);
|
|
if (!pbid)
|
|
{
|
|
IDeskBand *pdbBrandBand;
|
|
hr = CBrandBand_CreateInstance(NULL, (IUnknown **)&pdbBrandBand, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pbid = _AddNewBand(pdbBrandBand, CBIDX_BRAND);
|
|
fCreated = TRUE;
|
|
pdbBrandBand->Release();
|
|
}
|
|
else
|
|
return hr;
|
|
}
|
|
|
|
if (!pbid)
|
|
return E_OUTOFMEMORY;
|
|
|
|
pbid->pdb->ShowDW(TRUE);
|
|
|
|
i = BandIDtoIndex(_bs._hwnd, CBIDX_BRAND);
|
|
if (fCreated)
|
|
{
|
|
// add these to ::IDeskBand::GetBandInfo()
|
|
rbbi.cbSize = sizeof(REBARBANDINFO);
|
|
rbbi.fMask = RBBIM_STYLE;
|
|
rbbi.fStyle = RBBS_FIXEDSIZE | RBBS_VARIABLEHEIGHT;
|
|
|
|
if (pbs)
|
|
{
|
|
rbbi.fMask |= RBBIM_SIZE;
|
|
rbbi.fStyle |= pbs->fStyle;
|
|
rbbi.cx = pbs->cx;
|
|
}
|
|
SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM)&rbbi);
|
|
// this can cause the band to move because a fixed size band
|
|
// is forced in a particular location.
|
|
// so we need to re-fetch the index
|
|
i = BandIDtoIndex(_bs._hwnd, CBIDX_BRAND);
|
|
}
|
|
SendMessage(_bs._hwnd, RB_SHOWBAND, i, _nVisibleBands & VBF_BRAND);
|
|
return S_OK;
|
|
}
|
|
|
|
void CInternetToolbar::_EnsureAllBandsShown()
|
|
{
|
|
if (_hwnd)
|
|
{
|
|
INT_PTR fRedraw = SendMessage(_bs._hwnd, WM_SETREDRAW, FALSE, 0);
|
|
|
|
_ShowMenu(NULL);
|
|
_ShowTools(NULL);
|
|
_ShowAddressBand(NULL);
|
|
_ShowLinks(NULL);
|
|
_ShowBrand(NULL);
|
|
for (int i = CBIDX_EXTERNALFIRST; i <= CBIDX_EXTERNALLAST; i++)
|
|
{
|
|
_ShowExternalBand( NULL, i );
|
|
}
|
|
|
|
_SetBackground();
|
|
_bs._SetMinDimensions();
|
|
_UpdateLocking();
|
|
|
|
SendMessage(_bs._hwnd, WM_SETREDRAW, fRedraw, 0);
|
|
}
|
|
}
|
|
|
|
BOOL CInternetToolbar::_ShowBands(UINT fVisible)
|
|
{
|
|
fVisible &= VBF_VALID;
|
|
|
|
if (fVisible == _nVisibleBands)
|
|
return(TRUE);
|
|
|
|
_nVisibleBands = fVisible;
|
|
_EnsureAllBandsShown();
|
|
ShowDW(_fShow);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
HRESULT CInternetToolbar::_CreateBands()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!_hwnd && _ptbsite)
|
|
{
|
|
HWND hwndParent;
|
|
|
|
hr = _ptbsite->GetWindow(&hwndParent);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
TCHAR szScratch[16];
|
|
int i;
|
|
|
|
// Check if coolbar layout had already been loaded from the registry
|
|
if(_cs.cbVer != CBS_VERSION)
|
|
{
|
|
TraceMsg(DM_ITBAR, "CInternetToolbar::_CreateBands failed. Bad Version");
|
|
ASSERT(0);
|
|
|
|
return(S_FALSE);
|
|
}
|
|
|
|
_nVisibleBands = _cs.uiVisible;
|
|
|
|
_InitComCtl32(); // don't check result, if this fails our CreateWindows will fail
|
|
|
|
MLLoadString(IDS_WEB_TB_TEXTROWS, szScratch, ARRAYSIZE(szScratch));
|
|
_uiTBTextRows = _uiTBDefaultTextRows = StrToInt(szScratch);
|
|
|
|
_fCompressed = (_cs.fNoText != FALSE);
|
|
|
|
_hwnd = SHCreateWorkerWindow(SizableWndProc, hwndParent, 0, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
|
(HMENU)FCIDM_REBAR, this);
|
|
|
|
if (!IS_VALID_HANDLE(_hwnd, WND))
|
|
{
|
|
_fDontSave = TRUE;
|
|
TraceMsg(TF_ERROR, "CInternetToolbar::_CreateBands() - _hwnd failed");
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// delay until now
|
|
// this sets up the parent child chain so that these children can
|
|
// queryservice through us
|
|
hr = SetClient(SAFECAST(&_bs, IInputObjectSite*));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
INT_PTR fRedraw = SendMessage(_bs._hwnd, WM_SETREDRAW, FALSE, 0);
|
|
|
|
for (i = 0; i < CBANDSMAX; i++)
|
|
{
|
|
hr = S_OK;
|
|
switch (_cs.bs[i].wID)
|
|
{
|
|
case CBIDX_TOOLS:
|
|
if(!SHRestricted2W(REST_NoToolBar, NULL, 0))
|
|
{
|
|
hr = _ShowTools(_cs.bs + i);
|
|
}
|
|
else
|
|
{
|
|
_nVisibleBands &= ~VBF_TOOLS;
|
|
}
|
|
break;
|
|
|
|
case CBIDX_ADDRESS:
|
|
if(!SHRestricted2W(REST_NoAddressBar, NULL, 0))
|
|
{
|
|
hr = _ShowAddressBand(_cs.bs + i);
|
|
}
|
|
else
|
|
{
|
|
_nVisibleBands &= ~VBF_ADDRESS;
|
|
}
|
|
break;
|
|
|
|
case CBIDX_LINKS:
|
|
if(!SHRestricted2W(REST_NoLinksBar, NULL, 0))
|
|
{
|
|
hr = _ShowLinks(_cs.bs + i);
|
|
}
|
|
else
|
|
{
|
|
_nVisibleBands &= ~VBF_LINKS;
|
|
}
|
|
break;
|
|
|
|
case CBIDX_BRAND:
|
|
hr = _ShowBrand(_cs.bs + i);
|
|
break;
|
|
|
|
case CBIDX_MENU:
|
|
hr = _ShowMenu(_cs.bs + i);
|
|
break;
|
|
|
|
// If there is no id associated, there's nothing more to restore.
|
|
case 0:
|
|
{
|
|
// Out of bands; stop loop.
|
|
i = CBANDSMAX;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
if (IS_EXTERNALBAND(_cs.bs[i].wID))
|
|
{
|
|
for (DWORD j = 0; j < MAXEXTERNALBANDS; j++)
|
|
{
|
|
if (_cs.aclsidExternalBands[MAP_TO_EXTERNAL(_cs.bs[i].wID)] == _rgebi[j].clsid)
|
|
{
|
|
CLSID clsidTemp = _rgebi[j].clsid;
|
|
_rgebi[j].clsid = _rgebi[MAP_TO_EXTERNAL(_cs.bs[i].wID)].clsid;
|
|
_rgebi[MAP_TO_EXTERNAL(_cs.bs[i].wID)].clsid = clsidTemp;
|
|
hr = _ShowExternalBand(_cs.bs + i, _cs.bs[i].wID);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
TraceMsg(TF_ERROR, "CInternetToolbar::_CreateBands -- band ID %x creation failed", _cs.bs[i].wID);
|
|
|
|
// if band creation failed, we still go ahead and open the browser and do our normal stuff --
|
|
// including persisting the band state.
|
|
// unfortunately for the user who opens too many windows, they hit GDI limits and we can't
|
|
// create the bands and we fail, and then persist out that state. so all future windows
|
|
// are broken without the file menu etc. and the user cant get out.
|
|
_fDontSave = TRUE;
|
|
}
|
|
}
|
|
|
|
_SetBackground();
|
|
_bs._SetMinDimensions();
|
|
_UpdateLocking();
|
|
|
|
SendMessage(_bs._hwnd, WM_SETREDRAW, fRedraw, 0);
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::ShowDW(BOOL fShow)
|
|
{
|
|
if ((g_dwProfileCAP & 0x00000008) && s_imlTBGlyphs.arhiml[0])
|
|
{
|
|
StartCAP();
|
|
}
|
|
|
|
HRESULT hres = _CreateBands();
|
|
if (FAILED(hres))
|
|
return hres;
|
|
|
|
if (!_nVisibleBands && fShow)
|
|
return(FALSE);
|
|
|
|
_fShow = fShow;
|
|
|
|
_bs.UIActivateDBC(fShow ? DBC_SHOW : DBC_HIDE);
|
|
|
|
ResizeBorderDW(NULL, NULL, FALSE);
|
|
ShowWindow(_hwnd, fShow ? SW_SHOW : SW_HIDE);
|
|
|
|
|
|
BOOL fConnect = (fShow && _dwcpCookie == 0);
|
|
if (fConnect || (!fShow && _dwcpCookie != 0))
|
|
{
|
|
ConnectToConnectionPoint(SAFECAST(this, IDockingWindow*), DIID_DWebBrowserEvents2, fConnect, _pdie, &_dwcpCookie, NULL);
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
int ITBar_TrackPopupMenuEx(HMENU hmenu, UINT uFlags, int x, int y, HWND hwnd, LPRECT prcExclude)
|
|
{
|
|
TPMPARAMS tpm;
|
|
if (prcExclude)
|
|
{
|
|
tpm.cbSize = sizeof(TPMPARAMS);
|
|
CopyRect(&tpm.rcExclude, prcExclude);
|
|
}
|
|
return TrackPopupMenuEx(hmenu, uFlags, x, y, hwnd, prcExclude ? &tpm : NULL);
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: CInternetToolbar::_ShowBackForwardMenu
|
|
|
|
SYNOPSIS:
|
|
NOTES:
|
|
********************************************************************/
|
|
BOOL CInternetToolbar::_ShowBackForwardMenu(BOOL fForward, POINT pt, LPRECT prcExclude)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
HMENU hmenuBF = CreatePopupMenu();
|
|
if (hmenuBF)
|
|
{
|
|
ASSERT(_pbs2);
|
|
ITravelLog *ptl;
|
|
|
|
_pbs2->GetTravelLog(&ptl);
|
|
if (NULL != ptl)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = ptl->InsertMenuEntries(_pbs2, hmenuBF, 0, 1, MAX_NAV_MENUITEMS, fForward ? TLMENUF_FORE : TLMENUF_BACK);
|
|
if (S_OK == hr)
|
|
{
|
|
OLECMD cmd;
|
|
|
|
cmd.cmdID = SBCMDID_HISTORYBAR;
|
|
cmd.cmdf = 0;
|
|
|
|
ASSERT(NULL != _ptbsitect);
|
|
_ptbsitect->QueryStatus(&CGID_Explorer, 1, &cmd, NULL);
|
|
|
|
if (((cmd.cmdf & OLECMDF_ENABLED) && !(cmd.cmdf & OLECMDF_LATCHED)) &&
|
|
(1 /* MAX_NAV_MENUITEMS */ < ptl->CountEntries(_pbs2)))
|
|
{
|
|
static TCHAR s_szMenuText[MAX_PATH];
|
|
static int s_iMenuIcon = -1;
|
|
|
|
if (TEXT('\0') == s_szMenuText[0])
|
|
{
|
|
MLLoadString(IDS_MI_BACK_HISTORY, s_szMenuText, ARRAYSIZE(s_szMenuText));
|
|
ASSERT(TEXT('\0') != s_szMenuText[0]);
|
|
}
|
|
|
|
if (-1 == s_iMenuIcon)
|
|
{
|
|
IShellFolder *psfParent;
|
|
LPITEMIDLIST pidlHistory;
|
|
LPCITEMIDLIST pidlItem;
|
|
|
|
psfParent = NULL;
|
|
pidlHistory = NULL;
|
|
pidlItem = NULL;
|
|
|
|
SHGetSpecialFolderLocation(NULL, CSIDL_HISTORY, &pidlHistory);
|
|
if (NULL != pidlHistory)
|
|
{
|
|
SHBindToIDListParent(pidlHistory, IID_PPV_ARG(IShellFolder, &psfParent), &pidlItem);
|
|
if (NULL != psfParent)
|
|
{
|
|
ASSERT(NULL != pidlItem);
|
|
|
|
hr = SHMapPIDLToSystemImageListIndex(psfParent, pidlItem, &s_iMenuIcon);
|
|
if (FAILED(hr))
|
|
s_iMenuIcon = -1;
|
|
|
|
psfParent->Release();
|
|
}
|
|
|
|
ILFree(pidlHistory);
|
|
}
|
|
}
|
|
|
|
ULONG_PTR rgpData[2];
|
|
|
|
rgpData[0] = (ULONG_PTR)s_szMenuText;
|
|
rgpData[1] = s_iMenuIcon;
|
|
|
|
AppendMenu(hmenuBF, MF_SEPARATOR, -1, NULL);
|
|
AppendMenu(hmenuBF, MF_OWNERDRAW, FCIDM_VBBHISTORYBAND, (PCTSTR)rgpData);
|
|
}
|
|
|
|
// If any menu items were added, show the menu and navigate to it
|
|
#ifndef MAINWIN
|
|
int nIndex;
|
|
|
|
if (nIndex = ITBar_TrackPopupMenuEx (hmenuBF, TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, _hwnd, prcExclude))
|
|
#else
|
|
// Because mainwin doesn't support win95 look and feel we are
|
|
// having a problem to keep the popup from dismissing when we
|
|
// pass NULL as noDismissal area.
|
|
RECT rect;
|
|
GetWindowRect( _hwnd, &rect );
|
|
if (nIndex = (int)TrackPopupMenu (hmenuBF,
|
|
TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD,
|
|
pt.x, pt.y, 0, _hwnd,
|
|
&rect))
|
|
#endif
|
|
{
|
|
if (FCIDM_VBBHISTORYBAND != nIndex)
|
|
{
|
|
ptl->Travel(_pbs2, (fForward ? nIndex : -nIndex));
|
|
}
|
|
else
|
|
{
|
|
VARIANTARG varOn;
|
|
|
|
varOn.vt = VT_I4;
|
|
varOn.lVal = 1;
|
|
|
|
_ptbsitect->Exec(&CGID_Explorer, SBCMDID_HISTORYBAR, OLECMDEXECOPT_DONTPROMPTUSER, &varOn, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
ptl->Release();
|
|
}
|
|
|
|
DestroyMenu (hmenuBF);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
// get per folder search items and default search
|
|
BOOL CInternetToolbar::_GetFolderSearchData()
|
|
{
|
|
int iInserted=0;
|
|
|
|
if (_pbs2)
|
|
{
|
|
LPCBASEBROWSERDATA pbbd;
|
|
|
|
if (SUCCEEDED(_pbs2->GetBaseBrowserData(&pbbd)) && (pbbd->_psfPending || pbbd->_psf))
|
|
{
|
|
IShellFolder2 * psf2;
|
|
IShellFolder* psf = pbbd->_psfPending ? pbbd->_psfPending : pbbd->_psf;
|
|
|
|
if (SUCCEEDED(psf->QueryInterface(IID_PPV_ARG(IShellFolder2, &psf2))))
|
|
{
|
|
LPENUMEXTRASEARCH penum;
|
|
GUID guid;
|
|
|
|
if (SUCCEEDED(psf2->GetDefaultSearchGUID(&guid)))
|
|
_guidDefaultSearch = guid;
|
|
|
|
// get per folder search items
|
|
if (_hdpaFSI && SUCCEEDED(psf2->EnumSearches(&penum)))
|
|
{
|
|
EXTRASEARCH xs;
|
|
|
|
while(penum->Next(1, &xs, NULL) == S_OK)
|
|
{
|
|
LPFOLDERSEARCHITEM pfsi = (LPFOLDERSEARCHITEM)LocalAlloc(LPTR, sizeof(FOLDERSEARCHITEM));
|
|
if (pfsi)
|
|
{
|
|
pfsi->idCmd = -1;
|
|
pfsi->guidSearch = xs.guidSearch;
|
|
StrCpyNW(pfsi->wszUrl, xs.wszUrl, ARRAYSIZE(pfsi->wszUrl));
|
|
StrCpyNW(pfsi->wszName, xs.wszFriendlyName, ARRAYSIZE(pfsi->wszName));
|
|
|
|
if (DPA_InsertPtr(_hdpaFSI, iInserted, pfsi) != -1)
|
|
iInserted++;
|
|
else
|
|
LocalFree(pfsi);
|
|
}
|
|
}
|
|
penum->Release();
|
|
}
|
|
psf2->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
return (iInserted > 0);
|
|
}
|
|
|
|
BOOL NavigateSearchBar(IWebBrowser2 *pwb2, LPCWSTR pwszUrl)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
SA_BSTRGUID bstr;
|
|
InitFakeBSTR(&bstr, CLSID_SearchBand);
|
|
|
|
VARIANT var;
|
|
var.vt = VT_BSTR;
|
|
var.bstrVal = bstr.wsz;
|
|
|
|
// show a search bar
|
|
VARIANT varEmpty = {0};
|
|
if (SUCCEEDED(pwb2->ShowBrowserBar(&var, &varEmpty, &varEmpty)))
|
|
{
|
|
VARIANT varTargetFrame = {0};
|
|
VARIANT varFlags = {0};
|
|
|
|
StrCpyNW(bstr.wsz, pwszUrl, ARRAYSIZE(bstr.wsz));
|
|
bstr.cb = lstrlenW(bstr.wsz) * sizeof(WCHAR);
|
|
|
|
varFlags.vt = VT_I4;
|
|
varFlags.lVal = navBrowserBar;
|
|
|
|
var.vt = VT_BSTR;
|
|
var.bstrVal = bstr.wsz;
|
|
|
|
// navigate the search bar to the correct url
|
|
if (SUCCEEDED(pwb2->Navigate2(&var, &varFlags, &varTargetFrame, &varEmpty, &varEmpty)))
|
|
bRet = TRUE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
void RestrictItbarViewMenu(HMENU hmenu, IUnknown *punkBar )
|
|
{
|
|
BOOL fIsRestricted = SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0);
|
|
if (fIsRestricted)
|
|
{
|
|
_EnableMenuItem(hmenu, FCIDM_VIEWLINKS, FALSE);
|
|
_EnableMenuItem(hmenu, FCIDM_VIEWMENU, FALSE);
|
|
_EnableMenuItem(hmenu, FCIDM_VIEWADDRESS, FALSE);
|
|
_EnableMenuItem(hmenu, FCIDM_VIEWTOOLS, FALSE);
|
|
}
|
|
|
|
for (int i = 0; i < MAXEXTERNALBANDS; i++)
|
|
{
|
|
OLECMD cmd = { CITIDM_VIEWEXTERNALBAND_FIRST + i, 0 };
|
|
OLECMDTEXTV<MAX_EXTERNAL_BAND_NAME_LEN> cmdtv;
|
|
OLECMDTEXT *pcmdText = &cmdtv;
|
|
pcmdText->cmdtextf = OLECMDTEXTF_NAME;
|
|
pcmdText->cwActual = 0;
|
|
pcmdText->cwBuf = MAX_EXTERNAL_BAND_NAME_LEN;
|
|
|
|
IUnknown_QueryStatus( punkBar, &CGID_PrivCITCommands, 1, &cmd, pcmdText );
|
|
if (cmd.cmdf & OLECMDF_SUPPORTED)
|
|
{
|
|
DWORD dwMenuCommand = FCIDM_EXTERNALBANDS_FIRST + i;
|
|
InsertMenu( hmenu, FCIDM_VIEWCONTEXTMENUSEP, MF_BYCOMMAND, dwMenuCommand, pcmdText->rgwz );
|
|
if (cmd.cmdf & OLECMDF_ENABLED)
|
|
{
|
|
_CheckMenuItem( hmenu, dwMenuCommand, TRUE );
|
|
}
|
|
if (fIsRestricted)
|
|
{
|
|
_EnableMenuItem( hmenu, dwMenuCommand, FALSE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CInternetToolbar::_ShowContextMenu(HWND hwnd, LPARAM lParam, LPRECT prcExclude)
|
|
{
|
|
// Bail if this context menu doesn't correspond to a band (fixes NT5 #181899)
|
|
POINT pt;
|
|
int iIndex = _bs._ContextMenuHittest(lParam, &pt);
|
|
int idBandActive = _bs._IndexToBandID(iIndex);
|
|
if (!InRange(idBandActive, CBIDX_FIRST, CBANDSMAX))
|
|
return;
|
|
|
|
// Bail if we can't find the resource
|
|
HMENU hmenuITB = LoadMenuPopup(MENU_ITOOLBAR);
|
|
if (!hmenuITB)
|
|
return;
|
|
|
|
UEMFireEvent(&UEMIID_SHELL, UEME_INSTRBROWSER, UEMF_INSTRUMENT, UIBW_UICONTEXT, idBandActive == -1 ? UIBL_CTXTITBBKGND : UIBL_CTXTITBITEM);
|
|
|
|
// Set the initial state of the menu
|
|
_CheckMenuItem (hmenuITB, FCIDM_VIEWTOOLS, _nVisibleBands & VBF_TOOLS);
|
|
_CheckMenuItem (hmenuITB, FCIDM_VIEWADDRESS, _nVisibleBands & VBF_ADDRESS);
|
|
_CheckMenuItem (hmenuITB, FCIDM_VIEWLINKS, _nVisibleBands & VBF_LINKS);
|
|
|
|
int cItemsBelowSep = 4;
|
|
|
|
// only in theater mode can we autohide
|
|
if (!_fTheater)
|
|
{
|
|
DeleteMenu(hmenuITB, FCIDM_VIEWAUTOHIDE, MF_BYCOMMAND);
|
|
cItemsBelowSep--;
|
|
if (_nVisibleBands & VBF_MENU || _fNoShowMenu)
|
|
DeleteMenu(hmenuITB, FCIDM_VIEWMENU, MF_BYCOMMAND);
|
|
}
|
|
else
|
|
{
|
|
if (_fNoShowMenu)
|
|
DeleteMenu(hmenuITB, FCIDM_VIEWMENU, MF_BYCOMMAND);
|
|
DeleteMenu(hmenuITB, FCIDM_VIEWTOOLS, MF_BYCOMMAND);
|
|
_CheckMenuItem (hmenuITB, FCIDM_VIEWAUTOHIDE, _fAutoHide);
|
|
_CheckMenuItem (hmenuITB, FCIDM_VIEWMENU, _nVisibleBands & VBF_MENU);
|
|
|
|
}
|
|
|
|
if (_fTheater || SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0))
|
|
{
|
|
// No lock in theater mode or Windows Explorer
|
|
DeleteMenu(hmenuITB, FCIDM_VIEWLOCKTOOLBAR, MF_BYCOMMAND);
|
|
}
|
|
else
|
|
{
|
|
_CheckMenuItem(hmenuITB, FCIDM_VIEWLOCKTOOLBAR, _fLockedToolbar);
|
|
}
|
|
|
|
// if it was done via the keyboard, but focus wasn't on the tools band,
|
|
// then don't have customize menu option
|
|
// or if click didn't happen on the band
|
|
if (!(_btb._fCustomize && idBandActive == CBIDX_TOOLS))
|
|
{
|
|
DeleteMenu(hmenuITB, FCIDM_VIEWTOOLBARCUSTOMIZE, MF_BYCOMMAND);
|
|
cItemsBelowSep--;
|
|
}
|
|
|
|
BOOL fGoButtonAvailable =
|
|
WasOpenedAsBrowser(static_cast<IExplorerToolbar *>(this)) || (GetUIVersion() >= 5);
|
|
|
|
// Only show the go button item when you click on the address bar
|
|
if (idBandActive != CBIDX_ADDRESS || !fGoButtonAvailable)
|
|
{
|
|
DeleteMenu(hmenuITB, FCIDM_VIEWGOBUTTON, MF_BYCOMMAND);
|
|
cItemsBelowSep--;
|
|
}
|
|
else
|
|
{
|
|
BOOL fShowGoButton = SHRegGetBoolUSValue(REGSTR_PATH_MAIN,
|
|
TEXT("ShowGoButton"), FALSE, /*default*/TRUE);
|
|
_CheckMenuItem(hmenuITB, FCIDM_VIEWGOBUTTON, fShowGoButton);
|
|
}
|
|
|
|
if (_fTheater || _btb._fCustomize || SHRestricted2(REST_LOCKICONSIZE, NULL, 0))
|
|
{
|
|
DeleteMenu(hmenuITB, FCIDM_VIEWTEXTLABELS, MF_BYCOMMAND);
|
|
cItemsBelowSep--;
|
|
}
|
|
else
|
|
{
|
|
// If customize is unavailable, then there's no way for the user to
|
|
// turn list style on/off. In this case we want toggling text labels
|
|
// to work the way it did in IE4 -- that is, switch between "text on
|
|
// all buttons" and "text on no buttons". So, if we're in "selective
|
|
// text on right" mode, we say that labels are turned off. If the user
|
|
// picks this menu option, we'll go into "text on all buttons" mode.
|
|
|
|
BOOL fChecked = !_fCompressed && !IS_LIST_STYLE(_btb._hwnd);
|
|
_CheckMenuItem(hmenuITB, FCIDM_VIEWTEXTLABELS, fChecked);
|
|
}
|
|
|
|
if (!cItemsBelowSep)
|
|
DeleteMenu(hmenuITB, FCIDM_VIEWCONTEXTMENUSEP, MF_BYCOMMAND);
|
|
|
|
RestrictItbarViewMenu(hmenuITB, SAFECAST( this, IOleCommandTarget* ) );
|
|
ITBar_TrackPopupMenuEx(hmenuITB, TPM_LEFTBUTTON | TPM_RIGHTBUTTON, pt.x, pt.y, _hwnd, prcExclude);
|
|
|
|
// HACK: since the ITBar isn't a real bar/bandsite, we have to
|
|
// do this so any menuband that might be up can take back the
|
|
// mouse capture.
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_MENU);
|
|
if (pbid)
|
|
IUnknown_Exec(pbid->pdb, &CGID_MenuBand, MBANDCID_RECAPTURE, 0, NULL, NULL);
|
|
|
|
DestroyMenu (hmenuITB);
|
|
}
|
|
|
|
|
|
void CInternetToolbar::_QueryStatusTip(IOleCommandTarget *pct, LPTOOLTIPTEXT pnmTT, UINT uiCmd, const GUID* pguid)
|
|
{
|
|
OLECMD rgcmd = { uiCmd, 0 };
|
|
OLECMDTEXTV<MAX_TOOLTIP_STRING> cmdtv;
|
|
OLECMDTEXT *pcmdText = &cmdtv;
|
|
|
|
pcmdText->cwBuf = MAX_TOOLTIP_STRING;
|
|
pcmdText->cmdtextf = OLECMDTEXTF_NAME;
|
|
pcmdText->rgwz[0] = 0;
|
|
pct->QueryStatus(pguid, 1, &rgcmd, pcmdText);
|
|
if (rgcmd.cmdf & OLECMDF_ENABLED)
|
|
{
|
|
SHUnicodeToTChar(pcmdText->rgwz, pnmTT->szText, MAX_TOOLTIP_STRING);
|
|
}
|
|
|
|
}
|
|
|
|
BOOL _IsDocHostGUID(const GUID* pguid)
|
|
{
|
|
// Dochost merges under one of two clsids, so have to check both
|
|
BOOL fRet = IsEqualGUID(*pguid, CLSID_InternetButtons) ||
|
|
IsEqualGUID(*pguid, CLSID_MSOButtons);
|
|
return fRet;
|
|
}
|
|
|
|
void _PruneAmpersands(LPTSTR psz)
|
|
{
|
|
//
|
|
// Collapse double ampersands in the string to single
|
|
// ampersands, and rip out single ampersands. e.g.,
|
|
//
|
|
// "AT&T" -> "ATT"
|
|
// "AT&&T" -> "AT&T"
|
|
//
|
|
// We need to do this to hack around the ToolTips control's
|
|
// annoying prefix behavior. When TTS_NOPREFIX is set
|
|
// (which is true of itbar's), TT leaves prefix characters
|
|
// alone completely. However when it is not set, besides just
|
|
// letting DrawText do it's prefix thing on the string, TT also
|
|
// pre-processes the string using an analogous version of the
|
|
// below function, collapsing double ampersands to single
|
|
// ampersands and ripping out single ampersands. This is so
|
|
// that that if you use menu text (e.g. "&File") as a tooltip,
|
|
// you won't get an underline. Unfortunately, the side effect
|
|
// is that you're in trouble if you really wanted an ampersand in
|
|
// the title (e.g. "AT&&T"), since the preprocessing turns "AT&&T"
|
|
// into "AT&T", which DrawText then renders with an underline.
|
|
//
|
|
// Thus we have to leave TTS_NOPREFIX set and mimic the DrawText
|
|
// preprocessing ourselves.
|
|
//
|
|
|
|
if (psz)
|
|
{
|
|
LPTSTR pszOut = psz;
|
|
BOOL fLastAmpSkipped = FALSE;
|
|
|
|
while (*psz)
|
|
{
|
|
if (*psz == TEXT('&'))
|
|
{
|
|
if (fLastAmpSkipped)
|
|
{
|
|
fLastAmpSkipped = FALSE;
|
|
*pszOut++ = *psz;
|
|
}
|
|
else
|
|
{
|
|
fLastAmpSkipped = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pszOut++ = *psz;
|
|
}
|
|
|
|
psz++;
|
|
}
|
|
|
|
*pszOut = TEXT('\0');
|
|
}
|
|
}
|
|
|
|
void CInternetToolbar::_OnTooltipNeeded(LPTOOLTIPTEXT pnmTT)
|
|
{
|
|
UINT uiCmd;
|
|
GUID guid;
|
|
|
|
ASSERT(pnmTT->hdr.hwndFrom == (HWND)SendMessage(_btb._hwnd, TB_GETTOOLTIPS, 0, 0));
|
|
|
|
// Make sure tooltips don't filter out ampersands
|
|
LONG lStyle = GetWindowLong(pnmTT->hdr.hwndFrom, GWL_STYLE);
|
|
if (!IsFlagSet(lStyle, TTS_NOPREFIX))
|
|
{
|
|
SetWindowLong(pnmTT->hdr.hwndFrom, GWL_STYLE, lStyle | TTS_NOPREFIX);
|
|
}
|
|
|
|
|
|
if (SUCCEEDED(_btb._ConvertCmd(NULL, (UINT)pnmTT->hdr.idFrom, &guid, &uiCmd)))
|
|
{
|
|
if (IsEqualGUID(guid, CLSID_CommonButtons))
|
|
{
|
|
switch (uiCmd)
|
|
{
|
|
case TBIDM_FORWARD:
|
|
case TBIDM_BACK:
|
|
if (_ptbsite)
|
|
{
|
|
IBrowserService *pbsvc;
|
|
|
|
if (SUCCEEDED(_ptbsite->QueryInterface(IID_PPV_ARG(IBrowserService, &pbsvc))))
|
|
{
|
|
// FEATURE raymondc - make ITravelLog UNICODE someday
|
|
ITravelLog *ptl;
|
|
pbsvc->GetTravelLog( &ptl );
|
|
if (ptl)
|
|
{
|
|
WCHAR szTemp[ARRAYSIZE(pnmTT->szText)];
|
|
if (uiCmd == TBIDM_BACK)
|
|
ptl->GetToolTipText(pbsvc, TLOG_BACK, 0, szTemp, ARRAYSIZE(szTemp));
|
|
else if (uiCmd == TBIDM_FORWARD)
|
|
ptl->GetToolTipText(pbsvc, TLOG_FORE, 0, szTemp, ARRAYSIZE(szTemp));
|
|
|
|
SHUnicodeToTChar(szTemp, pnmTT->szText, ARRAYSIZE(pnmTT->szText));
|
|
|
|
ptl->Release();
|
|
}
|
|
pbsvc->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#ifdef EDIT_HACK
|
|
// Dochost merges under one of two clsids, so have to check both
|
|
else if (_IsDocHostGUID(&guid))
|
|
{
|
|
if (uiCmd == DVIDM_EDITPAGE)
|
|
{
|
|
_aEditVerb.GetToolTip(pnmTT->szText, ARRAYSIZE(pnmTT->szText));
|
|
}
|
|
else
|
|
{
|
|
// If the button text is hidden or truncated, we use that text for the tooltip.
|
|
TBBUTTONINFO tbbi = {0};
|
|
tbbi.cbSize = sizeof(TBBUTTONINFO);
|
|
tbbi.dwMask = TBIF_STYLE | TBIF_STATE;
|
|
SendMessage(_btb._hwnd, TB_GETBUTTONINFO, pnmTT->hdr.idFrom, (LPARAM)&tbbi);
|
|
|
|
if (_fCompressed ||
|
|
IS_LIST_STYLE(_btb._hwnd) && !(tbbi.fsStyle & BTNS_SHOWTEXT) ||
|
|
(tbbi.fsState & TBSTATE_ELLIPSES))
|
|
{
|
|
//
|
|
// Get the button text and fix up the ampersands so that the
|
|
// tooltip will look right
|
|
//
|
|
if (SendMessage(_btb._hwnd, TB_GETBUTTONTEXT, pnmTT->hdr.idFrom, (LPARAM)&pnmTT->szText))
|
|
{
|
|
_PruneAmpersands(pnmTT->szText);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
LRESULT CInternetToolbar::_OnBeginDrag(NMREBAR *pnm)
|
|
{
|
|
if (SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0) || _fLockedToolbar)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (_fTheater)
|
|
{
|
|
// if we're in theater mode, we do our own drag handling where we force
|
|
// all the mouse moves into the middle of the band, thereby disallowing
|
|
// the user to make a multi line rebar
|
|
SetCapture(_hwnd);
|
|
SendMessage(_bs._hwnd, RB_BEGINDRAG, pnm->uBand, (LPARAM)-2);
|
|
_fRebarDragging = TRUE;
|
|
return 1;
|
|
}
|
|
return SHRestricted2(REST_NoToolbarOptions, NULL, 0);
|
|
}
|
|
|
|
LRESULT CInternetToolbar::_OnNotify(LPNMHDR pnmh)
|
|
{
|
|
LRESULT lres = 0;
|
|
if (!_pdie)
|
|
return 0;
|
|
|
|
if (pnmh->code == TTN_NEEDTEXT && pnmh->hwndFrom == (HWND)SendMessage(_btb._hwnd, TB_GETTOOLTIPS, 0, 0))
|
|
{
|
|
_OnTooltipNeeded((LPTOOLTIPTEXT)pnmh);
|
|
return 0;
|
|
}
|
|
|
|
if(_SendToToolband(pnmh->hwndFrom, WM_NOTIFY,0, (LPARAM)pnmh, &lres))
|
|
return lres;
|
|
|
|
switch (pnmh->idFrom)
|
|
{
|
|
case FCIDM_REBAR:
|
|
switch (pnmh->code)
|
|
{
|
|
case RBN_BEGINDRAG:
|
|
return _OnBeginDrag((NMREBAR*)pnmh);
|
|
|
|
case RBN_HEIGHTCHANGE:
|
|
ResizeBorderDW(NULL, NULL, FALSE);
|
|
break;
|
|
|
|
case RBN_CHILDSIZE:
|
|
{
|
|
// make the brand always take the full height
|
|
NMREBARCHILDSIZE *pnm = (NMREBARCHILDSIZE*)pnmh;
|
|
if (pnm->wID == CBIDX_BRAND)
|
|
{
|
|
pnm->rcChild.top = pnm->rcBand.top;
|
|
pnm->rcChild.bottom = pnm->rcBand.bottom;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case RBN_LAYOUTCHANGED:
|
|
//Because the layout has changed, remember to save later!
|
|
_fDirty = TRUE;
|
|
_UpdateBrandSize();
|
|
|
|
if (_ptbsitect)
|
|
_ptbsitect->Exec(&CGID_ShellBrowser, FCIDM_PERSISTTOOLBAR, 0, NULL, NULL);
|
|
break;
|
|
|
|
case RBN_GETOBJECT:
|
|
{
|
|
NMOBJECTNOTIFY *pnmon = (NMOBJECTNOTIFY *)pnmh;
|
|
if (IsEqualIID(*pnmon->piid, IID_IDropTarget))
|
|
{
|
|
HWND hwnd;
|
|
|
|
switch (pnmon->iItem)
|
|
{
|
|
case CBIDX_MENU:
|
|
case CBIDX_LINKS:
|
|
{
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(pnmon->iItem);
|
|
if (pbid && pbid->pdb)
|
|
{
|
|
pnmon->hResult = pbid->pdb->QueryInterface(IID_IDropTarget, (void**)&pnmon->pObject);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case CBIDX_TOOLS:
|
|
hwnd = _btb._hwnd;
|
|
pnmon->hResult = (HRESULT)SendMessage(hwnd, TB_GETOBJECT,
|
|
(WPARAM)&IID_IDropTarget, (LPARAM)&pnmon->pObject);
|
|
break;
|
|
|
|
case CBIDX_ADDRESS:
|
|
if (_ptbsite)
|
|
{
|
|
pnmon->hResult = _ptbsite->QueryInterface(IID_IDropTarget, (void**)&pnmon->pObject);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
ASSERT((SUCCEEDED(pnmon->hResult) && pnmon->pObject) ? (IS_VALID_CODE_PTR(pnmon->pObject, IUnknown)) : (pnmon->pObject == NULL));
|
|
return TRUE;
|
|
}
|
|
|
|
case RBN_CHEVRONPUSHED:
|
|
{
|
|
LPNMREBARCHEVRON pnmch = (LPNMREBARCHEVRON) pnmh;
|
|
if (pnmch->wID == CBIDX_TOOLS)
|
|
{
|
|
int idMenu = MENU_TBMENU;
|
|
// this must be the tools band (not enumerated in bandsite)
|
|
MapWindowPoints(pnmh->hwndFrom, HWND_DESKTOP, (LPPOINT)&pnmch->rc, 2);
|
|
if (!_btb._fCustomize)
|
|
idMenu = 0;
|
|
|
|
ToolbarMenu_Popup(_hwnd, &pnmch->rc, NULL, _btb._hwnd, idMenu, (DWORD)pnmch->lParamNM);
|
|
return TRUE;
|
|
}
|
|
_bs._OnNotify(pnmh);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
return _bs._OnNotify(pnmh);
|
|
|
|
} // switch (pnmh->code)
|
|
break;
|
|
|
|
} // switch (pnmh->idFrom)
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: CInternetToolbar::_DoNavigateA
|
|
|
|
SYNOPSIS: Called when the user types in or selects a URL
|
|
to navigate to through the address bar
|
|
|
|
NOTES: This function calls the helper function _DoNavigate.
|
|
This is just here to convert the ANSI string to
|
|
a BSTR.
|
|
|
|
********************************************************************/
|
|
HRESULT CInternetToolbar::_DoNavigateA(LPSTR pszURL, int iNewSelection)
|
|
{
|
|
ASSERT(pszURL); // must have valid URL to navigate to
|
|
|
|
LBSTR::CString strText;
|
|
|
|
LPTSTR pstrText = strText.GetBuffer( MAX_URL_STRING );
|
|
|
|
if ( strText.GetAllocLength() < MAX_URL_STRING )
|
|
{
|
|
TraceMsg( TF_WARNING, "CInternetToolbar::_DoNavigateA() - strText Allocation Failed!" );
|
|
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
SHAnsiToUnicode( pszURL, pstrText, MAX_URL_STRING );
|
|
|
|
strText.ReleaseBuffer();
|
|
|
|
return _DoNavigate( strText, iNewSelection );
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: CInternetToolbar::_DoNavigateW
|
|
|
|
SYNOPSIS: Called when the user types in or selects a URL
|
|
to navigate to through the address bar
|
|
|
|
NOTES: This function calls the helper function _DoNavigate.
|
|
This is just here to convert the Unicode string to
|
|
a BSTR.
|
|
|
|
********************************************************************/
|
|
HRESULT CInternetToolbar::_DoNavigateW(LPWSTR pwzURL, int iNewSelection)
|
|
{
|
|
ASSERT(pwzURL); // must have valid URL to navigate to
|
|
|
|
LBSTR::CString strPath( pwzURL );
|
|
|
|
return _DoNavigate( strPath, iNewSelection );
|
|
}
|
|
|
|
/*******************************************************************
|
|
|
|
NAME: CInternetToolbar::_DoNavigate
|
|
|
|
SYNOPSIS: Called when the user types in or selects a URL
|
|
to navigate to through the address bar
|
|
|
|
ENTRY: bstrURL - string of URL to navigate to, in BSTR form
|
|
iNewSelection - index of current selection in address
|
|
bar combo box
|
|
|
|
********************************************************************/
|
|
HRESULT CInternetToolbar::_DoNavigate(BSTR bstrURL,int iNewSelection)
|
|
{
|
|
HRESULT hr;
|
|
|
|
ASSERT(bstrURL); // must have valid URL to browse to
|
|
ASSERT(_pdie); // must have valid pointer to automation interface
|
|
|
|
VARIANTARG v;
|
|
VariantInit (&v);
|
|
|
|
v.vt = VT_I4;
|
|
v.lVal = navAllowAutosearch;
|
|
|
|
// call automation interface to make browser navigate to this URL
|
|
hr = _pdie->Navigate(bstrURL, &v, PVAREMPTY, PVAREMPTY, PVAREMPTY);
|
|
|
|
VariantClearLazy(&v);
|
|
|
|
return hr;
|
|
}
|
|
|
|
LPITEMIDLIST CInternetToolbar::_GetCurrentPidl(void)
|
|
{
|
|
LPITEMIDLIST pidl = NULL;
|
|
|
|
ASSERT(_pbs2);
|
|
if (_pbs2)
|
|
{
|
|
_pbs2->GetPidl(&pidl);
|
|
}
|
|
|
|
return pidl;
|
|
}
|
|
|
|
void CInternetToolbar::_CommonHandleFileSysChange(LONG lEvent, LPITEMIDLIST* ppidl)
|
|
{
|
|
// stuff that needs to be done tree or no tree
|
|
switch (lEvent)
|
|
{
|
|
// README:
|
|
// If you need to add events here, then you must change SHELLBROWSER_FSNOTIFY_FLAGS in
|
|
// shbrowse.cpp in order to get the notifications
|
|
case SHCNE_DRIVEREMOVED:
|
|
case SHCNE_MEDIAREMOVED:
|
|
case SHCNE_MEDIAINSERTED:
|
|
case SHCNE_DRIVEADD:
|
|
case SHCNE_UPDATEIMAGE:
|
|
case SHCNE_UPDATEITEM:
|
|
// Forward this command to CAddressBand::FileSysChange()
|
|
// by using IToolbandHelper::OnWinEvent().
|
|
{
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
|
|
if (pbid)
|
|
{
|
|
// REVIEW: why don't we use IShellChangeNotify here?
|
|
//
|
|
IUnknown_FileSysChange(pbid->pdb, (DWORD)lEvent, (LPCITEMIDLIST*)ppidl);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
HRESULT CInternetToolbar::OnChange(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
|
|
{
|
|
LPITEMIDLIST ppidl[2] = {(LPITEMIDLIST)pidl1, (LPITEMIDLIST)pidl2};
|
|
_CommonHandleFileSysChange(lEvent, ppidl);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CInternetToolbar::_OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (!_pdie)
|
|
return;
|
|
|
|
HWND hwndControl = GET_WM_COMMAND_HWND(wParam, lParam);
|
|
UINT idCmd = GET_WM_COMMAND_ID(wParam, lParam);
|
|
|
|
// If this is a command from the toolbar, and it is not one of the StdBrowseButtons
|
|
// call Exec() on the appropriate CmdTarget
|
|
if (hwndControl == _btb._hwnd)
|
|
{
|
|
UINT uiInternalCmdID = idCmd;
|
|
|
|
// Convert to the real thing and get the guid
|
|
CMDMAP* pcm = _btb._GetCmdMapByID(idCmd);
|
|
|
|
IOleCommandTarget* pct = _btb._CommandTargetFromCmdMap(pcm);
|
|
if (pct)
|
|
{
|
|
VARIANTARG var;
|
|
var.vt = VT_I4;
|
|
var.lVal = uiInternalCmdID;
|
|
if (SHIsSameObject(_btb._pctCurrentButtonGroup, pct))
|
|
{
|
|
// give the browser a chance to pick this off in case
|
|
// focus doesn't belong to the view currently
|
|
if (SUCCEEDED(_ptbsitect->Exec(&IID_IExplorerToolbar, pcm->nCmdID, 0, NULL, &var)))
|
|
return;
|
|
}
|
|
|
|
UEMFireEvent(&UEMIID_BROWSER, UEME_UITOOLBAR, UEMF_XEVENT,
|
|
UIG_COMMON, (LPARAM)pcm->nCmdID);
|
|
pct->Exec(&pcm->guidButtonGroup, (DWORD)pcm->nCmdID, 0, NULL, &var);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (_SendToToolband(hwndControl, WM_COMMAND, wParam, lParam, NULL))
|
|
return;
|
|
|
|
|
|
// this switch block actually executes
|
|
switch(idCmd)
|
|
{
|
|
case FCIDM_VIEWTOOLBARCUSTOMIZE:
|
|
ASSERT(!SHRestricted2(REST_NOTOOLBARCUSTOMIZE, NULL, 0));
|
|
SendMessage (_btb._hwnd, TB_CUSTOMIZE, 0, 0L);
|
|
break;
|
|
|
|
case FCIDM_DRIVELIST:
|
|
_SendToToolband(_hwndAddressBand, WM_COMMAND, wParam, lParam, NULL);
|
|
break;
|
|
|
|
case FCIDM_VIEWADDRESS:
|
|
case FCIDM_VIEWTOOLS:
|
|
case FCIDM_VIEWMENU:
|
|
case FCIDM_VIEWLINKS:
|
|
if (!SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0)
|
|
&& !SHRestricted2(REST_NoToolbarOptions, NULL, 0))
|
|
{
|
|
DWORD dw = _nVisibleBands;
|
|
switch (idCmd)
|
|
{
|
|
case FCIDM_VIEWTOOLS:
|
|
dw ^= VBF_TOOLS;
|
|
break;
|
|
case FCIDM_VIEWMENU:
|
|
dw ^= VBF_MENU;
|
|
break;
|
|
case FCIDM_VIEWADDRESS:
|
|
dw ^= VBF_ADDRESS;
|
|
break;
|
|
case FCIDM_VIEWLINKS:
|
|
dw ^= VBF_LINKS;
|
|
break;
|
|
}
|
|
if ( !( dw & ~VBF_BRAND))
|
|
{
|
|
_pdie->put_ToolBar( FALSE );
|
|
}
|
|
|
|
_ShowVisible(dw, TRUE);
|
|
}
|
|
return;
|
|
|
|
case FCIDM_VIEWAUTOHIDE:
|
|
{
|
|
ASSERT(_fTheater);
|
|
_fAutoHide = !_fAutoHide;
|
|
|
|
VARIANTARG v = {0};
|
|
v.vt = VT_I4;
|
|
v.lVal = _fAutoHide;
|
|
IUnknown_Exec(_ptbsite, &CGID_Theater, THID_SETTOOLBARAUTOHIDE, 0, &v, NULL);
|
|
|
|
ResizeBorderDW(NULL, NULL, FALSE);
|
|
|
|
break;
|
|
}
|
|
|
|
case FCIDM_VIEWLOCKTOOLBAR:
|
|
{
|
|
_fLockedToolbar = !_fLockedToolbar;
|
|
DWORD dwResult = _fLockedToolbar;
|
|
SHSetValue(HKEY_CURRENT_USER, c_szRegKeyCoolbar, TEXT("Locked"), REG_DWORD, &dwResult, sizeof(dwResult));
|
|
_UpdateLocking();
|
|
break;
|
|
}
|
|
|
|
case FCIDM_VIEWTEXTLABELS:
|
|
if(!SHRestricted2(REST_NoToolbarOptions, NULL, 0))
|
|
{
|
|
if (!_btb._fCustomize && IS_LIST_STYLE(_btb._hwnd))
|
|
{
|
|
// If customize is unavailable, then there's no way for the user to
|
|
// turn list style on/off. In this case we want toggling text labels
|
|
// to work the way it did in IE4 -- that is, switch between "text on
|
|
// all buttons" and "text on no buttons". So, if we're in "selective
|
|
// text on right" mode, we say that labels are turned off. If the user
|
|
// picks this menu option, we'll go into "text on all buttons" mode.
|
|
|
|
_UpdateToolsStyle(FALSE);
|
|
|
|
// Make ourselves believe that text labels are turned off (so
|
|
// that _UpdateToolbarDisplay will turn them on)
|
|
|
|
_fCompressed = TRUE;
|
|
}
|
|
_UpdateToolbarDisplay(UTD_TEXTLABEL, 0, !_fCompressed, TRUE);
|
|
}
|
|
return;
|
|
|
|
case FCIDM_VIEWGOBUTTON:
|
|
_SendToToolband(_hwndAddressBand, WM_COMMAND, wParam, lParam, NULL);
|
|
break;
|
|
|
|
default:
|
|
if (InRange( idCmd, FCIDM_EXTERNALBANDS_FIRST, FCIDM_EXTERNALBANDS_LAST ))
|
|
{
|
|
if (!SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0))
|
|
{
|
|
DWORD dw = _nVisibleBands;
|
|
dw ^= EXTERNALBAND_VBF_BIT(idCmd - FCIDM_EXTERNALBANDS_FIRST);
|
|
if ( !( dw & ~VBF_BRAND))
|
|
{
|
|
_pdie->put_ToolBar( FALSE );
|
|
}
|
|
_ShowVisible(dw, TRUE);
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// get the doc property, then get the command target from that and do it
|
|
void CInternetToolbar::_SendDocCommand(UINT idCmd)
|
|
{
|
|
if (_ptbsitect)
|
|
{
|
|
VARIANTARG varIn;
|
|
VARIANTARG varOut;
|
|
VARIANTARG *pvarIn = &varIn;
|
|
VARIANTARG *pvarOut = &varOut;
|
|
|
|
VariantInit(&varIn);
|
|
VariantInit(&varOut);
|
|
|
|
|
|
switch (idCmd)
|
|
{
|
|
case OLECMDID_HIDETOOLBARS:
|
|
case OLECMDID_PRINT:
|
|
// word & excel barf if there are arguments passed to print
|
|
pvarIn = NULL;
|
|
pvarOut = NULL;
|
|
break;
|
|
|
|
case OLECMDID_ZOOM:
|
|
// get the zoom range
|
|
int iMax, iMin;
|
|
if (FAILED(_ptbsitect->Exec(NULL, OLECMDID_GETZOOMRANGE, OLECMDEXECOPT_DONTPROMPTUSER, NULL, &varOut)))
|
|
goto Bail;
|
|
|
|
if (varOut.vt == VT_I4)
|
|
{
|
|
iMin = (int)(short)LOWORD(varOut.lVal);
|
|
iMax = (int)(short)HIWORD(varOut.lVal);
|
|
}
|
|
else
|
|
goto Bail;
|
|
|
|
varOut.vt = VT_EMPTY; // return to VariantInit state
|
|
|
|
// get the current zoom depth
|
|
if (FAILED(_ptbsitect->Exec(NULL, OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, NULL, &varIn)))
|
|
goto Bail;
|
|
|
|
if (varIn.vt == VT_I4)
|
|
{
|
|
varIn.lVal++;
|
|
if ((int)varIn.lVal > iMax)
|
|
{
|
|
varIn.lVal = iMin;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
goto Bail;
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#ifdef FEATURE_IE40
|
|
_ptbsitect->Exec(NULL, idCmd, OLECMDEXECOPT_DONTPROMPTUSER, pvarIn, pvarOut);
|
|
#else
|
|
_ptbsitect->Exec(NULL, idCmd, OLECMDEXECOPT_PROMPTUSER, pvarIn, pvarOut);
|
|
#endif
|
|
|
|
Bail:
|
|
// if this fails, we should maybe do the invoke with a
|
|
// proper verb?
|
|
VariantClearLazy(&varIn);
|
|
VariantClearLazy(&varOut);
|
|
|
|
}
|
|
}
|
|
|
|
BOOL CInternetToolbar::_CompressBands(BOOL fCompress, UINT uRowsNew, BOOL fForceUpdate)
|
|
{
|
|
UINT_PTR uRowsOld = SendMessage(_btb._hwnd, TB_GETTEXTROWS, 0, 0L);
|
|
if (fCompress)
|
|
uRowsNew = 0;
|
|
|
|
if (!fForceUpdate && (uRowsOld == uRowsNew))
|
|
{
|
|
// same as what we've already got, blow it off
|
|
return FALSE;
|
|
}
|
|
|
|
_fCompressed = fCompress;
|
|
|
|
// Change the size of the Brand window and add ot remove the text
|
|
SendMessage(_btb._hwnd, TB_SETMAXTEXTROWS, uRowsNew, 0L);
|
|
|
|
UINT uWidthNew = _fCompressed ? MAX_TB_COMPRESSED_WIDTH : _uiMaxTBWidth;
|
|
SendMessage(_btb._hwnd, TB_SETBUTTONWIDTH, 0, (LPARAM) MAKELONG(0, uWidthNew));
|
|
|
|
_btb._BandInfoChanged();
|
|
|
|
_UpdateBrandSize();
|
|
_bs._SetMinDimensions();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#define ABS(x) (((x) < 0) ? -(x) : (x))
|
|
|
|
void CInternetToolbar::_TrackSliding(int x, int y)
|
|
{
|
|
INT_PTR cBands = SendMessage(_bs._hwnd, RB_GETBANDCOUNT, 0, 0L);
|
|
INT_PTR cRows = SendMessage(_bs._hwnd, RB_GETROWCOUNT, 0, 0L);
|
|
INT_PTR cyHalfRow = SendMessage(_bs._hwnd, RB_GETROWHEIGHT, cBands-1, 0L) / 2;
|
|
RECT rc;
|
|
int cyBefore;
|
|
int c;
|
|
BOOL_PTR fChanged = FALSE;
|
|
|
|
// do this instead of GetClientRect so that we include borders
|
|
GetWindowRect(_bs._hwnd, &rc);
|
|
MapWindowPoints(HWND_DESKTOP, _bs._hwnd, (LPPOINT)&rc, 2);
|
|
cyBefore = rc.bottom - rc.top;
|
|
|
|
c = y - _yCapture;
|
|
rc.bottom = y;
|
|
|
|
// was there enough change?
|
|
if (ABS(c) <= cyHalfRow)
|
|
return;
|
|
|
|
if ((cRows == 1) || _fCompressed)
|
|
{
|
|
if (c < -cyHalfRow)
|
|
fChanged = _CompressBands(TRUE, 0, FALSE);
|
|
else
|
|
fChanged = _CompressBands(FALSE, _uiTBTextRows, FALSE);
|
|
|
|
}
|
|
|
|
if (!fChanged)
|
|
{
|
|
// if the compressing bands didn't change anything, try to fit it to size
|
|
fChanged = SendMessage(_bs._hwnd, RB_SIZETORECT, 0, (LPARAM)&rc);
|
|
}
|
|
|
|
|
|
// TODO: There is a drawing glitch when you resize from 3 bars (No Text) to 3 bars
|
|
// with text. The _yCapture gets set to a value greater than y. So on the
|
|
// next MOUSEMOVE it figures that the user moved up and switches from 3 bars with text
|
|
// to 2 bars with text.
|
|
if (fChanged)
|
|
{
|
|
_UpdateBrandSize();
|
|
GetWindowRect(_bs._hwnd, &rc);
|
|
_yCapture += (rc.bottom - rc.top) - cyBefore;
|
|
_fDirty = TRUE; //Since the band layout changed, set the dirty bit ON.
|
|
if (_ptbsitect)
|
|
_ptbsitect->Exec(&CGID_ShellBrowser, FCIDM_PERSISTTOOLBAR, 0, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
void CInternetToolbar::_ShowVisible(DWORD dwVisibleBands, BOOL fPersist)
|
|
{
|
|
// PERF (scotth): is this even necessary now that we have a
|
|
// menu band always showing?
|
|
BOOL fShowInitial = (! (_nVisibleBands & ~VBF_BRAND));
|
|
|
|
_UpdateToolbarDisplay(UTD_VISIBLE, dwVisibleBands, _fCompressed, fPersist);
|
|
|
|
if (fShowInitial)
|
|
_pdie->put_ToolBar(TRUE);
|
|
}
|
|
|
|
|
|
HRESULT CInternetToolbar::_UpdateToolbarDisplay(DWORD dwFlags, UINT uVisibleBands, BOOL fNoText, BOOL fPersist)
|
|
{
|
|
_fDirty = TRUE; //Since we are making changes, set the dirty bit!
|
|
|
|
//Update the back bitmap
|
|
_SetBackground();
|
|
|
|
//Show the bands.
|
|
if(dwFlags & UTD_VISIBLE)
|
|
_ShowBands(uVisibleBands);
|
|
|
|
//Show/Hide the text.
|
|
if(dwFlags & UTD_TEXTLABEL)
|
|
_CompressBands(fNoText, _uiTBTextRows, TRUE);
|
|
|
|
_fDirty = TRUE; //Since we are making changes, set the dirty bit!
|
|
if (!_fTheater && fPersist && _ptbsitect)
|
|
_ptbsitect->Exec(&CGID_ShellBrowser, FCIDM_PERSISTTOOLBAR, 0, NULL, NULL);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CInternetToolbar::_UpdateBrandSize()
|
|
{
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_BRAND);
|
|
if (pbid && ((_nVisibleBands & (VBF_TOOLS | VBF_BRAND)) == (VBF_TOOLS | VBF_BRAND)))
|
|
{
|
|
BOOL fMinAlways = _fCompressed;
|
|
|
|
if (!fMinAlways)
|
|
{
|
|
INT_PTR iTools = BandIDtoIndex(_bs._hwnd, CBIDX_TOOLS);
|
|
INT_PTR iBrand = BandIDtoIndex(_bs._hwnd, CBIDX_BRAND);
|
|
|
|
if (iBrand < iTools && !_fTheater)
|
|
fMinAlways = TRUE;
|
|
}
|
|
|
|
VARIANTARG v = {0};
|
|
v.vt = VT_I4;
|
|
v.lVal = fMinAlways;
|
|
IUnknown_Exec(pbid->pdb, &CGID_PrivCITCommands, CITIDM_BRANDSIZE, 0, &v, NULL);
|
|
}
|
|
}
|
|
|
|
LRESULT CALLBACK CInternetToolbar::SizableWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CInternetToolbar* pitbar = (CInternetToolbar*)GetWindowPtr0(hwnd); // GetWindowLong(hwnd, 0)
|
|
|
|
switch(uMsg)
|
|
{
|
|
case WM_SETCURSOR:
|
|
{
|
|
if (pitbar->_fLockedToolbar)
|
|
{
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
return TRUE;
|
|
}
|
|
|
|
if ((HWND)wParam == hwnd && LOWORD(lParam) == HTCLIENT &&
|
|
!SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0))
|
|
{
|
|
SetCursor(LoadCursor(NULL, IDC_SIZENS));
|
|
return TRUE;
|
|
}
|
|
goto DoDefault;
|
|
}
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
case WM_WININICHANGE:
|
|
if (FALSE == pitbar->_fDestroyed)
|
|
{
|
|
DWORD dwSection = SHIsExplorerIniChange(wParam, lParam);
|
|
|
|
BOOL fRebuild = (uMsg == WM_SYSCOLORCHANGE) ||
|
|
(dwSection == EICH_KWINEXPLSMICO) ||
|
|
(wParam == SPI_SETNONCLIENTMETRICS);
|
|
|
|
if (fRebuild)
|
|
{
|
|
pitbar->_InitForScreenSize();
|
|
ITBar_LoadToolbarGlyphs(pitbar->_btb._hwnd);
|
|
pitbar->_ReloadBitmapDSA();
|
|
pitbar->_SetSearchStuff();
|
|
pitbar->_ReloadButtons();
|
|
#ifdef EDIT_HACK
|
|
if (uMsg == WM_SYSCOLORCHANGE)
|
|
{
|
|
pitbar->_RefreshEditGlyph();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef EDIT_HACK
|
|
if (dwSection == EICH_KINET)
|
|
{
|
|
pitbar->_aEditVerb.InitDefaultEditor();
|
|
pitbar->_UpdateEditButton();
|
|
}
|
|
#endif
|
|
|
|
SendMessage(pitbar->_bs._hwnd, uMsg, wParam, lParam);
|
|
pitbar->_SendToToolband(HWND_BROADCAST, uMsg, wParam, lParam, NULL);
|
|
|
|
if (fRebuild)
|
|
{
|
|
pitbar->_SetBackground();
|
|
InvalidateRect(pitbar->_bs._hwnd, NULL, TRUE);
|
|
pitbar->_bs._SetMinDimensions();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
// RelayToToolTips(prb->hwndToolTips, hwnd, wMsg, wParam, lParam);
|
|
// Don't allow toolbar resizing in theater mode
|
|
if (!pitbar->_fTheater &&
|
|
!SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0) &&
|
|
(!pitbar->_fLockedToolbar))
|
|
{
|
|
pitbar->_xCapture = GET_X_LPARAM(lParam);
|
|
pitbar->_yCapture = GET_Y_LPARAM(lParam);
|
|
SetCapture(hwnd);
|
|
}
|
|
break;
|
|
|
|
case WM_MOUSEMOVE:
|
|
// RelayToToolTips(prb->hwndToolTips, hwnd, wMsg, wParam, lParam);
|
|
|
|
if (pitbar->_yCapture != -1)
|
|
{
|
|
if (hwnd != GetCapture())
|
|
pitbar->_yCapture = -1;
|
|
else
|
|
pitbar->_TrackSliding(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
|
}
|
|
else if (pitbar->_fRebarDragging)
|
|
{
|
|
RECT rc;
|
|
POINT pt;
|
|
GetClientRect(pitbar->_bs._hwnd, &rc);
|
|
GetCursorPos(&pt);
|
|
MapWindowPoints(HWND_DESKTOP, pitbar->_bs._hwnd, &pt, 1);
|
|
rc.bottom /= 2;
|
|
if (pt.y > rc.bottom)
|
|
pt.y = rc.bottom;
|
|
SendMessage(pitbar->_bs._hwnd, RB_DRAGMOVE, 0, MAKELPARAM(pt.x, pt.y));
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
case WM_RBUTTONUP:
|
|
// RelayToToolTips(prb->hwndToolTips, hwnd, wMsg, wParam, lParam);
|
|
|
|
pitbar->_yCapture = -1;
|
|
if (pitbar->_fRebarDragging)
|
|
{
|
|
pitbar->_fRebarDragging = FALSE;
|
|
SendMessage(pitbar->_bs._hwnd, RB_ENDDRAG, 0, 0);
|
|
}
|
|
if (GetCapture() == hwnd)
|
|
ReleaseCapture();
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
pitbar->_bs.OnWinEvent(pitbar->_hwnd, uMsg, wParam, lParam, NULL);
|
|
break;
|
|
|
|
case WM_VKEYTOITEM:
|
|
case WM_CHARTOITEM:
|
|
// We must swallow these messages to avoid infinit SendMessage
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
// We must swallow these messages to avoid infinit SendMessage
|
|
return pitbar->_OnNotify((LPNMHDR)lParam);
|
|
|
|
case WM_NOTIFYFORMAT:
|
|
if (NF_QUERY == lParam)
|
|
return (DLL_IS_UNICODE ? NFR_UNICODE : NFR_ANSI);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
pitbar->_OnCommand(wParam, lParam);
|
|
break;
|
|
|
|
case WM_ERASEBKGND:
|
|
{
|
|
HDC hdc = (HDC)wParam;
|
|
RECT rc;
|
|
GetClientRect(hwnd, &rc);
|
|
SHFillRectClr(hdc, &rc, (pitbar->_fTheater) ? RGB(0,0,0) : GetSysColor(COLOR_3DFACE));
|
|
break;
|
|
}
|
|
|
|
case WM_PALETTECHANGED:
|
|
//
|
|
// PERF: we could optimize this by realizing and checking the
|
|
// return value
|
|
//
|
|
// for now we will just invalidate ourselves and all children...
|
|
//
|
|
RedrawWindow(hwnd, NULL, NULL,
|
|
RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
|
|
break;
|
|
|
|
case WM_MEASUREITEM:
|
|
{
|
|
PMEASUREITEMSTRUCT pmis;
|
|
|
|
ASSERT(NULL != lParam);
|
|
pmis = (PMEASUREITEMSTRUCT)lParam;
|
|
|
|
switch (pmis->itemID)
|
|
{
|
|
case FCIDM_VBBHISTORYBAND:
|
|
ASSERT(0 == wParam);
|
|
{
|
|
PULONG_PTR pData = (PULONG_PTR)pmis->itemData;
|
|
ASSERT(NULL != pData);
|
|
MeasureMenuItem(pmis, (PCTSTR)pData[0]);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
goto DoDefault;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_DRAWITEM:
|
|
{
|
|
PDRAWITEMSTRUCT pdis;
|
|
|
|
ASSERT(NULL != lParam);
|
|
pdis = (PDRAWITEMSTRUCT)lParam;
|
|
|
|
switch (pdis->itemID)
|
|
{
|
|
case FCIDM_VBBHISTORYBAND:
|
|
ASSERT(0 == wParam);
|
|
{
|
|
PULONG_PTR pData = (PULONG_PTR)pdis->itemData;
|
|
ASSERT(NULL != pData);
|
|
DrawMenuItem(pdis, (PCTSTR)pData[0], (UINT) pData[1]);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
goto DoDefault;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_MENUCHAR:
|
|
if (MF_POPUP == HIWORD(wParam))
|
|
{
|
|
MENUITEMINFO mii = { 0 };
|
|
|
|
mii.cbSize = sizeof(mii);
|
|
mii.fMask = MIIM_DATA | MIIM_TYPE;
|
|
GetMenuItemInfo((HMENU)lParam, FCIDM_VBBHISTORYBAND, FALSE, &mii);
|
|
|
|
if (TEXT('h') == LOWORD(wParam) || TEXT('H') == LOWORD(wParam))
|
|
{
|
|
return MAKELRESULT(FCIDM_VBBHISTORYBAND, MNC_EXECUTE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
switch (wParam)
|
|
{
|
|
case IDT_UPDATETOOLBAR:
|
|
pitbar->_fUpdateToolbarTimer = FALSE;
|
|
KillTimer(hwnd, wParam);
|
|
if (pitbar->_fNeedUpdateToolbar)
|
|
pitbar->_UpdateToolbarNow();
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
pitbar->_Unadvise(); // remove ref-loop with _pdie
|
|
TraceMsg(DM_TBREF, "CInternetToolbar::SizableWndProc() - Called RemoveProp. Called Release new _cRef=%d", pitbar->_cRef);
|
|
goto DoDefault;
|
|
|
|
DoDefault:
|
|
default:
|
|
return(DefWindowProcWrap(hwnd, uMsg, wParam, lParam));
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
|
|
|
|
HRESULT CInternetToolbar::ResizeBorderDW(LPCRECT prcBorder,
|
|
IUnknown* punkToolbarSite,
|
|
BOOL fReserved)
|
|
{
|
|
TraceMsg(DM_LAYOUT, "CITB::ResizeBorderDW called (_fShow==%d)", _fShow);
|
|
HRESULT hres = S_OK;
|
|
|
|
ASSERT(_ptbsite);
|
|
if (_ptbsite)
|
|
{
|
|
RECT rcRequest = { 0, 0, 0, 0 };
|
|
|
|
if (_fShow)
|
|
{
|
|
RECT rcRebar, rcBorder;
|
|
int cx,cy;
|
|
|
|
GetWindowRect(_bs._hwnd, &rcRebar);
|
|
cx = rcRebar.right - rcRebar.left;
|
|
cy = rcRebar.bottom - rcRebar.top;
|
|
|
|
int iExtra = 3;
|
|
if (_fTheater)
|
|
{
|
|
// 1 for the 1 pixel border on the bottom
|
|
iExtra = 1;
|
|
}
|
|
else if (_fLockedToolbar)
|
|
{
|
|
iExtra = 0;
|
|
}
|
|
|
|
TraceMsg(DM_LAYOUT, "CITB::ResizeBorderDW cy = %d", cy);
|
|
|
|
if (!prcBorder)
|
|
{
|
|
_ptbsite->GetBorderDW(SAFECAST(this, IDockingWindow*), &rcBorder);
|
|
prcBorder = &rcBorder;
|
|
}
|
|
|
|
cx = prcBorder->right - prcBorder->left;
|
|
|
|
|
|
SetWindowPos(_bs._hwnd, NULL, 0, 0,
|
|
cx, cy, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
|
|
|
|
GetWindowRect(_bs._hwnd, &rcRebar);
|
|
|
|
|
|
rcRequest.top = rcRebar.bottom - rcRebar.top + iExtra;
|
|
SetWindowPos(_hwnd, NULL, prcBorder->left, prcBorder->top,
|
|
rcRebar.right - rcRebar.left, rcRequest.top, SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
|
|
if (_fTheater && _fAutoHide)
|
|
{
|
|
// if we're in theater mode, then we should request no space
|
|
rcRequest.left = rcRequest.top = 0;
|
|
}
|
|
|
|
TraceMsg(DM_LAYOUT, "CITB::ResizeBorderDW calling RequstBS with %d,%d,%d,%d",
|
|
rcRequest.left, rcRequest.top, rcRequest.right, rcRequest.bottom);
|
|
_ptbsite->RequestBorderSpaceDW(SAFECAST(this, IDockingWindow*), &rcRequest);
|
|
|
|
TraceMsg(DM_LAYOUT, "CITB::ResizeBorderDW calling SetBS with %d,%d,%d,%d",
|
|
rcRequest.left, rcRequest.top, rcRequest.right, rcRequest.bottom);
|
|
_ptbsite->SetBorderSpaceDW(SAFECAST(this, IDockingWindow*), &rcRequest);
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::QueryStatus(const GUID *pguidCmdGroup,
|
|
ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
|
|
{
|
|
HRESULT hr = OLECMDERR_E_UNKNOWNGROUP;
|
|
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
|
|
if (pbid && pbid->pdb)
|
|
{
|
|
IOleCommandTarget *poct;
|
|
if (SUCCEEDED(pbid->pdb->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &poct))))
|
|
{
|
|
hr = poct->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
|
|
poct->Release();
|
|
}
|
|
}
|
|
|
|
if (pguidCmdGroup && IsEqualGUID(CGID_PrivCITCommands, *pguidCmdGroup))
|
|
{
|
|
hr = S_OK;
|
|
for (ULONG i = 0 ; i < cCmds; i++)
|
|
{
|
|
rgCmds[i].cmdf = 0;
|
|
switch (rgCmds[i].cmdID)
|
|
{
|
|
case CITIDM_VIEWTOOLS:
|
|
if (_nVisibleBands & VBF_TOOLS)
|
|
rgCmds[i].cmdf = OLECMDF_ENABLED;
|
|
break;
|
|
|
|
case CITIDM_VIEWMENU:
|
|
if (_nVisibleBands & VBF_MENU)
|
|
rgCmds[i].cmdf = OLECMDF_ENABLED;
|
|
break;
|
|
|
|
case CITIDM_VIEWTOOLBARCUSTOMIZE:
|
|
if (_btb._fCustomize)
|
|
rgCmds[i].cmdf = OLECMDF_ENABLED;
|
|
break;
|
|
|
|
case CITIDM_VIEWAUTOHIDE:
|
|
if (_fAutoHide)
|
|
rgCmds[i].cmdf = OLECMDF_ENABLED;
|
|
break;
|
|
|
|
case CITIDM_VIEWLOCKTOOLBAR:
|
|
if (_fLockedToolbar)
|
|
rgCmds[i].cmdf = OLECMDF_ENABLED;
|
|
break;
|
|
|
|
case CITIDM_VIEWADDRESS:
|
|
if (_nVisibleBands & VBF_ADDRESS)
|
|
rgCmds[i].cmdf = OLECMDF_ENABLED;
|
|
break;
|
|
|
|
case CITIDM_VIEWLINKS:
|
|
if (_nVisibleBands & VBF_LINKS)
|
|
rgCmds[i].cmdf = OLECMDF_ENABLED;
|
|
break;
|
|
|
|
case CITIDM_TEXTLABELS:
|
|
if (!_fCompressed)
|
|
rgCmds[i].cmdf = OLECMDF_ENABLED;
|
|
break;
|
|
|
|
case CITIDM_EDITPAGE:
|
|
if (_fEditEnabled)
|
|
rgCmds[i].cmdf = OLECMDF_ENABLED;
|
|
#ifdef EDIT_HACK
|
|
// The tooltip text is also used for the menu
|
|
if (pcmdtext)
|
|
{
|
|
TCHAR szBuf[MAX_PATH];
|
|
if ((pcmdtext->cmdtextf == OLECMDTEXTF_NAME) &&
|
|
_aEditVerb.GetMenuText(szBuf, ARRAYSIZE(szBuf)))
|
|
{
|
|
SHTCharToUnicode(szBuf, pcmdtext->rgwz, pcmdtext->cwBuf);
|
|
pcmdtext->cwActual = lstrlenW(pcmdtext->rgwz) + 1;
|
|
}
|
|
else
|
|
{
|
|
pcmdtext->cwActual = 0;
|
|
}
|
|
}
|
|
#endif
|
|
break;
|
|
default:
|
|
if (InRange( rgCmds[i].cmdID, CITIDM_VIEWEXTERNALBAND_FIRST, CITIDM_VIEWEXTERNALBAND_LAST))
|
|
{
|
|
int iBand = rgCmds[i].cmdID - CITIDM_VIEWEXTERNALBAND_FIRST;
|
|
if (!IsEqualCLSID( _rgebi[iBand].clsid, GUID_NULL ))
|
|
{
|
|
rgCmds[i].cmdf |= OLECMDF_SUPPORTED;
|
|
if (_nVisibleBands & EXTERNALBAND_VBF_BIT( iBand ))
|
|
{
|
|
rgCmds[i].cmdf |= OLECMDF_ENABLED;
|
|
}
|
|
if (pcmdtext)
|
|
{
|
|
pcmdtext->rgwz[0] = TEXT('\0');
|
|
switch (pcmdtext->cmdtextf)
|
|
{
|
|
case OLECMDTEXTF_NAME:
|
|
if (_rgebi[iBand].pwszName)
|
|
Str_GetPtrW(_rgebi[iBand].pwszName, pcmdtext->rgwz, pcmdtext->cwBuf );
|
|
break;
|
|
|
|
case OLECMDTEXTF_STATUS:
|
|
if (_rgebi[iBand].pwszHelp)
|
|
Str_GetPtrW(_rgebi[iBand].pwszHelp, pcmdtext->rgwz, pcmdtext->cwBuf );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
pcmdtext->cwActual = lstrlen( pcmdtext->rgwz );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
void CInternetToolbar::_RestoreSaveStruct(COOLBARSAVE* pcs)
|
|
{
|
|
REBARBANDINFO rbbi;
|
|
rbbi.cbSize = sizeof(REBARBANDINFO);
|
|
int i;
|
|
|
|
_fAutoHide = pcs->fAutoHide;
|
|
_ShowVisible(pcs->uiVisible, FALSE);
|
|
|
|
BOOL fAllowRetry = TRUE;
|
|
BOOL fNeedRetry = FALSE;
|
|
INT_PTR fRedraw = SendMessage(_bs._hwnd, WM_SETREDRAW, FALSE, 0);
|
|
Retry:
|
|
for (i = 0; i < CBANDSMAX; i++)
|
|
{
|
|
INT_PTR iIndex = SendMessage(_bs._hwnd, RB_IDTOINDEX, pcs->bs[i].wID, 0);
|
|
if (iIndex != -1)
|
|
{
|
|
SendMessage(_bs._hwnd, RB_MOVEBAND, iIndex, i);
|
|
rbbi.fMask = RBBIM_STYLE;
|
|
if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
|
|
{
|
|
rbbi.fMask = RBBIM_SIZE | RBBIM_STYLE;
|
|
rbbi.cx = pcs->bs[i].cx;
|
|
rbbi.fStyle = pcs->bs[i].fStyle;
|
|
SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM) &rbbi);
|
|
}
|
|
|
|
// the SetBandInfo could have potentially caused items to shift around
|
|
// verify that this didn't happen.
|
|
iIndex = SendMessage(_bs._hwnd, RB_IDTOINDEX, pcs->bs[i].wID, 0);
|
|
if (iIndex != i)
|
|
{
|
|
fNeedRetry = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fAllowRetry && fNeedRetry)
|
|
{
|
|
fAllowRetry = FALSE;
|
|
goto Retry;
|
|
}
|
|
|
|
_CSHSetStatusBar(pcs->fStatusBar);
|
|
_UpdateToolsStyle(pcs->fList);
|
|
|
|
RECT rc;
|
|
GetWindowRect(_bs._hwnd, &rc);
|
|
SetWindowPos(_bs._hwnd, NULL, 0,0, RECTWIDTH(rc), pcs->cyRebar, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
SendMessage(_bs._hwnd, WM_SETREDRAW, fRedraw, 0);
|
|
}
|
|
|
|
void CInternetToolbar::_CSHSetStatusBar(BOOL fOn)
|
|
{
|
|
VARIANTARG v = { 0 };
|
|
v.vt = VT_I4;
|
|
v.lVal = fOn;
|
|
IUnknown_Exec(_ptbsite, &CGID_ShellBrowser, FCIDM_SETSTATUSBAR,
|
|
0, &v, NULL);
|
|
}
|
|
|
|
void CInternetToolbar::_TheaterModeLayout(BOOL fEnter)
|
|
{
|
|
static const struct {
|
|
int id;
|
|
int cx;
|
|
} c_layout[] =
|
|
{
|
|
{ CBIDX_TOOLS, 400 },
|
|
{ CBIDX_MENU, 200 },
|
|
{ CBIDX_ADDRESS, 300 },
|
|
{ CBIDX_LINKS, 40 }
|
|
};
|
|
|
|
REBARBANDINFO rbbi;
|
|
rbbi.cbSize = sizeof(REBARBANDINFO);
|
|
|
|
BOOL_PTR fRedraw = SendMessage(_bs._hwnd, WM_SETREDRAW, FALSE, 0);
|
|
SHSetWindowBits(_bs._hwnd, GWL_STYLE, RBS_AUTOSIZE, 0);
|
|
if (fEnter)
|
|
{
|
|
_BuildSaveStruct(&_cs);
|
|
|
|
// turn off text labels
|
|
COOLBARSAVE cs;
|
|
DWORD dwType, cbSize = sizeof(COOLBARSAVE);
|
|
if (SHRegGetUSValue(c_szRegKeyCoolbar, c_szValueTheater, &dwType, (void*)&cs, &cbSize, FALSE, NULL, 0) == ERROR_SUCCESS &&
|
|
cs.cbVer == CBS_VERSION)
|
|
{
|
|
_RestoreSaveStruct(&cs);
|
|
_UpdateToolbarDisplay(UTD_TEXTLABEL, 0, TRUE, TRUE);
|
|
}
|
|
else
|
|
{
|
|
_UpdateToolbarDisplay(UTD_TEXTLABEL, 0, TRUE, TRUE);
|
|
_ShowVisible(VBF_TOOLS | VBF_BRAND, FALSE); // only show tools band by default
|
|
RECT rc = { 0, 0, GetSystemMetrics(SM_CXSCREEN), 20 }; // something arbitrarily small vertically
|
|
SendMessage(_bs._hwnd, RB_SIZETORECT, 0, (LPARAM)&rc);
|
|
|
|
int cBands = (int) SendMessage(_bs._hwnd, RB_GETBANDCOUNT, 0, 0L);
|
|
int i;
|
|
// strip off all blanks
|
|
rbbi.fMask = RBBIM_STYLE;
|
|
for (i = 0; i < cBands; i++)
|
|
{
|
|
if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
|
|
{
|
|
rbbi.fStyle &= ~RBBS_BREAK;
|
|
SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM) &rbbi);
|
|
}
|
|
}
|
|
|
|
// then move into the proper order and size
|
|
for (i = 0; i < ARRAYSIZE(c_layout); i++)
|
|
{
|
|
INT_PTR iIndex = SendMessage(_bs._hwnd, RB_IDTOINDEX, c_layout[i].id, 0);
|
|
if (iIndex != -1)
|
|
{
|
|
SendMessage(_bs._hwnd, RB_MOVEBAND, iIndex, i);
|
|
|
|
rbbi.fMask = RBBIM_SIZE;
|
|
rbbi.cx = c_layout[i].cx;
|
|
SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM) &rbbi);
|
|
}
|
|
}
|
|
_CSHSetStatusBar(FALSE); // default value in theater mode
|
|
}
|
|
SHSetWindowBits(_bs._hwnd, GWL_STYLE, RBS_BANDBORDERS | WS_BORDER, RBS_BANDBORDERS);
|
|
}
|
|
else
|
|
{
|
|
COOLBARSAVE cs;
|
|
_BuildSaveStruct(&cs);
|
|
SHRegSetUSValue(c_szRegKeyCoolbar, c_szValueTheater, REG_BINARY,
|
|
(void*)&cs, sizeof(COOLBARSAVE), SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
|
|
_RestoreSaveStruct(&_cs);
|
|
_UpdateToolbarDisplay(UTD_TEXTLABEL, 0, _cs.fNoText, FALSE);
|
|
SHSetWindowBits(_bs._hwnd, GWL_STYLE, RBS_BANDBORDERS | WS_BORDER, RBS_BANDBORDERS | WS_BORDER);
|
|
}
|
|
|
|
_SetBackground();
|
|
SHSetWindowBits(_bs._hwnd, GWL_STYLE, RBS_AUTOSIZE, RBS_AUTOSIZE);
|
|
SendMessage(_bs._hwnd, WM_SETREDRAW, fRedraw, 0);
|
|
|
|
SetWindowPos(_bs._hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
|
|
}
|
|
|
|
HRESULT CInternetToolbar::_GetMinRowHeight()
|
|
{
|
|
UINT iHeight = 0;
|
|
int icBands = (int) SendMessage( _bs._hwnd, RB_GETBANDCOUNT, 0, 0 );
|
|
for (int i = 0; i < icBands; i++)
|
|
{
|
|
REBARBANDINFO rbbi;
|
|
rbbi.cbSize = sizeof(REBARBANDINFO);
|
|
rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_STYLE;
|
|
if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM)&rbbi))
|
|
{
|
|
// go until the end of the row
|
|
if (rbbi.fStyle & RBBS_BREAK)
|
|
break;
|
|
|
|
if (!(rbbi.fStyle & RBBS_HIDDEN))
|
|
{
|
|
if (rbbi.cyMinChild > iHeight)
|
|
iHeight = rbbi.cyMinChild;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ResultFromShort(iHeight);
|
|
}
|
|
|
|
BOOL IsBarRefreshable(IDeskBar* pdb)
|
|
{
|
|
ASSERT(pdb);
|
|
BOOL fIsRefreshable = TRUE;
|
|
VARIANT varClsid = {0};
|
|
|
|
if (SUCCEEDED(IUnknown_Exec(pdb, &CGID_DeskBarClient, DBCID_CLSIDOFBAR, 1, NULL, &varClsid)) && (varClsid.vt == VT_BSTR))
|
|
{
|
|
CLSID clsidBar;
|
|
|
|
//if the bar is hidden, it returns GUID_NULL, so don't refresh it
|
|
if ( GUIDFromString(varClsid.bstrVal, &clsidBar) &&
|
|
(IsEqualGUID(clsidBar, GUID_NULL)) )
|
|
{
|
|
fIsRefreshable = FALSE;
|
|
}
|
|
else
|
|
{
|
|
//APPHACK for office discussions band (and possibly others)
|
|
//CLSID\GUID\Instance
|
|
WCHAR wszKey[6+40+1+9];
|
|
DWORD dwValue, dwType=REG_DWORD, dwcbData = 4;
|
|
wnsprintf(wszKey, ARRAYSIZE(wszKey), L"CLSID\\%s\\Instance", varClsid.bstrVal);
|
|
|
|
if ( (SHGetValue(HKEY_CLASSES_ROOT, wszKey, L"DontRefresh", &dwType, &dwValue, &dwcbData) == ERROR_SUCCESS) &&
|
|
(dwValue != 0) )
|
|
{
|
|
fIsRefreshable = FALSE;
|
|
}
|
|
}
|
|
VariantClear(&varClsid);
|
|
}
|
|
return fIsRefreshable;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
|
|
DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
|
|
{
|
|
HRESULT hr = OLECMDERR_E_UNKNOWNGROUP; // assume failure
|
|
|
|
if (!pguidCmdGroup)
|
|
{
|
|
goto Lother;
|
|
}
|
|
else if (IsEqualGUID(CLSID_CommonButtons, *pguidCmdGroup))
|
|
{
|
|
if (pvarargOut)
|
|
{
|
|
ASSERT(pvarargOut && pvarargOut->vt == VT_I4);
|
|
UINT uiInternalCmdID = pvarargOut->lVal;
|
|
|
|
if (nCmdID == TBIDM_SEARCH && uiInternalCmdID == -1)
|
|
_btb._ConvertCmd(pguidCmdGroup, nCmdID, NULL, &uiInternalCmdID);
|
|
|
|
switch (nCmdID)
|
|
{
|
|
case TBIDM_BACK:
|
|
case TBIDM_FORWARD:
|
|
case TBIDM_STOPDOWNLOAD:
|
|
case TBIDM_REFRESH:
|
|
case TBIDM_HOME:
|
|
case TBIDM_SEARCH:
|
|
case TBIDM_FAVORITES:
|
|
case TBIDM_HISTORY:
|
|
case TBIDM_ALLFOLDERS:
|
|
case TBIDM_MEDIABAR:
|
|
if (!SendMessage(_btb._hwnd, TB_ISBUTTONENABLED, uiInternalCmdID, 0))
|
|
return S_OK;
|
|
break;
|
|
}
|
|
if (nCmdexecopt == OLECMDEXECOPT_PROMPTUSER)
|
|
{
|
|
// the user hit the drop down
|
|
if (_ptbsitect && pvarargIn && pvarargIn->vt == VT_INT_PTR)
|
|
{
|
|
// v.vt = VT_I4;
|
|
POINT pt;
|
|
RECT* prc = (RECT*)pvarargIn->byref;
|
|
pt.x = prc->left;
|
|
pt.y = prc->bottom;
|
|
|
|
switch (nCmdID)
|
|
{
|
|
case TBIDM_BACK:
|
|
_ShowBackForwardMenu(FALSE, pt, prc);
|
|
break;
|
|
|
|
case TBIDM_FORWARD:
|
|
_ShowBackForwardMenu(TRUE, pt, prc);
|
|
break;
|
|
}
|
|
// VariantClearLazy(&v);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
switch(nCmdID)
|
|
{
|
|
case TBIDM_PREVIOUSFOLDER:
|
|
_ptbsitect->Exec(&CGID_ShellBrowser, FCIDM_PREVIOUSFOLDER, 0, NULL, NULL);
|
|
break;
|
|
|
|
case TBIDM_CONNECT:
|
|
DoNetConnect(_hwnd);
|
|
break;
|
|
|
|
case TBIDM_DISCONNECT:
|
|
DoNetDisconnect(_hwnd);
|
|
break;
|
|
|
|
case TBIDM_BACK:
|
|
_pdie->GoBack();
|
|
break;
|
|
|
|
case TBIDM_FORWARD:
|
|
_pdie->GoForward();
|
|
break;
|
|
|
|
case TBIDM_HOME:
|
|
_pdie->GoHome();
|
|
break;
|
|
|
|
case TBIDM_SEARCH:
|
|
if (_ptbsitect)
|
|
{
|
|
VARIANTARG vaOut = {0};
|
|
VARIANTARG* pvaOut = NULL;
|
|
LPITEMIDLIST pidl = NULL;
|
|
|
|
// i'm leaving this not #ifdefed out because it is used by explorer bar
|
|
// persistance (reljai)
|
|
//_SetSearchStuff initializes _guidDefaultSearch, which may or may not have
|
|
// been called yet
|
|
if (IsEqualGUID(_guidDefaultSearch, GUID_NULL))
|
|
_SetSearchStuff();
|
|
|
|
// see if what the state of search pane is, so we can toggle it...
|
|
OLECMD rgcmds[] = {{ SBCMDID_SEARCHBAR, 0 },};
|
|
|
|
if (_ptbsitect)
|
|
_ptbsitect->QueryStatus(&CGID_Explorer, ARRAYSIZE(rgcmds), rgcmds, NULL);
|
|
// not pressed, then show the pane
|
|
if (!(rgcmds[0].cmdf & OLECMDF_LATCHED))
|
|
{
|
|
WCHAR wszUrl[MAX_URL_STRING];
|
|
|
|
if (_GetSearchUrl(wszUrl, ARRAYSIZE(wszUrl)))
|
|
{
|
|
CLSID clsid;
|
|
|
|
if (GUIDFromString(wszUrl, &clsid))
|
|
{
|
|
IContextMenu* pcm;
|
|
|
|
if (SUCCEEDED(SHCoCreateInstance(NULL, &clsid, NULL, IID_PPV_ARG(IContextMenu, &pcm))))
|
|
{
|
|
CMINVOKECOMMANDINFO ici = {0};
|
|
CHAR szGuid[GUIDSTR_MAX];
|
|
BOOL bSetSite = TRUE;
|
|
|
|
ici.cbSize = sizeof(ici);
|
|
ici.hwnd = _hwnd;
|
|
ici.lpVerb = (LPSTR)MAKEINTRESOURCE(0);
|
|
ici.nShow = SW_NORMAL;
|
|
SHStringFromGUIDA(_guidDefaultSearch, szGuid, ARRAYSIZE(szGuid));
|
|
ici.lpParameters = szGuid;
|
|
|
|
// in case of rooted browser we need to open the search in the new window
|
|
// 'coz otherwise the pane opens in the same window and user starts search
|
|
// and browseobject (or someone) detects the rooted case and launches new
|
|
// browser for our search results view (which is blank because it cannot do
|
|
// search by itself and also there is not search pane) (reljai)
|
|
if (_pbs2)
|
|
{
|
|
LPITEMIDLIST pidl;
|
|
|
|
if (SUCCEEDED(_pbs2->GetPidl(&pidl)))
|
|
{
|
|
bSetSite = !ILIsRooted(pidl);
|
|
ILFree(pidl);
|
|
}
|
|
}
|
|
// if there is no site, InvokeCommand bellow will launch new browser w/ the
|
|
// search pane open
|
|
if (bSetSite)
|
|
IUnknown_SetSite(pcm, _psp);
|
|
hr = pcm->InvokeCommand(&ici);
|
|
if (bSetSite)
|
|
IUnknown_SetSite(pcm, NULL);
|
|
pcm->Release();
|
|
}
|
|
break;
|
|
}
|
|
//_guidCurrentSearch = _guidDefaultSearch;//done on set state
|
|
IECreateFromPathW(wszUrl, &pidl);
|
|
// convert pidl into VARIANT
|
|
// way to pass the pidl, so...
|
|
InitVariantFromIDList(&vaOut, pidl);
|
|
pvaOut = &vaOut;
|
|
}
|
|
}
|
|
|
|
hr = _ptbsitect->Exec(&CGID_Explorer, SBCMDID_SEARCHBAR, OLECMDEXECOPT_DONTPROMPTUSER, NULL, pvaOut); // vaIn:NULL means toggle
|
|
ASSERT(SUCCEEDED(hr));
|
|
if (pvaOut)
|
|
VariantClear(pvaOut);
|
|
ILFree(pidl);
|
|
}
|
|
else
|
|
{
|
|
TraceMsg(DM_ERROR, "CITBar::Exec: no IOleCommandTarget!");
|
|
}
|
|
break;
|
|
|
|
case TBIDM_FAVORITES:
|
|
case TBIDM_HISTORY:
|
|
case TBIDM_ALLFOLDERS:
|
|
case TBIDM_MEDIABAR:
|
|
if (_ptbsitect)
|
|
{
|
|
static const int tbtab[] = {
|
|
TBIDM_FAVORITES , TBIDM_HISTORY , TBIDM_ALLFOLDERS , TBIDM_MEDIABAR ,
|
|
};
|
|
static const int cttab[] = {
|
|
SBCMDID_FAVORITESBAR, SBCMDID_HISTORYBAR, SBCMDID_EXPLORERBAR, SBCMDID_MEDIABAR,
|
|
};
|
|
HRESULT hres;
|
|
int idCT;
|
|
|
|
idCT = SHSearchMapInt(tbtab, cttab, ARRAYSIZE(tbtab), nCmdID);
|
|
hres = _ptbsitect->Exec(&CGID_Explorer, idCT, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL); // vaIn:NULL means toggle
|
|
ASSERT(SUCCEEDED(hres));
|
|
}
|
|
else
|
|
{
|
|
TraceMsg(DM_ERROR, "CITBar::Exec: no IOleCommandTarget!");
|
|
}
|
|
break;
|
|
|
|
case TBIDM_THEATER:
|
|
{
|
|
VARIANT_BOOL b;
|
|
if (SUCCEEDED(_pdie->get_TheaterMode(&b)))
|
|
_pdie->put_TheaterMode( b == VARIANT_TRUE ? VARIANT_FALSE : VARIANT_TRUE);
|
|
break;
|
|
}
|
|
|
|
case TBIDM_STOPDOWNLOAD:
|
|
if (_fTransitionToHTML)
|
|
{
|
|
UINT uiState;
|
|
_fTransitionToHTML = FALSE;
|
|
if (SUCCEEDED(GetState(&CLSID_CommonButtons, TBIDM_STOPDOWNLOAD, &uiState)))
|
|
{
|
|
uiState |= TBSTATE_HIDDEN;
|
|
SetState(&CLSID_CommonButtons, TBIDM_STOPDOWNLOAD, uiState);
|
|
}
|
|
SendMessage(_hwndAddressBand, CB_SETEDITSEL, NULL, (LPARAM)MAKELONG(-1,0));
|
|
}
|
|
_pdie->Stop();
|
|
break;
|
|
|
|
case TBIDM_REFRESH:
|
|
{
|
|
VARIANT v = {0};
|
|
v.vt = VT_I4;
|
|
v.lVal = (GetAsyncKeyState(VK_CONTROL) < 0) ?
|
|
OLECMDIDF_REFRESH_COMPLETELY|OLECMDIDF_REFRESH_PROMPTIFOFFLINE :
|
|
OLECMDIDF_REFRESH_NO_CACHE|OLECMDIDF_REFRESH_PROMPTIFOFFLINE;
|
|
_pdie->Refresh2(&v);
|
|
|
|
if (_hwndAddressBand)
|
|
{
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
|
|
if (pbid && pbid->pdb)
|
|
{
|
|
IAddressBand *pab = NULL;
|
|
if (SUCCEEDED(pbid->pdb->QueryInterface(IID_PPV_ARG(IAddressBand, &pab))))
|
|
{
|
|
VARIANTARG varType = {0};
|
|
varType.vt = VT_I4;
|
|
varType.lVal = OLECMD_REFRESH_TOPMOST;
|
|
pab->Refresh(&varType);
|
|
pab->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
// pass this to vert and horz bars
|
|
IDockingWindowFrame *psb;
|
|
if (_psp && SUCCEEDED(_psp->QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IDockingWindowFrame, &psb))))
|
|
{
|
|
IDeskBar* pdb;
|
|
|
|
if (SUCCEEDED(psb->FindToolbar(INFOBAR_TBNAME, IID_PPV_ARG(IDeskBar, &pdb))) && pdb &&
|
|
IsBarRefreshable(pdb))
|
|
{
|
|
IUnknown_Exec(pdb, NULL, OLECMDID_REFRESH, OLECMDIDF_REFRESH_NORMAL|OLECMDIDF_REFRESH_PROMPTIFOFFLINE, NULL, NULL);
|
|
pdb->Release();
|
|
}
|
|
if (SUCCEEDED(psb->FindToolbar(COMMBAR_TBNAME, IID_PPV_ARG(IDeskBar, &pdb))) && pdb &&
|
|
IsBarRefreshable(pdb))
|
|
{
|
|
IUnknown_Exec(pdb, NULL, OLECMDID_REFRESH, OLECMDIDF_REFRESH_NORMAL|OLECMDIDF_REFRESH_PROMPTIFOFFLINE, NULL, NULL);
|
|
pdb->Release();
|
|
}
|
|
psb->Release();
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (IsEqualGUID(IID_IExplorerToolbar, *pguidCmdGroup))
|
|
{
|
|
switch (nCmdID)
|
|
{
|
|
case ETCMDID_GETBUTTONS:
|
|
{
|
|
if (_iButtons == -1)
|
|
{
|
|
// haven't initialized yet
|
|
_iButtons = ARRAYSIZE(c_tbExplorer);
|
|
memcpy(_tbExplorer, c_tbExplorer, sizeof(TBBUTTON) * ARRAYSIZE(c_tbExplorer));
|
|
|
|
if (IS_BIDI_LOCALIZED_SYSTEM())
|
|
{
|
|
if (!SHUseClassicToolbarGlyphs())
|
|
{
|
|
_tbExplorer[0].iBitmap = 1;
|
|
_tbExplorer[1].iBitmap = 0;
|
|
}
|
|
}
|
|
|
|
if (GetUIVersion() < 5)
|
|
{
|
|
// we don't want up button and network drive buttons available
|
|
// on < nt5 shell (by trident pm design)
|
|
|
|
// no customization in shell view on < nt5
|
|
ASSERT(!_fShellView);
|
|
|
|
ASSERT(c_tbExplorer[TBXID_PREVIOUSFOLDER].idCommand == TBIDM_PREVIOUSFOLDER);
|
|
_tbExplorer[TBXID_PREVIOUSFOLDER].fsState |= TBSTATE_HIDDEN;
|
|
|
|
ASSERT(c_tbExplorer[TBXID_CONNECT].idCommand == TBIDM_CONNECT);
|
|
_tbExplorer[TBXID_CONNECT].fsState |= TBSTATE_HIDDEN;
|
|
|
|
ASSERT(c_tbExplorer[TBXID_DISCONNECT].idCommand == TBIDM_DISCONNECT);
|
|
_tbExplorer[TBXID_DISCONNECT].fsState |= TBSTATE_HIDDEN;
|
|
|
|
ASSERT(c_tbExplorer[TBXID_ALLFOLDERS].idCommand == TBIDM_ALLFOLDERS);
|
|
if (!_FoldersButtonAvailable())
|
|
_tbExplorer[TBXID_ALLFOLDERS].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(c_tbExplorer[TBXID_SEARCH].idCommand == TBIDM_SEARCH);
|
|
if (_fShellView && SHRestricted(REST_NOSHELLSEARCHBUTTON))
|
|
_tbExplorer[TBXID_SEARCH].fsState |= TBSTATE_HIDDEN;
|
|
|
|
ASSERT(c_tbExplorer[TBXID_CONNECT].idCommand == TBIDM_CONNECT);
|
|
ASSERT(c_tbExplorer[TBXID_DISCONNECT].idCommand == TBIDM_DISCONNECT);
|
|
if (SHRestricted(REST_NONETCONNECTDISCONNECT))
|
|
{
|
|
_tbExplorer[TBXID_CONNECT].fsState |= TBSTATE_HIDDEN;
|
|
_tbExplorer[TBXID_DISCONNECT].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
}
|
|
ASSERT(_tbExplorer[TBXID_MEDIABAR].idCommand == TBIDM_MEDIABAR);
|
|
if (_fShellView || SHRestricted2W(REST_No_LaunchMediaBar, NULL, 0) || !CMediaBarUtil::IsWMP7OrGreaterCapable())
|
|
{
|
|
_tbExplorer[TBXID_MEDIABAR].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
|
|
ASSERT(_tbExplorer[TBXID_PREVIOUSFOLDER].idCommand == TBIDM_PREVIOUSFOLDER);
|
|
if (!_fShellView)
|
|
{
|
|
_tbExplorer[TBXID_PREVIOUSFOLDER].fsState |= TBSTATE_HIDDEN;
|
|
}
|
|
|
|
_iButtons = RemoveHiddenButtons(_tbExplorer, ARRAYSIZE(_tbExplorer));
|
|
}
|
|
|
|
pvarargOut->vt = VT_BYREF;
|
|
pvarargOut->byref = (void*)_tbExplorer;
|
|
*pvarargIn->plVal = _iButtons;
|
|
}
|
|
return S_OK;
|
|
}
|
|
}
|
|
else if (IsEqualGUID(CGID_PrivCITCommands, *pguidCmdGroup))
|
|
{
|
|
DWORD dw;
|
|
hr = S_OK;
|
|
switch (nCmdID)
|
|
{
|
|
case CITIDM_GETFOLDERSEARCHES:
|
|
{
|
|
hr = E_INVALIDARG;
|
|
|
|
if (pvarargOut)
|
|
{
|
|
IFolderSearches *pfs;
|
|
hr = _GetFolderSearches(&pfs);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
VariantClear(pvarargOut);
|
|
pvarargOut->vt = VT_UNKNOWN;
|
|
pvarargOut->punkVal = pfs;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CITIDM_SET_DIRTYBIT:
|
|
_fDirty = BOOLIFY(nCmdexecopt);
|
|
break;
|
|
|
|
case CITIDM_GETMINROWHEIGHT:
|
|
hr = _GetMinRowHeight();
|
|
break;
|
|
|
|
case CITIDM_VIEWTOOLBARCUSTOMIZE:
|
|
_OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWTOOLBARCUSTOMIZE, _hwnd, 0));
|
|
break;
|
|
|
|
case CITIDM_TEXTLABELS:
|
|
_OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWTEXTLABELS, _hwnd, 0));
|
|
break;
|
|
|
|
case CITIDM_EDITPAGE:
|
|
// FEATURE: temp code -- edit code moving to dochost.cpp
|
|
_btb.Exec(&CLSID_InternetButtons, DVIDM_EDITPAGE, 0, NULL, NULL);
|
|
break;
|
|
|
|
case CITIDM_ONINTERNET:
|
|
switch (nCmdexecopt)
|
|
{
|
|
case CITE_INTERNET:
|
|
_fInitialPidlIsWeb = TRUE;
|
|
_fShellView = !_fInitialPidlIsWeb;
|
|
break;
|
|
case CITE_SHELL:
|
|
_fInitialPidlIsWeb = FALSE;
|
|
_fShellView = !_fInitialPidlIsWeb;
|
|
break;
|
|
case CITE_QUERY:
|
|
return ResultFromScode(_fShellView ? CITE_SHELL : CITE_INTERNET);
|
|
break;
|
|
}
|
|
return ResultFromScode(_fInitialPidlIsWeb ? CITE_INTERNET : CITE_SHELL);
|
|
|
|
case CITIDM_VIEWTOOLS:
|
|
_OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWTOOLS, _hwnd, 0));
|
|
break;
|
|
|
|
case CITIDM_VIEWAUTOHIDE:
|
|
_OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWAUTOHIDE, _hwnd, 0));
|
|
break;
|
|
|
|
case CITIDM_VIEWLOCKTOOLBAR:
|
|
_OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWLOCKTOOLBAR, _hwnd, 0));
|
|
break;
|
|
|
|
case CITIDM_VIEWADDRESS:
|
|
_OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWADDRESS, _hwnd, 0));
|
|
break;
|
|
|
|
case CITIDM_VIEWLINKS:
|
|
_OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWLINKS, _hwnd, 0));
|
|
break;
|
|
|
|
case CITIDM_VIEWMENU:
|
|
_OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWMENU, _hwnd, 0));
|
|
break;
|
|
|
|
case CITIDM_SHOWTOOLS:
|
|
dw = VBF_TOOLS;
|
|
goto ShowABand;
|
|
|
|
case CITIDM_SHOWADDRESS:
|
|
dw = VBF_ADDRESS;
|
|
goto ShowABand;
|
|
|
|
case CITIDM_SHOWLINKS:
|
|
dw = VBF_LINKS;
|
|
goto ShowABand;
|
|
|
|
#ifdef UNIX
|
|
case CITIDM_SHOWBRAND:
|
|
dw = VBF_BRAND;
|
|
goto ShowABand;
|
|
#endif
|
|
|
|
case CITIDM_SHOWMENU:
|
|
dw = VBF_MENU;
|
|
ShowABand:
|
|
if (nCmdexecopt)
|
|
dw |= _nVisibleBands; // Set
|
|
else
|
|
dw = (_nVisibleBands & ~dw); // Clear
|
|
|
|
_ShowVisible(dw, TRUE);
|
|
_fUsingDefaultBands = FALSE;
|
|
break;
|
|
|
|
case CITIDM_DISABLESHOWMENU:
|
|
_fNoShowMenu = BOOLIFY(nCmdexecopt);
|
|
break;
|
|
|
|
case CITIDM_STATUSCHANGED:
|
|
_fDirty = TRUE;
|
|
if (_ptbsitect)
|
|
_ptbsitect->Exec(&CGID_ShellBrowser, FCIDM_PERSISTTOOLBAR, 0, NULL, NULL);
|
|
break;
|
|
|
|
case CITIDM_THEATER:
|
|
|
|
if (_fShow)
|
|
{
|
|
|
|
// IF YOU SEE HTIS ASSERT, TRY TO REMEMBER WHAT YOU DID AND CALL CHEE
|
|
ASSERT(_fTheater || _nVisibleBands & VBF_MENU);
|
|
|
|
switch (nCmdexecopt)
|
|
{
|
|
|
|
case THF_ON:
|
|
_fTheater = TRUE;
|
|
ResizeBorderDW(NULL, NULL, FALSE);
|
|
_TheaterModeLayout(TRUE);
|
|
// theater has its own brand, so needs to know whether we're in shell or web view so it can show the right brand
|
|
IUnknown_Exec(_ptbsite, &CGID_Theater, THID_ONINTERNET, _fShellView ? CITE_SHELL : CITE_INTERNET, NULL, NULL);
|
|
|
|
// pass back _fAutoHide
|
|
pvarargOut->vt = VT_I4;
|
|
pvarargOut->lVal = _fAutoHide;
|
|
|
|
goto notify_bands;
|
|
|
|
|
|
case THF_OFF:
|
|
_fTheater = FALSE;
|
|
ResizeBorderDW(NULL, NULL, FALSE);
|
|
_TheaterModeLayout(FALSE);
|
|
|
|
// position everything properly (needed after reparenting)
|
|
SendMessage(_hwnd, RB_PRIV_RESIZE, 0, 0);
|
|
goto notify_bands;
|
|
|
|
notify_bands:
|
|
{
|
|
int icBands = (int) SendMessage( _bs._hwnd, RB_GETBANDCOUNT, 0, 0 );
|
|
for (int i = 0; i < icBands; i++)
|
|
{
|
|
REBARBANDINFO rbbi;
|
|
rbbi.cbSize = sizeof(REBARBANDINFO);
|
|
rbbi.fMask = RBBIM_ID;
|
|
|
|
if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
|
|
{
|
|
LPBANDITEMDATA pbid = (LPBANDITEMDATA)_bs._GetBandItemDataStructByID(rbbi.wID);
|
|
if (pbid)
|
|
IUnknown_Exec(pbid->pdb, pguidCmdGroup, CITIDM_THEATER, nCmdexecopt, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case THF_UNHIDE:
|
|
// position everything properly (needed after reparenting)
|
|
SendMessage(_hwnd, RB_PRIV_RESIZE, 0, 0);
|
|
break;
|
|
}
|
|
|
|
// IF YOU SEE HTIS ASSERT, TRY TO REMEMBER WHAT YOU DID AND CALL CHEE
|
|
ASSERT(_fTheater || _nVisibleBands & VBF_MENU);
|
|
}
|
|
|
|
break;
|
|
case CITIDM_VIEWEXTERNALBAND_BYCLASSID:
|
|
if ((pvarargIn->vt == VT_BSTR) && pvarargIn->bstrVal)
|
|
{
|
|
CLSID clsid;
|
|
if (GUIDFromString( pvarargIn->bstrVal, &clsid ))
|
|
{
|
|
hr = E_FAIL;
|
|
for (DWORD i = 0; i < MAXEXTERNALBANDS; i++)
|
|
{
|
|
if (clsid == _rgebi[i].clsid)
|
|
{
|
|
DWORD dw = _nVisibleBands;
|
|
DWORD dwBit = EXTERNALBAND_VBF_BIT( i );
|
|
dw = (nCmdexecopt) ? dw | dwBit : dw & ~dwBit;
|
|
if ( !( dw & ~VBF_BRAND))
|
|
{
|
|
_pdie->put_ToolBar( FALSE );
|
|
}
|
|
_ShowVisible(dw, TRUE);
|
|
_fUsingDefaultBands = FALSE;
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
if (InRange( nCmdID, CITIDM_VIEWEXTERNALBAND_FIRST, CITIDM_VIEWEXTERNALBAND_LAST ))
|
|
{
|
|
_OnCommand(GET_WM_COMMAND_MPS( nCmdID - CITIDM_VIEWEXTERNALBAND_FIRST + FCIDM_EXTERNALBANDS_FIRST, _hwnd, 0));
|
|
break;
|
|
}
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Lother:
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
|
|
if (pbid)
|
|
{
|
|
hr = IUnknown_Exec(pbid->pdb, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
BOOL _GetSearchHKEY(REFGUID guidSearch, HKEY *phkey)
|
|
{
|
|
HKEY hkey;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_SZ_STATIC, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
|
|
{
|
|
TCHAR szExt[MAX_PATH];//extension key name
|
|
DWORD cchExt = ARRAYSIZE(szExt);
|
|
int iExt;
|
|
BOOL bNoUrl = FALSE; // true iff guidSearch is found and there is no Url subkey
|
|
|
|
for (iExt=0;
|
|
!bRet && RegEnumKeyEx(hkey, iExt, szExt, &cchExt, NULL, NULL, NULL, NULL) == ERROR_SUCCESS;
|
|
cchExt = ARRAYSIZE(szExt), iExt++)
|
|
{
|
|
HKEY hkeyExt; // static extension key
|
|
|
|
if (RegOpenKeyEx(hkey, szExt, 0, KEY_READ, &hkeyExt) == ERROR_SUCCESS)
|
|
{
|
|
int i;
|
|
TCHAR szSubKey[32];
|
|
HKEY hkeySub;
|
|
|
|
for (i = 0; !bRet && (wnsprintf(szSubKey, ARRAYSIZE(szSubKey), TEXT("%d"), i),
|
|
RegOpenKey(hkeyExt, szSubKey, &hkeySub) == ERROR_SUCCESS);
|
|
i++)
|
|
{
|
|
TCHAR szSearchGuid[GUIDSTR_MAX];
|
|
DWORD cb;
|
|
DWORD dwType;
|
|
|
|
cb = sizeof(szSearchGuid);
|
|
if (SHGetValue(hkeySub, REG_SZ_SEARCH_GUID, NULL, &dwType, (BYTE*)szSearchGuid, &cb) == ERROR_SUCCESS)
|
|
{
|
|
GUID guid;
|
|
|
|
if (GUIDFromString(szSearchGuid, &guid) &&
|
|
IsEqualGUID(guid, guidSearch))
|
|
{
|
|
HKEY hkeyTmp;
|
|
|
|
if (RegOpenKey(hkeySub, REG_SZ_SEARCH_URL, &hkeyTmp) == ERROR_SUCCESS)
|
|
RegCloseKey(hkeyTmp);
|
|
else
|
|
bNoUrl = TRUE;
|
|
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
if (!bRet || bNoUrl)
|
|
RegCloseKey(hkeySub);
|
|
else
|
|
*phkey = hkeySub;
|
|
|
|
}
|
|
if (!bNoUrl)
|
|
RegCloseKey(hkeyExt);
|
|
else
|
|
{
|
|
ASSERT(bRet);
|
|
*phkey = hkeyExt;
|
|
}
|
|
}
|
|
}
|
|
RegCloseKey(hkey);
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::GetDefaultSearchUrl(LPWSTR pwszUrl, UINT cch)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (GetDefaultInternetSearchUrlW(pwszUrl, cch, TRUE))
|
|
hr = S_OK;
|
|
return hr;
|
|
}
|
|
|
|
void WINAPI CopyEnumElement(void *pDest, const void *pSource, DWORD dwSize)
|
|
{
|
|
if (!pDest)
|
|
return;
|
|
|
|
memcpy(pDest, pSource, dwSize);
|
|
}
|
|
|
|
class CFolderSearches : public IFolderSearches
|
|
{
|
|
public:
|
|
// *** IUnknown ***
|
|
STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj);
|
|
STDMETHODIMP_(ULONG) AddRef(void);
|
|
STDMETHODIMP_(ULONG) Release(void);
|
|
// *** IFolderSearches ***
|
|
STDMETHODIMP EnumSearches(IEnumUrlSearch **ppenum);
|
|
STDMETHODIMP DefaultSearch(GUID *pguid);
|
|
|
|
CFolderSearches(GUID *pguid, int iCount, URLSEARCH *pUrlSearch);
|
|
~CFolderSearches();
|
|
private:
|
|
LONG _cRef;
|
|
int _iCount;
|
|
GUID _guidDefault;
|
|
URLSEARCH *_pUrlSearch;
|
|
};
|
|
|
|
CFolderSearches::CFolderSearches(GUID *pguid, int iCount, URLSEARCH *pUrlSearch)
|
|
{
|
|
_cRef = 1;
|
|
_iCount = iCount;
|
|
_guidDefault = *pguid;
|
|
_pUrlSearch = pUrlSearch;
|
|
}
|
|
|
|
CFolderSearches::~CFolderSearches()
|
|
{
|
|
if (_pUrlSearch)
|
|
LocalFree(_pUrlSearch);
|
|
}
|
|
|
|
HRESULT CFolderSearches::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
static const QITAB qit[] =
|
|
{
|
|
QITABENT(CFolderSearches, IFolderSearches),
|
|
{ 0 },
|
|
};
|
|
|
|
return QISearch(this, qit, riid, ppvObj);
|
|
}
|
|
|
|
ULONG CFolderSearches::AddRef()
|
|
{
|
|
return ++_cRef;
|
|
}
|
|
|
|
ULONG CFolderSearches::Release()
|
|
{
|
|
if (--_cRef > 0)
|
|
return _cRef;
|
|
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
HRESULT CFolderSearches::EnumSearches(IEnumUrlSearch **ppenum)
|
|
{
|
|
HRESULT hres = E_OUTOFMEMORY;
|
|
|
|
*ppenum = (IEnumUrlSearch *)new CStandardEnum(IID_IEnumUrlSearch, FALSE,
|
|
_iCount, sizeof(URLSEARCH), _pUrlSearch, CopyEnumElement);
|
|
if (*ppenum)
|
|
{
|
|
_pUrlSearch = NULL;
|
|
_iCount = 0;
|
|
hres = S_OK;
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
HRESULT CFolderSearches::DefaultSearch(GUID *pguid)
|
|
{
|
|
*pguid = _guidDefault;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::_GetFolderSearches(IFolderSearches **ppfs)
|
|
{
|
|
HRESULT hres = E_FAIL;
|
|
|
|
*ppfs = NULL;
|
|
if (_hdpaFSI)
|
|
{
|
|
LPURLSEARCH pUrlSearch = NULL;
|
|
int iCount = 0;
|
|
int cFSIs = DPA_GetPtrCount(_hdpaFSI);
|
|
|
|
hres = E_OUTOFMEMORY;
|
|
if (cFSIs > 0
|
|
&& ((pUrlSearch = (LPURLSEARCH)LocalAlloc(LPTR, sizeof(URLSEARCH)*cFSIs)) != NULL))
|
|
{
|
|
LPFOLDERSEARCHITEM pfsi;
|
|
int i;
|
|
|
|
// insert per folder items
|
|
for (i = 0; i < cFSIs && (pfsi = (LPFOLDERSEARCHITEM)DPA_GetPtr(_hdpaFSI, i)) != NULL; i++)
|
|
{
|
|
CLSID clsid;
|
|
|
|
// check if Url is actually a GUID. if yes we cannot enumerate it because
|
|
// we need Title/Url pair.
|
|
if (!GUIDFromStringW(pfsi->wszUrl, &clsid))
|
|
{
|
|
lstrcpynW(pUrlSearch[iCount].wszName, pfsi->wszName, ARRAYSIZE(pUrlSearch[iCount].wszName));
|
|
lstrcpynW(pUrlSearch[iCount].wszUrl, pfsi->wszUrl, ARRAYSIZE(pUrlSearch[iCount].wszUrl));
|
|
iCount++;
|
|
}
|
|
}
|
|
}
|
|
*ppfs = new CFolderSearches(&_guidDefaultSearch, iCount, pUrlSearch);
|
|
if (*ppfs)
|
|
hres = S_OK;
|
|
else
|
|
LocalFree(pUrlSearch);
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
BOOL CInternetToolbar::_GetSearchUrl(LPWSTR pwszUrl, DWORD cch)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
HKEY hkey;
|
|
|
|
if (pwszUrl)
|
|
{
|
|
pwszUrl[0] = L'\0';
|
|
|
|
// if we are looking for web search url bypass the registry lookup and the
|
|
// per folder items and go straight to GetDefaultSearchUrl which call
|
|
// GetSearchAssistantUrlW
|
|
if (!IsEqualGUID(_guidDefaultSearch, SRCID_SWebSearch))
|
|
{
|
|
// _GetSearchHKEY looks in the registry where shell search items are registered
|
|
// if we have old shell32 then we don't display shell search items so we should
|
|
// not look in the registry
|
|
if (GetUIVersion() >= 5 && _GetSearchHKEY(_guidDefaultSearch, &hkey))
|
|
{
|
|
DWORD cb = cch*sizeof(TCHAR);
|
|
TCHAR szGuid[GUIDSTR_MAX];
|
|
DWORD cbGuid = sizeof(szGuid);
|
|
|
|
// is there a url key
|
|
if (SHGetValueW(hkey, REG_SZ_SEARCH_URL, NULL, NULL, pwszUrl, &cb) == ERROR_SUCCESS)
|
|
bRet = TRUE;
|
|
// no? try the default value, maybe it's the clsid
|
|
else if (SHGetValueW(hkey, NULL, NULL, NULL, szGuid, &cbGuid) == ERROR_SUCCESS)
|
|
{
|
|
GUID guid;
|
|
// is it a valid guid string
|
|
if (GUIDFromString(szGuid, &guid))
|
|
{
|
|
StrCpyNW(pwszUrl, szGuid, cch);
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
// maybe it's one of the per-folder items...
|
|
else if (_hdpaFSI) //FSI = folder search items
|
|
{
|
|
int i;
|
|
LPFOLDERSEARCHITEM pfsi;
|
|
|
|
for (i=0; (pfsi = (LPFOLDERSEARCHITEM)DPA_GetPtr(_hdpaFSI, i)) != NULL; i++)
|
|
{
|
|
if (IsEqualGUID(_guidDefaultSearch, pfsi->guidSearch))
|
|
{
|
|
StrCpyNW(pwszUrl, pfsi->wszUrl, cch);
|
|
bRet = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!bRet)
|
|
bRet = SUCCEEDED(GetDefaultSearchUrl(pwszUrl, cch));
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
void CInternetToolbar::_SetSearchStuff()
|
|
{
|
|
UINT uiState;
|
|
BOOL bChecked = FALSE;
|
|
|
|
if (SUCCEEDED(GetState(&CLSID_CommonButtons, TBIDM_SEARCH, &uiState)))
|
|
bChecked = uiState & TBSTATE_CHECKED;
|
|
|
|
if (!_hdpaFSI)
|
|
{
|
|
_hdpaFSI = DPA_Create(2);
|
|
}
|
|
else
|
|
{
|
|
DPA_EnumCallback(_hdpaFSI, DeleteDPAPtrCB, NULL); // delete all ptrs
|
|
DPA_DeleteAllPtrs(_hdpaFSI); // now tell hdpa to forget about them
|
|
}
|
|
|
|
// this is bogus -- _fShellView is always FALSE when using automation
|
|
if (_fShellView)
|
|
_guidDefaultSearch = SRCID_SFileSearch;
|
|
else
|
|
_guidDefaultSearch = SRCID_SWebSearch;
|
|
|
|
// get per folder search items and the default search (if any)
|
|
// and insert them to _himlSrc
|
|
_GetFolderSearchData();
|
|
|
|
if (!bChecked)
|
|
{
|
|
_guidCurrentSearch = _guidDefaultSearch;
|
|
}
|
|
}
|
|
|
|
//
|
|
// CInternetToolbar::SetCommandTarget()
|
|
//
|
|
// This function sets the current command target and button group. A client calls this
|
|
// before merging in buttons with the AddButtons method.
|
|
//
|
|
// There are a couple of tricky things about this function.
|
|
//
|
|
// NTRAID#NTBUG9-196149-2000/12/11-AIDANL Hide Address Bar by default in explorer for Per/Pro
|
|
// We no longer allow dwFlags to set links, address, tools, brand, relying on
|
|
// CInternetToolbar::_LoadDefaultSettings() for those settings.
|
|
//
|
|
// One is that the client can pass some flags (dwFlags param) specifying the bands it wants
|
|
// showing by default (menu, links, address, tools, brand, external). But we don't let them change
|
|
// the state of the menu band. And, if another client has already set the default bands, we
|
|
// don't let them change the state of any of the bands.
|
|
//
|
|
// The other is that we do some stuff to figure out if the caller is just another instantiation of the same
|
|
// client. If we think this is a new client (new guidButtonGroup), we flush the toolbar and return S_OK.
|
|
// But if we think this is the same client reincarnated (same guidButtonGroup and non-NULL command target),
|
|
// we return S_FALSE without flushing the toolbar. This is done for performance. A new dochost is instantiated
|
|
// on each navigation, but its toolbar buttons never change, so don't bother remerging its toolbar buttons.
|
|
//
|
|
HRESULT CInternetToolbar::SetCommandTarget(IUnknown* punkCmdTarget, const GUID* pguidButtonGroup, DWORD dwFlags)
|
|
{
|
|
if (!pguidButtonGroup || !punkCmdTarget || IsEqualGUID(CLSID_CommonButtons, *pguidButtonGroup))
|
|
return E_INVALIDARG;
|
|
|
|
// RAID 196149 - disallow changes to links, address, tools, brand, instead use _cs.uiVisible for these settings
|
|
dwFlags = dwFlags & ~(VBF_LINKS| VBF_ADDRESS | VBF_TOOLS | VBF_BRAND);
|
|
dwFlags |= (_cs.uiVisible & (VBF_LINKS| VBF_ADDRESS | VBF_TOOLS | VBF_BRAND));
|
|
|
|
// this should not change the menu bit or external bands.
|
|
dwFlags |= (_nVisibleBands & (VBF_MENU | VBF_EXTERNALBANDS));
|
|
|
|
_btb._fCustomize = !((dwFlags & VBF_NOCUSTOMIZE) || SHRestricted2(REST_NOTOOLBARCUSTOMIZE, NULL, 0));
|
|
|
|
// if the new button group is the internet button group, then we're
|
|
// in internet mode; else we're in shell mode
|
|
_fShellView = !(_IsDocHostGUID(pguidButtonGroup));
|
|
|
|
_SetSearchStuff();
|
|
|
|
HRESULT hr = S_FALSE;
|
|
|
|
BOOL fNewButtonGroup = !IsEqualGUID(*pguidButtonGroup, _btb._guidCurrentButtonGroup);
|
|
BOOL fNewCommandTarget = !SHIsSameObject(_btb._pctCurrentButtonGroup, punkCmdTarget);
|
|
|
|
// when changing button groups we need to invalidate our cache of buttons for customization
|
|
// why? well, with browse in separate process not turned on, navigating from shell to web
|
|
// reuses the toolbar and some buttons may be disabled for shell but not for browser and vice versa.
|
|
if (fNewButtonGroup)
|
|
_iButtons = -1;
|
|
|
|
if (fNewButtonGroup || fNewCommandTarget)
|
|
{
|
|
if (_btb._pctCurrentButtonGroup)
|
|
_btb._pctCurrentButtonGroup->Exec(&IID_IExplorerToolbar, ETCMDID_NEWCOMMANDTARGET, 0, NULL, NULL);
|
|
|
|
_btb._guidCurrentButtonGroup = *pguidButtonGroup;
|
|
ATOMICRELEASE(_btb._pctCurrentButtonGroup);
|
|
punkCmdTarget->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &_btb._pctCurrentButtonGroup));
|
|
|
|
// A new view can tell us how many rows of text it NEEDs.
|
|
// if it doesn't specify, we give it the default. (stored in _uiDefaultTBTextRows)
|
|
if (dwFlags & VBF_ONELINETEXT )
|
|
_uiTBTextRows = 1;
|
|
else if (dwFlags & VBF_TWOLINESTEXT)
|
|
_uiTBTextRows = 2;
|
|
else
|
|
_uiTBTextRows = _uiTBDefaultTextRows;
|
|
|
|
_CompressBands(_fCompressed, _uiTBTextRows, FALSE);
|
|
|
|
if (fNewButtonGroup)
|
|
{
|
|
// new button group; flush toolbar
|
|
_btb._RemoveAllButtons();
|
|
hr = S_OK;
|
|
}
|
|
|
|
if (_fUsingDefaultBands && !_fTheater)
|
|
_fUsingDefaultBands = FALSE;
|
|
else
|
|
dwFlags = _nVisibleBands;
|
|
|
|
if (dwFlags)
|
|
_ShowBands(dwFlags);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::AddStdBrowserButtons()
|
|
{
|
|
//
|
|
// code to add browser buttons has moved to CDocObjectHost::_AddButtons
|
|
//
|
|
ASSERT(0);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
void CInternetToolbar::_ReloadButtons()
|
|
{
|
|
if (!IsEqualGUID(_btb._guidCurrentButtonGroup, CLSID_CommonButtons) &&
|
|
_btb._pctCurrentButtonGroup)
|
|
{
|
|
HRESULT hres = _btb._pctCurrentButtonGroup->Exec(&IID_IExplorerToolbar, ETCMDID_RELOADBUTTONS, 0, NULL, NULL);
|
|
if (FAILED(hres))
|
|
AddButtons(&_btb._guidCurrentButtonGroup, _btb._cBtnsAdded, _btb._pbtnsAdded);
|
|
|
|
#ifdef EDIT_HACK
|
|
_InitEditButtonStyle();
|
|
#endif
|
|
|
|
_UpdateToolbar(TRUE);
|
|
}
|
|
}
|
|
|
|
// The cmdTarget should have already added the Imagelists and the strings.
|
|
HRESULT CInternetToolbar::AddButtons(const GUID* pguidButtonGroup, UINT nNewButtons, const TBBUTTON * lpButtons)
|
|
{
|
|
if (!pguidButtonGroup || !IsEqualGUID(*pguidButtonGroup, _btb._guidCurrentButtonGroup))
|
|
return E_INVALIDARG;
|
|
|
|
if (!IsWindow(_btb._hwnd))
|
|
return E_FAIL;
|
|
|
|
LPTBBUTTON lpTBCopy = (LPTBBUTTON)LocalAlloc(LPTR, nNewButtons * sizeof(TBBUTTON));
|
|
if (!lpTBCopy)
|
|
return E_OUTOFMEMORY;
|
|
|
|
_CreateBands();
|
|
_btb._RemoveAllButtons();
|
|
|
|
memcpy(lpTBCopy, lpButtons, sizeof(TBBUTTON) * nNewButtons);
|
|
|
|
nNewButtons = _btb._ProcessExternalButtons(lpTBCopy, nNewButtons);
|
|
|
|
// Free the old button array
|
|
_btb._FreeBtnsAdded();
|
|
|
|
_btb._pbtnsAdded = lpTBCopy;
|
|
_btb._cBtnsAdded = nNewButtons;
|
|
|
|
if (_btb._fCustomize && _btb._SaveRestoreToolbar(FALSE))
|
|
{
|
|
// Customization mechanism filled the toolbar for us
|
|
|
|
//
|
|
// The customization mechanism allocated its own set of
|
|
// cmdmaps for the buttons, which means that we need to
|
|
// free those hanging off _pbtnsAdded when _pbtnsAdded is
|
|
// freed.
|
|
//
|
|
_btb._fNeedFreeCmdMapsAdded = TRUE;
|
|
|
|
_btb._RecalcButtonWidths();
|
|
|
|
#ifdef EDIT_HACK
|
|
//
|
|
// If we had a custom edit glyph, reload it so that we
|
|
// don't momentarily flash the default glyph during
|
|
// navigation. We'll update it again when we get a
|
|
// DISPID_DOCUMENTCOMPLETE event.
|
|
//
|
|
_RefreshEditGlyph();
|
|
#endif //EDIT_HACK
|
|
|
|
if (!_fShellView)
|
|
{
|
|
_btb._AddMediaBarButton();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No customization found for this button group
|
|
|
|
//
|
|
// We're adding the button array to toolbar directly,
|
|
// and the cmdmaps get freed on TBN_DELETINGBUTTON, so
|
|
// we shouldn't also try to free them when _pbtnsAdded
|
|
// is freed.
|
|
//
|
|
_btb._fNeedFreeCmdMapsAdded = FALSE;
|
|
|
|
_AddCommonButtons();
|
|
SendMessage(_btb._hwnd, TB_ADDBUTTONS, nNewButtons, (LPARAM)lpTBCopy);
|
|
}
|
|
|
|
_bs._SetMinDimensions();
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::AddString(const GUID * pguidButtonGroup, HINSTANCE hInst, UINT_PTR uiResID, LONG_PTR *pOffset)
|
|
{
|
|
TraceMsg(DM_ITBAR, "CITBar::AddString called");
|
|
|
|
*pOffset = -1;
|
|
|
|
if (!IsWindow(_btb._hwnd))
|
|
{
|
|
TraceMsg(DM_ERROR, "CITBar::AddString failed");
|
|
return E_FAIL;
|
|
}
|
|
|
|
*pOffset= SendMessage(_btb._hwnd, TB_ADDSTRING, (WPARAM)hInst, (LPARAM)uiResID);
|
|
|
|
if (*pOffset != -1)
|
|
return S_OK;
|
|
|
|
TraceMsg(DM_ERROR, "CITBar::AddString failed");
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::GetButton(const GUID* pguidButtonGroup, UINT uiCommand, LPTBBUTTON lpButton)
|
|
{
|
|
UINT_PTR uiIndex = 0;
|
|
TraceMsg(DM_ITBAR, "CITBar::GetButton called");
|
|
|
|
if (!pguidButtonGroup || !IsWindow(_btb._hwnd))
|
|
return E_FAIL;
|
|
|
|
if (SUCCEEDED(_btb._ConvertCmd(pguidButtonGroup, uiCommand, NULL, &uiCommand)))
|
|
{
|
|
uiIndex = SendMessage(_btb._hwnd, TB_COMMANDTOINDEX, uiCommand, 0L);
|
|
if (SendMessage(_btb._hwnd, TB_GETBUTTON, uiIndex, (LPARAM)lpButton))
|
|
{
|
|
GUID guid;
|
|
_btb._ConvertCmd(NULL, lpButton->idCommand, &guid, (UINT*)&lpButton->idCommand);
|
|
return S_OK;
|
|
}
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::GetState(const GUID* pguidButtonGroup, UINT uiCommand, UINT * pfState)
|
|
{
|
|
TraceMsg(DM_ITBAR, "CITBar::GetState called");
|
|
|
|
if (!pguidButtonGroup || !IsWindow(_btb._hwnd))
|
|
return E_FAIL;
|
|
|
|
if (SUCCEEDED(_btb._ConvertCmd(pguidButtonGroup, uiCommand, NULL, &uiCommand)))
|
|
{
|
|
*pfState = (UINT)SendMessage(_btb._hwnd, TB_GETSTATE, uiCommand, 0L);
|
|
return S_OK;
|
|
}
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::SetState(const GUID* pguidButtonGroup, UINT uiCommand, UINT fState)
|
|
{
|
|
BOOL bIsSearchBtn;
|
|
|
|
if (!pguidButtonGroup || !IsWindow(_btb._hwnd))
|
|
return E_FAIL;
|
|
|
|
TraceMsg(DM_ITBAR, "CITBar::SetState called");
|
|
|
|
bIsSearchBtn = uiCommand == TBIDM_SEARCH;
|
|
if (SUCCEEDED(_btb._ConvertCmd(pguidButtonGroup, uiCommand, NULL, &uiCommand)))
|
|
{
|
|
UINT_PTR uiState;
|
|
|
|
uiState = SendMessage(_btb._hwnd, TB_GETSTATE, uiCommand, NULL);
|
|
uiState ^= fState;
|
|
if (uiState)
|
|
{
|
|
// search button is being unchecked, change the icon to the default search's
|
|
if (bIsSearchBtn && !(fState & TBSTATE_CHECKED) && !IsEqualGUID(_guidCurrentSearch, _guidDefaultSearch))
|
|
{
|
|
_guidCurrentSearch = _guidDefaultSearch;
|
|
}
|
|
if (SendMessage(_btb._hwnd, TB_SETSTATE, uiCommand, (LPARAM)fState))
|
|
{
|
|
if (uiState & TBSTATE_HIDDEN)
|
|
_bs._SetMinDimensions();
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// A bitmap can be added in two ways:
|
|
// 1. Send a bitmap in the hBMPNew field. The uiBMPType parameter needs to be a BITMAP_BMP*
|
|
// The uiCount and the ptb parameters are ignored
|
|
// The offset is placed in puiOffset
|
|
//
|
|
// 2. A TBADDBITMAP struct can be sent. The uiCount should have the count
|
|
// uiBMPType parameter needs to be a BITMAP_TBA* value
|
|
// The offset is placed in puiOffset
|
|
HRESULT CInternetToolbar::AddBitmap(const GUID * pguidButtonGroup, UINT uiBMPType, UINT uiCount, TBADDBITMAP * ptb, LRESULT * pOffset, COLORREF rgbMask)
|
|
{
|
|
UINT uiGetMSG, uiSetMSG;
|
|
TBBMP_LIST tbl = {NULL};
|
|
|
|
TraceMsg(DM_ITBAR, "CITBar::AddBitmap called");
|
|
*pOffset = -1;
|
|
|
|
_CreateBands();
|
|
if ((!pguidButtonGroup) || (!IsWindow(_btb._hwnd)) || !_hdsaTBBMPs)
|
|
{
|
|
TraceMsg(DM_ERROR, "CITBar::AddBitmap failed - NULL pguidButtonGroup or invalid _hwnd");
|
|
return E_FAIL;
|
|
}
|
|
|
|
// See if we already have the bitmap loaded.
|
|
TBBMP_LIST * pTBBs = NULL;
|
|
int nCount = DSA_GetItemCount(_hdsaTBBMPs);
|
|
for (int nIndex = 0; nIndex < nCount; nIndex++)
|
|
{
|
|
pTBBs = (TBBMP_LIST*)DSA_GetItemPtr(_hdsaTBBMPs, nIndex);
|
|
if ((pTBBs) && (pTBBs->hInst == ptb->hInst) && (pTBBs->uiResID == ptb->nID))
|
|
break;
|
|
pTBBs = NULL;
|
|
}
|
|
|
|
// If it was in the commctrl, then we should already have an entry in the DSA
|
|
if ((ptb->hInst == HINST_COMMCTRL) && (!pTBBs))
|
|
{
|
|
TraceMsg(DM_ERROR, "CITBar::AddBitmap failed - bogus ResID for HINST_COMMCTL");
|
|
return E_FAIL;
|
|
}
|
|
|
|
// If the icons being added are from fontsext.dll or from dialup networking
|
|
// or the briefcase, then we have it. So just send return the offset
|
|
if (ptb->hInst != HINST_COMMCTRL)
|
|
{
|
|
TCHAR szDLLFileName[MAX_PATH], *pszFN;
|
|
memset(szDLLFileName, 0, ARRAYSIZE(szDLLFileName));
|
|
if (GetModuleFileName(ptb->hInst, szDLLFileName, ARRAYSIZE(szDLLFileName)))
|
|
{
|
|
pszFN = PathFindFileName(szDLLFileName);
|
|
if(!lstrcmpi(pszFN, TEXT("fontext.dll")))
|
|
*pOffset = FONTGLYPH_OFFSET;
|
|
else if (!lstrcmpi(pszFN, TEXT("shell32.dll")))
|
|
{
|
|
// 140 and 141 are the glyphs that Shell32.dll uses:
|
|
// IDB_BRF_TB_SMALL 140
|
|
// IDB_BRF_TB_LARGE 141
|
|
if ((ptb->nID == 140) || (ptb->nID == 141))
|
|
*pOffset = BRIEFCASEGLYPH_OFFSET;
|
|
}
|
|
else if (!lstrcmpi(pszFN, TEXT("rnaui.dll")))
|
|
*pOffset = RNAUIGLYPH_OFFSET;
|
|
else if (!lstrcmpi(pszFN, TEXT("webcheck.dll")))
|
|
*pOffset = WEBCHECKGLYPH_OFFSET;
|
|
if (*pOffset != -1)
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
// So the bitmaps is not from commctrl. And we have never seen this before.
|
|
// Add an entry into the DSA and then add the bitmap to the himage list.
|
|
if (!pTBBs)
|
|
{
|
|
tbl.hInst = ptb->hInst;
|
|
tbl.uiResID = ptb->nID;
|
|
nIndex = DSA_AppendItem(_hdsaTBBMPs, &tbl);
|
|
if (nIndex < 0)
|
|
{
|
|
TraceMsg(DM_ERROR, "CITBar::AddBitmap failed - nIndex < 0!");
|
|
return E_FAIL;
|
|
}
|
|
pTBBs = (TBBMP_LIST*)DSA_GetItemPtr(_hdsaTBBMPs, nIndex);
|
|
if (!pTBBs)
|
|
{
|
|
TraceMsg(DM_ERROR, "CITBar::AddBitmap failed - pTBBS is NULL!");
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
|
|
switch(uiBMPType)
|
|
{
|
|
case BITMAP_NORMAL:
|
|
if ((pTBBs) && (pTBBs->fNormal))
|
|
{
|
|
*pOffset = pTBBs->uiOffset;
|
|
return S_OK;
|
|
}
|
|
else if (pTBBs)
|
|
pTBBs->fNormal = TRUE;
|
|
|
|
uiGetMSG = TB_GETIMAGELIST; uiSetMSG = TB_SETIMAGELIST;
|
|
break;
|
|
|
|
case BITMAP_HOT:
|
|
if ((pTBBs) && (pTBBs->fHot))
|
|
{
|
|
*pOffset = pTBBs->uiOffset;
|
|
return S_OK;
|
|
}
|
|
else if (pTBBs)
|
|
pTBBs->fHot = TRUE;
|
|
|
|
uiGetMSG = TB_GETHOTIMAGELIST; uiSetMSG = TB_SETHOTIMAGELIST;
|
|
break;
|
|
|
|
case BITMAP_DISABLED:
|
|
if ((pTBBs) && (pTBBs->fDisabled))
|
|
{
|
|
*pOffset = pTBBs->uiOffset;
|
|
return S_OK;
|
|
}
|
|
else if (pTBBs)
|
|
pTBBs->fDisabled = TRUE;
|
|
|
|
uiGetMSG = TB_GETDISABLEDIMAGELIST; uiSetMSG = TB_SETDISABLEDIMAGELIST;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(FALSE);
|
|
return E_FAIL;
|
|
}
|
|
pTBBs->uiCount = uiCount;
|
|
|
|
*pOffset = _AddBitmapFromForeignModule(uiGetMSG, uiSetMSG, uiCount, ptb->hInst, ptb->nID, rgbMask);
|
|
if (pTBBs)
|
|
pTBBs->uiOffset = (UINT)*pOffset;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// the CmdTarget needs to call this to see what size of bmps we are using.
|
|
HRESULT CInternetToolbar::GetBitmapSize(UINT * uiSize)
|
|
{
|
|
TraceMsg(DM_ITBAR, "CITBar::GetBitmapSize called");
|
|
|
|
*uiSize = g_fSmallIcons ? MAKELONG(TB_SMBMP_CX, TB_SMBMP_CY) : MAKELONG(g_iToolBarLargeIconWidth,g_iToolBarLargeIconHeight);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::SetImageList( const GUID* pguidCmdGroup, HIMAGELIST himlNormal, HIMAGELIST himlHot, HIMAGELIST himlDisabled)
|
|
{
|
|
if (IsEqualGUID(*pguidCmdGroup, _btb._guidCurrentButtonGroup))
|
|
{
|
|
SendMessage(_btb._hwnd, TB_SETIMAGELIST, 1, (LPARAM)himlNormal);
|
|
SendMessage(_btb._hwnd, TB_SETHOTIMAGELIST, 1, (LPARAM)himlHot);
|
|
SendMessage(_btb._hwnd, TB_SETDISABLEDIMAGELIST, 1, (LPARAM)himlDisabled);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::ModifyButton( const GUID * pguidButtonGroup, UINT uiCommand, LPTBBUTTON lpButton)
|
|
{
|
|
UINT uiIndex = 0;
|
|
TraceMsg(DM_ITBAR, "CITBar::ModifyButton called");
|
|
|
|
if (!pguidButtonGroup || !IsWindow(_btb._hwnd))
|
|
return E_FAIL;
|
|
|
|
if (SUCCEEDED(_btb._ConvertCmd(pguidButtonGroup, uiCommand, NULL, &uiCommand)))
|
|
{
|
|
TBBUTTONINFO tbbi;
|
|
tbbi.cbSize = sizeof(tbbi);
|
|
tbbi.dwMask = TBIF_STATE | TBIF_IMAGE;
|
|
tbbi.fsState = lpButton->fsState;
|
|
tbbi.iImage = lpButton->iBitmap;
|
|
|
|
if (SendMessage(_btb._hwnd, TB_SETBUTTONINFO, uiCommand, (LPARAM)&tbbi))
|
|
{
|
|
return S_OK;
|
|
}
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::SendToolbarMsg(const GUID* pguidButtonGroup, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT * plRes)
|
|
{
|
|
LRESULT lRes;
|
|
if (!IsWindow(_btb._hwnd))
|
|
{
|
|
TraceMsg(DM_ERROR, "CITBar::SendToolbarMsg Message failed");
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (
|
|
// this api is only here for back compat, and these messages didn't
|
|
// exist when the old clients were written
|
|
|
|
uMsg == TB_GETBUTTONINFOA ||
|
|
uMsg == TB_GETBUTTONINFOW ||
|
|
uMsg == TB_SETBUTTONINFOA ||
|
|
uMsg == TB_SETBUTTONINFOW ||
|
|
|
|
// unsupported right now
|
|
uMsg == TB_ADDBUTTONSA || uMsg == TB_ADDBUTTONSW
|
|
)
|
|
{
|
|
|
|
ASSERT(0);
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
|
|
if ((uMsg == TB_ENABLEBUTTON) || (uMsg == TB_HIDEBUTTON) || (uMsg == TB_CHECKBUTTON) ||
|
|
(uMsg == TB_PRESSBUTTON) || (uMsg == TB_MARKBUTTON))
|
|
{
|
|
unsigned int uiTemp;
|
|
if (SUCCEEDED(_btb._ConvertCmd(pguidButtonGroup, (UINT)wParam, NULL, &uiTemp)))
|
|
wParam = uiTemp;
|
|
}
|
|
|
|
if (uMsg == TB_INSERTBUTTON && lParam)
|
|
{
|
|
TBBUTTON btn = (*(TBBUTTON*)lParam);
|
|
_btb._PreProcessExternalTBButton(&btn);
|
|
lRes = SendMessage(_btb._hwnd, uMsg, wParam, (LPARAM)&btn);
|
|
}
|
|
else
|
|
{
|
|
lRes = SendMessage(_btb._hwnd, uMsg, wParam, lParam);
|
|
|
|
if (uMsg == TB_GETBUTTON)
|
|
{
|
|
TBBUTTON* pbtn = (TBBUTTON*)lParam;
|
|
if (pbtn && pbtn->dwData)
|
|
{
|
|
CMDMAP* pcm = (CMDMAP*)pbtn->dwData;
|
|
pbtn->idCommand = pcm->nCmdID;
|
|
pbtn->dwData = pcm->lParam;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (plRes)
|
|
*plRes = lRes;
|
|
return S_OK;
|
|
}
|
|
|
|
TOOLSBANDCLASS::CBrowserToolsBand() : CToolbarBand()
|
|
{
|
|
_fCanFocus = TRUE;
|
|
}
|
|
|
|
#define DEFAULT_LIST_VALUE() (GetUIVersion() >= 5)
|
|
|
|
void TOOLSBANDCLASS::_FreeBtnsAdded()
|
|
{
|
|
if (_pbtnsAdded)
|
|
{
|
|
if (_fNeedFreeCmdMapsAdded)
|
|
{
|
|
for (int i = 0; i < _cBtnsAdded; i++)
|
|
{
|
|
CMDMAP* pcm = (CMDMAP*)_pbtnsAdded[i].dwData;
|
|
_FreeCmdMap(pcm);
|
|
}
|
|
}
|
|
|
|
LocalFree(_pbtnsAdded);
|
|
|
|
_pbtnsAdded = NULL;
|
|
_cBtnsAdded = 0;
|
|
}
|
|
}
|
|
|
|
LRESULT TOOLSBANDCLASS::_ToolsCustNotify (LPNMHDR pnmh)
|
|
{
|
|
LPTBNOTIFY ptbn = (LPTBNOTIFY) pnmh;
|
|
|
|
switch (pnmh->code)
|
|
{
|
|
|
|
case TBN_SAVE:
|
|
{
|
|
NMTBSAVE *pnmtbs = (NMTBSAVE*)pnmh;
|
|
if (pnmtbs->iItem == -1)
|
|
{
|
|
// before the save
|
|
int nButtons = (int) SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0L);
|
|
int uSize = pnmtbs->cbData +
|
|
sizeof(BUTTONSAVEINFO) * nButtons + // stuff for each button
|
|
sizeof(TOOLBARSAVEINFO); // stuff for the toolbar
|
|
pnmtbs->pData = (LPDWORD)LocalAlloc(LPTR, uSize);
|
|
pnmtbs->pCurrent = pnmtbs->pData;
|
|
pnmtbs->cbData = uSize;
|
|
|
|
if (pnmtbs->pData)
|
|
{
|
|
TOOLBARSAVEINFO *ptbsi = (TOOLBARSAVEINFO*)pnmtbs->pData;
|
|
ptbsi->cVersion = TBSI_VERSION;
|
|
pnmtbs->pCurrent = (LPDWORD)(ptbsi+1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CMDMAP *pcm = (CMDMAP*)pnmtbs->tbButton.dwData;
|
|
BUTTONSAVEINFO* pbsi = (BUTTONSAVEINFO*)pnmtbs->pCurrent;
|
|
pnmtbs->pCurrent = (LPDWORD)(pbsi+1);
|
|
if (pcm)
|
|
{
|
|
pbsi->guid = pcm->guidButtonGroup;
|
|
pbsi->nCmdID = pcm->nCmdID;
|
|
pbsi->fButtonState = pnmtbs->tbButton.fsState;
|
|
#ifdef DEBUG
|
|
TCHAR szGuid[80];
|
|
SHStringFromGUID(pcm->guidButtonGroup, szGuid, ARRAYSIZE(szGuid));
|
|
TraceMsg(TF_TBCUST, "Saving: %s - %d (%x)", szGuid, pbsi->nCmdID, pbsi->nCmdID);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
ASSERT(pnmtbs->tbButton.fsStyle & BTNS_SEP);
|
|
if (pnmtbs->tbButton.idCommand)
|
|
{
|
|
TraceMsg(TF_TBCUST, "Saving: a separator w/ id %d (%x)", pnmtbs->tbButton.idCommand, pnmtbs->tbButton.idCommand);
|
|
pbsi->guid = CLSID_Separator;
|
|
pbsi->nCmdID = pnmtbs->tbButton.idCommand;
|
|
}
|
|
else
|
|
{
|
|
TraceMsg(TF_TBCUST, "Saving: a separator");
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case TBN_RESTORE:
|
|
{
|
|
NMTBRESTORE* pnmtbr = (NMTBRESTORE*)pnmh;
|
|
if (pnmtbr->iItem == -1)
|
|
{
|
|
// before the restore.
|
|
// take the data, verify the version,
|
|
// fill in the button count, bytes per record
|
|
// initialize the pCurrent to the end of the tb header
|
|
//
|
|
TOOLBARSAVEINFO* ptbsi = (TOOLBARSAVEINFO*)pnmtbr->pCurrent;
|
|
if (ptbsi->cVersion != TBSI_VERSION)
|
|
{
|
|
TraceMsg( TF_WARNING, "TOOLSBANDCLASS::_ToolsCustNotify() - Wrong Toolbar Save Info Version (0x%x vs. 0x%x)!", ptbsi->cVersion, TBSI_VERSION );
|
|
return 1; // abort
|
|
}
|
|
|
|
|
|
// we're actually going to do a restore. initialize our database:
|
|
_BuildButtonDSA();
|
|
|
|
pnmtbr->pCurrent = (LPDWORD)(ptbsi+1);
|
|
pnmtbr->cbBytesPerRecord += sizeof(BUTTONSAVEINFO);
|
|
pnmtbr->cButtons = (pnmtbr->cbData - sizeof(TOOLBARSAVEINFO)) / pnmtbr->cbBytesPerRecord;
|
|
// make sure we did the math right and there are no remainders
|
|
ASSERT(((pnmtbr->cbData - sizeof(TOOLBARSAVEINFO)) % pnmtbr->cbBytesPerRecord) == 0);
|
|
|
|
//this is going to clobber all of the buttons in the current toolbar.
|
|
// since toolbar control just writes over the dwords, we need to go free them now.
|
|
int nButtons = (int) SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0L);
|
|
|
|
for (int nTemp = 0; nTemp < nButtons; nTemp++)
|
|
{
|
|
CMDMAP *pcm = _GetCmdMapByIndex(nTemp);
|
|
_FreeCmdMap(pcm);
|
|
TBBUTTONINFO tbbi;
|
|
tbbi.cbSize = sizeof(tbbi);
|
|
tbbi.lParam = (LPARAM)NULL;
|
|
tbbi.dwMask = TBIF_LPARAM | TBIF_BYINDEX;
|
|
SendMessage(_hwnd, TB_SETBUTTONINFO, nTemp, (LPARAM)&tbbi);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BUTTONSAVEINFO* pbsi = (BUTTONSAVEINFO*)pnmtbr->pCurrent;
|
|
pnmtbr->pCurrent = (LPDWORD)(pbsi+1);
|
|
pnmtbr->tbButton.dwData = 0;
|
|
pnmtbr->tbButton.iString = -1;
|
|
|
|
if (IsEqualGUID(CLSID_Separator, pbsi->guid))
|
|
{
|
|
// restore a separator with a command id
|
|
pnmtbr->tbButton.fsStyle = BTNS_SEP;
|
|
TraceMsg(TF_TBCUST, "Restoring: a separator w/ id %d (%x)", pnmtbr->tbButton.idCommand, pnmtbr->tbButton.idCommand);
|
|
}
|
|
else if (!(pnmtbr->tbButton.fsStyle & BTNS_SEP))
|
|
{
|
|
// Make sure that the button exists for this site
|
|
CMDMAPCUSTOMIZE* pcmc = _GetCmdMapCustomize(&pbsi->guid, pbsi->nCmdID);
|
|
if ((pcmc == NULL) || (SHRestricted(REST_NONLEGACYSHELLMODE) && ((pbsi->nCmdID == TBIDM_BACK) || (pbsi->nCmdID == TBIDM_FORWARD))))
|
|
{
|
|
// Ignore this button
|
|
return 1;
|
|
}
|
|
|
|
CMDMAP* pcm = (CMDMAP*)LocalAlloc(LPTR, sizeof(CMDMAP));
|
|
if (pcm)
|
|
{
|
|
pcm->guidButtonGroup = pbsi->guid;
|
|
pcm->nCmdID = pbsi->nCmdID;
|
|
|
|
#ifdef DEBUG
|
|
TCHAR szGuid[80];
|
|
SHStringFromGUID(pcm->guidButtonGroup, szGuid, ARRAYSIZE(szGuid));
|
|
TraceMsg(TF_TBCUST, "Restoring: %s - %d (%x)", szGuid, pbsi->nCmdID, pbsi->nCmdID);
|
|
#endif
|
|
|
|
// fill in the rest of the info
|
|
pnmtbr->tbButton = pcmc->btn;
|
|
pnmtbr->tbButton.fsState = pbsi->fButtonState;
|
|
pnmtbr->tbButton.dwData = (DWORD_PTR) pcm;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TraceMsg(TF_TBCUST, "Restoring: a separator");
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TBN_ENDADJUST:
|
|
_OnEndCustomize();
|
|
break;
|
|
|
|
case TBN_TOOLBARCHANGE:
|
|
_pcinfo->fDirty = TRUE;
|
|
break;
|
|
|
|
case TBN_INITCUSTOMIZE:
|
|
_OnBeginCustomize((NMTBCUSTOMIZEDLG*)pnmh);
|
|
return TBNRF_HIDEHELP;
|
|
|
|
case TBN_RESET:
|
|
_pcinfo->fDirty = FALSE;
|
|
if (_pctCurrentButtonGroup)
|
|
{
|
|
NMTBCUSTOMIZEDLG *pnm = (NMTBCUSTOMIZEDLG*)pnmh;
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
TCHAR szGuid[GUIDSTR_MAX];
|
|
SHStringFromGUID(_guidCurrentButtonGroup, szGuid, ARRAYSIZE(szGuid));
|
|
SHDeleteValue(HKEY_CURRENT_USER, REGSTR_PATH_TOOLBAR, szGuid);
|
|
|
|
// Default text labels setting should be as follows:
|
|
//
|
|
// If fullscreen mode, any platform -- "No text labels"
|
|
// Else if NT5 -- "Selective text on right"
|
|
// Else -- "Show text labels"
|
|
//
|
|
int idsDefault;
|
|
|
|
if (pitbar->_fTheater)
|
|
idsDefault = IDS_NOTEXTLABELS;
|
|
else if (DEFAULT_LIST_VALUE())
|
|
idsDefault = IDS_PARTIALTEXT;
|
|
else
|
|
idsDefault = IDS_TEXTLABELS;
|
|
|
|
_UpdateTextSettings(idsDefault);
|
|
|
|
HWND hwnd = (HWND) GetProp(pnm->hDlg, SZ_PROP_CUSTDLG);
|
|
if (hwnd)
|
|
{
|
|
// update our dialog's control selection states
|
|
_SetDialogSelections(hwnd, _DefaultToSmallIcons());
|
|
}
|
|
|
|
_RemoveAllButtons();
|
|
_OnEndCustomize();
|
|
if (_pbtnsAdded)
|
|
{
|
|
pitbar->AddButtons(&_guidCurrentButtonGroup, _cBtnsAdded, _pbtnsAdded);
|
|
|
|
#ifdef EDIT_HACK
|
|
// Restore the edit button
|
|
pitbar->_InitEditButtonStyle();
|
|
#endif
|
|
|
|
pitbar->_UpdateToolbar(TRUE);
|
|
}
|
|
else
|
|
{
|
|
return TBNRF_ENDCUSTOMIZE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TBN_QUERYINSERT:
|
|
return TRUE;
|
|
|
|
case TBN_QUERYDELETE:
|
|
return (SendMessage(_hwnd, TB_ISBUTTONHIDDEN,
|
|
(WPARAM) ptbn->tbButton.idCommand,
|
|
(LPARAM) 0)) ? FALSE : TRUE;
|
|
|
|
case TBN_GETBUTTONINFO:
|
|
if (ptbn->iItem < DSA_GetItemCount(_pcinfo->hdsa))
|
|
{
|
|
CMDMAPCUSTOMIZE *pcmc;
|
|
pcmc = (CMDMAPCUSTOMIZE*)DSA_GetItemPtr(_pcinfo->hdsa, ptbn->iItem);
|
|
ptbn->tbButton = pcmc->btn;
|
|
ptbn->tbButton.fsState &= ~TBSTATE_HIDDEN;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
|
|
case TBN_BEGINADJUST:
|
|
if (!_pcinfo || !_pcinfo->fAdjust)
|
|
return 1;
|
|
break;
|
|
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL TOOLSBANDCLASS::_SaveRestoreToolbar(BOOL fSave)
|
|
{
|
|
TBSAVEPARAMS tbsp;
|
|
TCHAR szGuid[GUIDSTR_MAX];
|
|
SHStringFromGUID(_guidCurrentButtonGroup, szGuid, ARRAYSIZE(szGuid));
|
|
|
|
tbsp.hkr = HKEY_CURRENT_USER;
|
|
tbsp.pszSubKey = REGSTR_PATH_TOOLBAR;
|
|
tbsp.pszValueName = szGuid;
|
|
BOOL fRet = BOOLFROMPTR(SendMessage(_hwnd, TB_SAVERESTORE, (WPARAM) fSave, (LPARAM) &tbsp));
|
|
|
|
_FreeCustomizeInfo();
|
|
return fRet;
|
|
}
|
|
|
|
void TOOLSBANDCLASS::_AddMediaBarButton()
|
|
{
|
|
// Wrap this with a reg key to make sure it happens only once
|
|
// then check to make sure it's not already in the thing
|
|
|
|
if (_hwnd && !SHRestricted2W(REST_No_LaunchMediaBar, NULL, 0) && !SHRestricted2(REST_BTN_MEDIABAR, NULL, 0) && CMediaBarUtil::IsWMP7OrGreaterCapable())
|
|
{
|
|
DWORD dwType, dwSize;
|
|
DWORD dwValue = TBBIF_NONE;
|
|
dwSize = sizeof(dwValue);
|
|
if ( (ERROR_SUCCESS==SHGetValue(HKEY_CURRENT_USER, TBBIF_REG_PATH, TBBIF_REG_KEY, &dwType, &dwValue, &dwSize))
|
|
&& (dwType==REG_DWORD)
|
|
&& ((dwValue & TBBIF_MEDIA) != 0))
|
|
{
|
|
return;
|
|
}
|
|
dwValue |= TBBIF_MEDIA;
|
|
SHSetValue(HKEY_CURRENT_USER, TBBIF_REG_PATH, TBBIF_REG_KEY, REG_DWORD, &dwValue, sizeof(dwValue));
|
|
|
|
TBBUTTONINFO tbbi;
|
|
tbbi.cbSize = sizeof(tbbi);
|
|
tbbi.dwMask = TBIF_STATE | TBIF_BYINDEX | TBIF_LPARAM;
|
|
|
|
int iFavs = -1, iHist = -1, iLastTool = -1;
|
|
int iMedia = -1;
|
|
|
|
// lookup MediaBar in current toolbar
|
|
// this could be a previous PersonalBar since the MediaBar reuses the cmdID
|
|
BOOL fFound = FALSE;
|
|
int cntButtons = (int)SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0);
|
|
for (int j = 0; j < cntButtons; j++)
|
|
{
|
|
if (SendMessage(_hwnd, TB_GETBUTTONINFO, j, (LPARAM)&tbbi)!=-1)
|
|
{
|
|
CMDMAP* pcm = (CMDMAP*)tbbi.lParam;
|
|
if (pcm)
|
|
{
|
|
// already present ?
|
|
if (pcm->nCmdID == TBIDM_MEDIABAR)
|
|
{
|
|
fFound = TRUE; // no need to add, only care about updating position in toolbar
|
|
iMedia = j;
|
|
}
|
|
// will try placing after Favorites....
|
|
else if (pcm->nCmdID == TBIDM_FAVORITES)
|
|
{
|
|
iFavs = j;
|
|
iLastTool = j;
|
|
}
|
|
// ... and/or before History
|
|
else if (pcm->nCmdID == TBIDM_HISTORY)
|
|
{
|
|
iHist = j;
|
|
iLastTool = j;
|
|
}
|
|
// ... but at least after last found button in second group
|
|
else if ( (pcm->nCmdID == TBIDM_SEARCH)
|
|
|| (pcm->nCmdID == TBIDM_ALLFOLDERS))
|
|
{
|
|
iLastTool = j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// force-expose MediaBar button at least once
|
|
if (!fFound)
|
|
{
|
|
TBBUTTON tbXBar;
|
|
memcpy((VOID*)&tbXBar, (VOID*)&c_tbExplorer[TBXID_MEDIABAR], sizeof(TBBUTTON));
|
|
|
|
CMDMAP* pcm = (CMDMAP*)LocalAlloc(LPTR, sizeof(CMDMAP));
|
|
if (pcm)
|
|
{
|
|
pcm->guidButtonGroup = CLSID_CommonButtons;
|
|
pcm->nCmdID = c_tbExplorer[TBXID_MEDIABAR].idCommand;
|
|
|
|
tbXBar.idCommand = _nNextCommandID++;
|
|
tbXBar.dwData = (LPARAM)pcm;
|
|
SendMessage(_hwnd, TB_ADDBUTTONS, 1, (LPARAM)&tbXBar);
|
|
}
|
|
}
|
|
|
|
if (iMedia < 0)
|
|
{
|
|
cntButtons = (int)SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0);
|
|
for (j = cntButtons - 1; j >= 0; j--)
|
|
{
|
|
if (SendMessage(_hwnd, TB_GETBUTTONINFO, j, (LPARAM)&tbbi)!=-1)
|
|
{
|
|
CMDMAP* pcm = (CMDMAP*)tbbi.lParam;
|
|
if (pcm)
|
|
{
|
|
// already present ?
|
|
if (pcm->nCmdID == TBIDM_MEDIABAR)
|
|
{
|
|
iMedia = j;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// update position of MediaBar button
|
|
// do we know a preferred position where the MediaBar button should move to?
|
|
if ((iMedia >= 0) && ((iFavs >= 0) || (iHist >= 0) || (iLastTool >= 0)))
|
|
{
|
|
int iNewPos = -1;
|
|
if (iFavs >= 0)
|
|
{
|
|
iNewPos = iFavs;
|
|
}
|
|
else if (iHist >= 0)
|
|
{
|
|
iNewPos = max(iHist - 1, 0);
|
|
}
|
|
else if (iLastTool >= 0)
|
|
{
|
|
iNewPos = iLastTool;
|
|
}
|
|
|
|
if (iNewPos >= 0)
|
|
{
|
|
if (iNewPos < iMedia)
|
|
SendMessage(_hwnd, TB_MOVEBUTTON, iMedia, iNewPos + 1);
|
|
else
|
|
SendMessage(_hwnd, TB_MOVEBUTTON, iMedia, iNewPos);
|
|
|
|
_SaveRestoreToolbar(TRUE);
|
|
_RecalcButtonWidths();
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
int TOOLSBANDCLASS::_CommandFromIndex(UINT uIndex)
|
|
{
|
|
TBBUTTONINFO tbbi;
|
|
tbbi.cbSize = sizeof(tbbi);
|
|
tbbi.dwMask = TBIF_COMMAND | TBIF_BYINDEX;
|
|
SendMessage(_hwnd, TB_GETBUTTONINFO, uIndex, (LPARAM)&tbbi);
|
|
return tbbi.idCommand;
|
|
}
|
|
|
|
// _btb._ConvertCmd()
|
|
// This is used to covert a external Command ID to an internal ID or vice versa
|
|
// If we are converting to an external ID then
|
|
// call with pguidButtonGroup == NULL (to external: pguidButtonGroup == NULL)
|
|
// otherwise call with the external button group GUID (to internal: pguidOut == NULL)
|
|
HRESULT TOOLSBANDCLASS::_ConvertCmd(const GUID* pguidButtonGroup, UINT id, GUID* pguidOut, UINT * pid)
|
|
{
|
|
HRESULT hres = E_FAIL;
|
|
BOOL fToInternal = (bool) (pguidButtonGroup);
|
|
|
|
ASSERT((pguidButtonGroup == NULL) ^ (pguidOut == NULL));
|
|
|
|
// First look for the command
|
|
if (fToInternal)
|
|
{
|
|
if (_hwnd)
|
|
{
|
|
int nCount = (int) SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0);
|
|
for (int i = 0; i < nCount; i++)
|
|
{
|
|
CMDMAP *pcm = _GetCmdMapByIndex(i);
|
|
|
|
if (pcm)
|
|
{
|
|
// loop through the command mapping structures until we
|
|
// find this guid and id
|
|
if (IsEqualGUID(pcm->guidButtonGroup, *pguidButtonGroup) &&
|
|
id == pcm->nCmdID)
|
|
{
|
|
*pid = _CommandFromIndex(i);
|
|
hres = S_OK;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// going from toolbar id to commandtarget info
|
|
CMDMAP *pcm = _GetCmdMapByID(id);
|
|
if (pcm)
|
|
{
|
|
*pguidOut = pcm->guidButtonGroup;
|
|
*pid = pcm->nCmdID;
|
|
hres = S_OK;
|
|
}
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
|
|
|
|
LRESULT CInternetToolbar::_AddBitmapFromForeignModule(UINT uiGetMSG, UINT uiSetMSG, UINT uiCount, HINSTANCE hinst, UINT_PTR nID, COLORREF rgbMask)
|
|
{
|
|
HBITMAP hBMPRaw = NULL, hBMPFixedUp = NULL;
|
|
HBITMAP * phBmp = &hBMPFixedUp;
|
|
BITMAP bmp;
|
|
HIMAGELIST himlTemp;
|
|
LRESULT lRes = 1L;
|
|
BOOL fOk = TRUE;
|
|
HDC dc = NULL, dcMemSrc = NULL, dcMemDest = NULL;
|
|
HBITMAP hbmpOldDest = NULL, hbmpOldSrc = NULL;
|
|
int cxOrg = 0;
|
|
int xDest = 0, yDest = 0;
|
|
RECT rect = {0,0,0,0};
|
|
HBRUSH hbr = NULL;
|
|
|
|
// What if hinst == NULL? That means that nID is really an HBITMAP
|
|
ASSERT( hinst != NULL );
|
|
|
|
if (!(hBMPRaw = LoadBitmap(hinst, MAKEINTRESOURCE(nID))))
|
|
return 0L;
|
|
|
|
fOk = (BOOL)(GetObject(hBMPRaw, sizeof(BITMAP), &bmp) != 0);
|
|
|
|
// Check is the size is OK
|
|
if (fOk && (bmp.bmWidth != (LONG)(g_iToolBarLargeIconWidth * uiCount)) || (bmp.bmHeight != (LONG)g_iToolBarLargeIconHeight) )
|
|
{
|
|
int cxBmp;
|
|
int cyBmp;
|
|
|
|
if (g_fSmallIcons)
|
|
{
|
|
cxBmp = TB_SMBMP_CX;
|
|
cyBmp = TB_SMBMP_CY;
|
|
}
|
|
else
|
|
{
|
|
cxBmp = g_iToolBarLargeIconWidth;
|
|
cyBmp = g_iToolBarLargeIconHeight;
|
|
}
|
|
|
|
// If the height is 15, the we assume that this is one of the old bitmaps therefore
|
|
// the width is 16. We cannot rely on the (bmp.bmWidth / uiCount) because some apps
|
|
// like SecureFile give us a bitmap 192 wide and say that there are 10 glyphs in it.
|
|
if (bmp.bmHeight == 15)
|
|
cxOrg = 16;
|
|
else
|
|
cxOrg = bmp.bmWidth / (uiCount ? uiCount : 1);
|
|
|
|
if (rgbMask)
|
|
fOk = (BOOL)((hbr = CreateSolidBrush(rgbMask))!= NULL);
|
|
|
|
if (fOk)
|
|
fOk = (BOOL)((dc = GetDC(_btb._hwnd)) != NULL);
|
|
|
|
if (fOk)
|
|
fOk = (BOOL)((hBMPFixedUp = CreateCompatibleBitmap(dc, (cxBmp * uiCount), cyBmp)) != NULL);
|
|
|
|
if (fOk)
|
|
fOk = (BOOL)((dcMemSrc = CreateCompatibleDC(dc)) != NULL);
|
|
|
|
if (fOk)
|
|
fOk = (BOOL)((dcMemDest = CreateCompatibleDC(dc)) != NULL);
|
|
|
|
if (!fOk)
|
|
goto Error;
|
|
|
|
hbmpOldSrc = (HBITMAP)SelectObject(dcMemSrc, hBMPRaw);
|
|
hbmpOldDest = (HBITMAP)SelectObject(dcMemDest, hBMPFixedUp);
|
|
|
|
rect.right = (cxBmp * uiCount);
|
|
rect.bottom = cyBmp;
|
|
if (rgbMask)
|
|
FillRect(dcMemDest, &rect, hbr);
|
|
|
|
for (UINT n = 0; n < uiCount; n++)
|
|
{
|
|
|
|
int cxCopy;
|
|
int cyCopy;
|
|
|
|
xDest = (n * cxBmp);
|
|
if (cxOrg < cxBmp)
|
|
{
|
|
// if the bitmap is too small, we need to center it.
|
|
// the amount we copy is the full bitmap
|
|
cxCopy = cxOrg;
|
|
xDest += ((cxBmp - cxOrg) / 2);
|
|
}
|
|
else
|
|
{
|
|
// if the bitmap is big enough, we align it to top left and
|
|
// we strecth(shrink) it down to fit
|
|
cxCopy = cxBmp;
|
|
}
|
|
|
|
if (bmp.bmHeight < cyBmp)
|
|
{
|
|
cyCopy = bmp.bmHeight;
|
|
yDest = ((cyBmp - bmp.bmHeight) / 2);
|
|
}
|
|
else
|
|
{
|
|
cyCopy = cyBmp;
|
|
yDest = 0;
|
|
}
|
|
StretchBlt(dcMemDest, xDest, yDest, cxOrg, bmp.bmHeight,
|
|
dcMemSrc, (cxOrg * n), 0, cxCopy, cyCopy, SRCCOPY);
|
|
|
|
}
|
|
|
|
SelectObject(dcMemDest, hbmpOldDest);
|
|
SelectObject(dcMemSrc, hbmpOldSrc);
|
|
}
|
|
else
|
|
phBmp = &hBMPRaw;
|
|
|
|
if (!(himlTemp = (HIMAGELIST)SendMessage(_btb._hwnd, uiGetMSG, 0, 0L)))
|
|
{
|
|
TraceMsg(DM_ERROR, "CITBar::_AddBitmapFromForeignModule Failed - uiGetMSG SendMessage Failure");
|
|
fOk = FALSE;
|
|
goto Error;
|
|
}
|
|
|
|
if (rgbMask)
|
|
lRes = ImageList_AddMasked(himlTemp, (HBITMAP)*phBmp, rgbMask);
|
|
else
|
|
lRes = ImageList_Add(himlTemp, (HBITMAP)*phBmp, NULL);
|
|
|
|
if (lRes == -1)
|
|
{
|
|
TraceMsg(DM_ERROR, "CITBar::_AddBitmapFromForeignModule Failed - lRes == -1");
|
|
fOk = FALSE;
|
|
goto Error;
|
|
}
|
|
|
|
|
|
if (!SendMessage(_btb._hwnd, uiSetMSG, 0, (LPARAM)himlTemp))
|
|
{
|
|
TraceMsg(DM_ERROR, "CITBar::_AddBitmapFromForeignModule Failed - uiSetMSG SendMessage Failed");
|
|
fOk = FALSE;
|
|
goto Error;
|
|
}
|
|
|
|
Error:
|
|
if (hBMPFixedUp)
|
|
DeleteObject(hBMPFixedUp);
|
|
|
|
if (hBMPRaw)
|
|
DeleteObject(hBMPRaw);
|
|
|
|
if (dc)
|
|
ReleaseDC(_btb._hwnd, dc);
|
|
|
|
if (dcMemSrc)
|
|
DeleteDC(dcMemSrc);
|
|
|
|
if (dcMemDest)
|
|
DeleteDC(dcMemDest);
|
|
|
|
if (hbr)
|
|
DeleteObject(hbr);
|
|
|
|
if (!fOk)
|
|
lRes = 0L;
|
|
|
|
return lRes;
|
|
}
|
|
|
|
#define VERY_HIGH_NUMBER 4000
|
|
HRESULT CInternetToolbar::_LoadDefaultSettings()
|
|
{
|
|
memset(&_cs, 0, sizeof(COOLBARSAVE));
|
|
_cs.cbVer = CBS_VERSION;
|
|
|
|
_cs.bs[0].wID = CBIDX_MENU;
|
|
_cs.bs[0].cx = VERY_HIGH_NUMBER;
|
|
|
|
_cs.bs[1].wID = CBIDX_BRAND;
|
|
|
|
_cs.bs[2].wID = CBIDX_TOOLS;
|
|
_cs.bs[2].cx = VERY_HIGH_NUMBER;
|
|
_cs.bs[2].fStyle = RBBS_BREAK;
|
|
|
|
_cs.bs[3].wID = CBIDX_ADDRESS;
|
|
_cs.bs[3].cx = VERY_HIGH_NUMBER;
|
|
_cs.bs[3].fStyle = RBBS_BREAK;
|
|
|
|
_cs.bs[4].wID = CBIDX_LINKS;
|
|
|
|
if (!_fInitialPidlIsWeb)
|
|
{
|
|
// we're in shell view, or we're rooted. for perf, don't bother creating the links band.
|
|
if (IsOS(OS_WHISTLERORGREATER) && (IsOS(OS_PERSONAL)))
|
|
{
|
|
_cs.uiVisible = (VBF_MENU | VBF_TOOLS | VBF_BRAND);
|
|
}
|
|
else
|
|
{
|
|
_cs.uiVisible = (VBF_MENU | VBF_TOOLS | VBF_ADDRESS | VBF_BRAND);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// web page
|
|
_cs.uiVisible = (VBF_MENU | VBF_TOOLS | VBF_ADDRESS | VBF_LINKS | VBF_BRAND);
|
|
}
|
|
|
|
_cs.clsidVerticalBar = GUID_NULL;
|
|
_cs.clsidHorizontalBar = GUID_NULL;
|
|
_cs.fNoText = FALSE;
|
|
_cs.fList = DEFAULT_LIST_VALUE();
|
|
|
|
_fUsingDefaultBands = TRUE;
|
|
|
|
return(NOERROR);
|
|
}
|
|
|
|
typedef struct tagCOOLBARSAVEv12 // IE4
|
|
{
|
|
UINT cbVer;
|
|
UINT uiMaxTBWidth;
|
|
UINT uiMaxQLWidth;
|
|
#ifdef UNIX
|
|
BITBOOL fUnUsed : 28; // unused
|
|
#endif
|
|
BOOL fVertical : 1; // The bar is oriented vertically
|
|
BOOL fNoText :1; // "NoText"
|
|
BOOL fAutoHide : 1; // Auto hide toolbar in theater mode
|
|
BOOL fStatusBar : 1; // Status bar in theater mode
|
|
BOOL fSaveInShellIntegrationMode : 1; // Did we save in shell
|
|
UINT uiVisible; // "Visible bands"
|
|
UINT cyRebar;
|
|
BANDSAVE bs[5];
|
|
} COOLBARSAVEv12;
|
|
|
|
typedef struct tagCOOLBARSAVEv15 // IE5 Beta2
|
|
{
|
|
UINT cbVer;
|
|
UINT uiMaxTBWidth;
|
|
UINT uiMaxQLWidth;
|
|
#ifdef UNIX
|
|
BITBOOL fUnUsed : 28; // unused
|
|
#endif
|
|
BITBOOL fVertical : 1; // The bar is oriented vertically
|
|
BITBOOL fNoText :1; // "NoText"
|
|
BITBOOL fList : 1; // toolbar is TBSTYLE_LIST (text on right) + TBSTYLE_EX_MIXEDBUTTONS
|
|
BITBOOL fAutoHide : 1; // Auto hide toolbar in theater mode
|
|
BITBOOL fStatusBar : 1; // Status bar in theater mode
|
|
BITBOOL fSaveInShellIntegrationMode : 1; // Did we save in shell integration mode?
|
|
UINT uiVisible; // "Visible bands"
|
|
UINT cyRebar;
|
|
BANDSAVE bs[5];
|
|
CLSID clsidVerticalBar; //clsid of bar persisted within vertical band
|
|
CLSID clsidHorizontalBar;
|
|
} COOLBARSAVEv15;
|
|
|
|
#define CB_V12 (sizeof(COOLBARSAVEv12))
|
|
#define CB_V13 (sizeof(COOLBARSAVEv15))
|
|
#define CB_V14 CB_V13 // 14: added fList:1 (in middle!)
|
|
#define CB_V15 CB_V14 // 15: new rbbi.fStyle semantics
|
|
#define CB_V17 (sizeof(COOLBARSAVE))
|
|
|
|
HRESULT CInternetToolbar::_LoadUpgradeSettings(ULONG cbRead)
|
|
{
|
|
// If we shipped with the CBS_VERSION you're incrementing, you need
|
|
// to add upgrade code here for that version, then update this assertion.
|
|
COMPILETIME_ASSERT(CBS_VERSION == 17);
|
|
|
|
// Double-check our size calculations.
|
|
#ifndef UNIX
|
|
COMPILETIME_ASSERT(CB_V12 == (6 * sizeof(UINT) + CBIDX_LAST * sizeof(BANDSAVE)));
|
|
#endif
|
|
COMPILETIME_ASSERT(CB_V12 == (CB_V15 - sizeof(CLSID) * 2));
|
|
COMPILETIME_ASSERT(CB_V13 == (CB_V12 + 2 * sizeof(CLSID)));
|
|
COMPILETIME_ASSERT(CB_V14 == (CB_V13 + 0));
|
|
COMPILETIME_ASSERT(CB_V15 == (CB_V14 + 0));
|
|
COMPILETIME_ASSERT(CB_V17 == (CB_V15 + (MAXEXTERNALBANDS * sizeof(BANDSAVE)) + (MAXEXTERNALBANDS * sizeof(CLSID))));
|
|
|
|
// If the stream was shorter than the version data field, there's nothing we can do.
|
|
if (cbRead < sizeof(_cs.cbVer))
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Check to see if the version is one we know about and that the stream
|
|
// size is the same as that version's structure size.
|
|
if (!((_cs.cbVer == 12 && cbRead == CB_V12) || // IE4
|
|
(_cs.cbVer == 13 && cbRead == CB_V13) || // ?
|
|
(_cs.cbVer == 14 && cbRead == CB_V14) || // ?
|
|
(_cs.cbVer == 15 && cbRead == CB_V15))) // IE5 Beta2
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
TraceMsg(DM_WARNING, "citb._lus: try upgrade %d->%d", _cs.cbVer, CBS_VERSION);
|
|
|
|
// Make a scratch copy of _cs so we don't worry about overwriting
|
|
// parts of _cs we need to read later.
|
|
COOLBARSAVE cs = _cs;
|
|
|
|
if (_cs.cbVer == 12)
|
|
{
|
|
// clsidVerticalBar/clsidHorizontalBar weren't a part
|
|
// of the structure until v13
|
|
cs.clsidVerticalBar = GUID_NULL;
|
|
cs.clsidHorizontalBar = GUID_NULL;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(_cs.cbVer < 16);
|
|
|
|
// Band array (bs) grew in v16 to include external bands, so
|
|
// clsidVerticalBar/clsidHorizontalBar were at a different offset.
|
|
COOLBARSAVEv15 *pv15 = (COOLBARSAVEv15 *) &_cs;
|
|
cs.clsidVerticalBar = pv15->clsidVerticalBar;
|
|
cs.clsidHorizontalBar = pv15->clsidHorizontalBar;
|
|
cs.bs[CBIDX_LAST].wID = 0xFFFFFFFF;
|
|
}
|
|
|
|
if (InRange(_cs.cbVer, 12, 13))
|
|
{
|
|
// fList was inserted into the middle of the bitbool list in v14.
|
|
// Copy the displaced bitbools and initialize fList.
|
|
COOLBARSAVEv12 *pv12 = (COOLBARSAVEv12 *) &_cs;
|
|
cs.fAutoHide = pv12->fAutoHide;
|
|
cs.fStatusBar = pv12->fStatusBar;
|
|
cs.fSaveInShellIntegrationMode = pv12->fSaveInShellIntegrationMode;
|
|
cs.fList = DEFAULT_LIST_VALUE();
|
|
}
|
|
|
|
// Force FALSE as no longer support vertical itbar mode.
|
|
cs.fVertical = FALSE;
|
|
|
|
// Strip off any invalid visible band bits
|
|
cs.uiVisible &= VBF_VALID;
|
|
|
|
// Set current version and copy scratch cs back to _cs
|
|
cs.cbVer = CBS_VERSION;
|
|
_cs = cs;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::_LoadDefaultWidths()
|
|
{
|
|
// If there was no max width set for the QL bar or the Toolbar, then
|
|
// before we use the default, check it the localization people wanted to
|
|
// increase the width. The RC file string range from '0' to '9'
|
|
TCHAR szScratch[16];
|
|
UINT uiExtraWidth = 0;
|
|
|
|
if (GetSystemMetrics(SM_CXSCREEN) < 650)
|
|
{
|
|
MLLoadString(IDS_TB_WIDTH_EXTRA_LORES, szScratch, ARRAYSIZE(szScratch));
|
|
_uiMaxTBWidth = MAX_TB_WIDTH_LORES;
|
|
}
|
|
else
|
|
{
|
|
MLLoadString(IDS_TB_WIDTH_EXTRA_HIRES, szScratch, ARRAYSIZE(szScratch));
|
|
_uiMaxTBWidth = MAX_TB_WIDTH_HIRES;
|
|
}
|
|
_uiMaxTBWidth += StrToInt(szScratch) * WIDTH_FACTOR;
|
|
|
|
|
|
return(NOERROR);
|
|
}
|
|
|
|
BOOL IsClsidInHKCR(REFGUID pclsid)
|
|
{
|
|
HKEY hkeyResult;
|
|
|
|
if (SHRegGetCLSIDKeyW(pclsid, NULL, FALSE, FALSE, &hkeyResult) == ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hkeyResult);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
typedef struct tagCOOLBARSAVEv2 // IE3
|
|
{
|
|
UINT cbVer;
|
|
UINT uiMaxTBWidth;
|
|
UINT uiMaxQLWidth;
|
|
BOOL fVertical; // The bar is oriented vertically
|
|
BANDSAVE bs[4];
|
|
} COOLBARSAVEv2;
|
|
|
|
#define VBF_VALIDv2 (VBF_TOOLS | VBF_ADDRESS | VBF_LINKS)
|
|
|
|
void CInternetToolbar::_TryLoadIE3Settings()
|
|
{
|
|
HKEY hKey;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegKeyCoolbar, 0, KEY_QUERY_VALUE, &hKey))
|
|
{
|
|
COOLBARSAVEv2 cbv2;
|
|
DWORD dwcbData = sizeof(cbv2);
|
|
if (SHQueryValueEx(hKey, TEXT("Layout"), NULL, NULL, (LPBYTE)&cbv2, &dwcbData) == ERROR_SUCCESS)
|
|
{
|
|
_cs.uiMaxTBWidth = cbv2.uiMaxTBWidth;
|
|
_cs.uiMaxQLWidth = cbv2.uiMaxQLWidth;
|
|
// FEATURE: todo -- read in bs field too; need to do some conversions as
|
|
// CBIDX_ numbers were zero-based and there was no menuband in IE3.
|
|
}
|
|
|
|
BOOL fNoText;
|
|
dwcbData = sizeof(fNoText);
|
|
if (SHQueryValueEx(hKey, TEXT("NoText"), NULL, NULL, (LPBYTE)&fNoText, &dwcbData) == ERROR_SUCCESS)
|
|
{
|
|
// Set the no-text flag.
|
|
_cs.fNoText = BOOLIFY(fNoText);
|
|
}
|
|
|
|
UINT uiVisible;
|
|
dwcbData = sizeof(uiVisible);
|
|
if (SHQueryValueEx(hKey, TEXT("VisibleBands"), NULL, NULL, (LPBYTE)&uiVisible, &dwcbData) == ERROR_SUCCESS)
|
|
{
|
|
// Set the visible bands, changing only the ones that IE3 knew about.
|
|
_cs.uiVisible = (_cs.uiVisible &~ VBF_VALIDv2) | (uiVisible & VBF_VALIDv2);
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
VOID CInternetToolbar::_UpdateLocking()
|
|
{
|
|
// if we have no gripper then turn them off
|
|
BANDSITEINFO bsinfo;
|
|
bsinfo.dwMask = BSIM_STYLE;
|
|
bsinfo.dwStyle = BSIS_LEFTALIGN | (_fLockedToolbar ? BSIS_NOGRIPPER : 0);
|
|
_bs.SetBandSiteInfo(&bsinfo);
|
|
_bs._UpdateAllBands(FALSE, TRUE);
|
|
ResizeBorderDW(NULL, NULL, FALSE);
|
|
}
|
|
|
|
HRESULT CInternetToolbar::Load(IStream *pstm)
|
|
{
|
|
ULONG ulRead;
|
|
|
|
//Read from the given stream and initialize the Toolbar data!
|
|
|
|
_fLoading = TRUE;
|
|
HRESULT hr = pstm->Read(&_cs, sizeof(COOLBARSAVE), &ulRead);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (ulRead != sizeof(COOLBARSAVE) || _cs.cbVer != CBS_VERSION)
|
|
{
|
|
hr = _LoadUpgradeSettings(ulRead);
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
_LoadDefaultSettings();
|
|
}
|
|
|
|
ASSERT(_cs.uiVisible & VBF_MENU);
|
|
// make sure that the settings include a menu
|
|
_cs.uiVisible |= VBF_MENU;
|
|
|
|
_LoadDefaultWidths();
|
|
hr = _CreateBands();
|
|
|
|
_UpdateLocking();
|
|
|
|
//if in web view, show the last visible browser bars too
|
|
if (!_fShellView)
|
|
{
|
|
VARIANT varOut = {0};
|
|
varOut.vt = VT_I4;
|
|
|
|
if (!IsEqualGUID(_cs.clsidVerticalBar, GUID_NULL) && IsClsidInHKCR(_cs.clsidVerticalBar))
|
|
{
|
|
BOOL fSearch = IsEqualGUID(_cs.clsidVerticalBar, CLSID_SearchBand)
|
|
|| IsEqualGUID(_cs.clsidVerticalBar, CLSID_FileSearchBand);
|
|
|
|
WCHAR wsz[GUIDSTR_MAX];
|
|
SHStringFromGUID((const CLSID)_cs.clsidVerticalBar, wsz, ARRAYSIZE(wsz));
|
|
|
|
#ifdef UNIX
|
|
// IEUNIX: Donot persist/load MsgBand
|
|
if (!IsEqualGUID(_cs.clsidVerticalBar, CLSID_MsgBand))
|
|
#endif
|
|
{
|
|
if (!fSearch)
|
|
{
|
|
VARIANT varClsid;
|
|
varClsid.vt = VT_BSTR;
|
|
varClsid.bstrVal = wsz;
|
|
|
|
IUnknown_Exec(_pbs2, &CGID_ShellDocView, SHDVID_SHOWBROWSERBAR, 1, &varClsid, &varOut);
|
|
}
|
|
else
|
|
{
|
|
// if it's the search band, must be shown in this way to get correct search
|
|
VARIANTARG var;
|
|
var.vt = VT_I4;
|
|
var.lVal = -1;
|
|
|
|
Exec(&CLSID_CommonButtons, TBIDM_SEARCH, 0, NULL, &var);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!IsEqualGUID(_cs.clsidHorizontalBar, GUID_NULL) && IsClsidInHKCR(_cs.clsidHorizontalBar))
|
|
{
|
|
WCHAR wsz[GUIDSTR_MAX];
|
|
SHStringFromGUID((const CLSID)_cs.clsidHorizontalBar, wsz, ARRAYSIZE(wsz));
|
|
|
|
VARIANT varClsid;
|
|
varClsid.vt = VT_BSTR;
|
|
varClsid.bstrVal = wsz;
|
|
|
|
IUnknown_Exec(_pbs2, &CGID_ShellDocView, SHDVID_SHOWBROWSERBAR, 1, &varClsid, &varOut);
|
|
}
|
|
}
|
|
_fLoading = FALSE;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//see APPHACK note below
|
|
const GUID CLSID_AlexaVert = { 0xBA0B386CL, 0x7143, 0x11d1, 0xba, 0x8c, 0x00, 0x60, 0x08, 0x27, 0x87, 0x8d };
|
|
const GUID CLSID_AlexaHorz = { 0xBA0B386EL, 0x7143, 0x11d1, 0xba, 0x8c, 0x00, 0x60, 0x08, 0x27, 0x87, 0x8d };
|
|
|
|
void CInternetToolbar::_GetVisibleBrowserBar(UINT idBar, CLSID *pclsidOut)
|
|
{
|
|
*pclsidOut = GUID_NULL;
|
|
|
|
ASSERT(idBar == IDBAR_VERTICAL || idBar == IDBAR_HORIZONTAL);
|
|
|
|
IDockingWindowFrame *psb;
|
|
if (_psp && SUCCEEDED(_psp->QueryService(SID_STopLevelBrowser, IID_PPV_ARG(IDockingWindowFrame, &psb))))
|
|
{
|
|
IDeskBar* pdb;
|
|
|
|
if ( (IDBAR_VERTICAL == idBar && (SUCCEEDED(psb->FindToolbar(INFOBAR_TBNAME, IID_PPV_ARG(IDeskBar, &pdb))) && pdb)) ||
|
|
(IDBAR_HORIZONTAL == idBar && (SUCCEEDED(psb->FindToolbar(COMMBAR_TBNAME, IID_PPV_ARG(IDeskBar, &pdb))) && pdb)) )
|
|
{
|
|
VARIANT varClsid = {0};
|
|
|
|
if (SUCCEEDED(IUnknown_Exec(pdb, &CGID_DeskBarClient, DBCID_CLSIDOFBAR, 1, NULL, &varClsid)))
|
|
{
|
|
if (varClsid.vt == VT_BSTR)
|
|
{
|
|
GUIDFromString(varClsid.bstrVal, pclsidOut);
|
|
VariantClear(&varClsid);
|
|
}
|
|
|
|
//APPHACK
|
|
// Alexa 3.0 has some code so that their explorer bar persists that works in ie4. however, when ie5
|
|
// persists them, they don't handle the case where the main page has not finished loading yet, which
|
|
// causes them to fault on launch of the browser. see IE5 55895.
|
|
if ( (IDBAR_VERTICAL == idBar && (IsEqualGUID(*pclsidOut, CLSID_AlexaVert))) ||
|
|
(IDBAR_HORIZONTAL == idBar && (IsEqualGUID(*pclsidOut, CLSID_AlexaHorz))) )
|
|
{
|
|
*pclsidOut = GUID_NULL;
|
|
}
|
|
//END APPHACK
|
|
}
|
|
|
|
pdb->Release();
|
|
}
|
|
psb->Release();
|
|
}
|
|
}
|
|
|
|
void CInternetToolbar::_BuildSaveStruct(COOLBARSAVE* pcs)
|
|
{
|
|
REBARBANDINFO rbbi;
|
|
RECT rc;
|
|
static BOOL fBrowserOnly = (WhichPlatform() != PLATFORM_INTEGRATED);
|
|
|
|
//Save into the given stream!
|
|
memset(pcs, 0, sizeof(COOLBARSAVE));
|
|
pcs->cbVer = CBS_VERSION;
|
|
|
|
// Browser Only can't load Shell Integrated streams because of the Favorites
|
|
// shell extension created pidls unreadable by browser only which doesn't have the Favorites ShellExt
|
|
pcs->fSaveInShellIntegrationMode = !fBrowserOnly;
|
|
|
|
GetWindowRect(_bs._hwnd, &rc);
|
|
pcs->cyRebar = RECTHEIGHT(rc);
|
|
//Save the new fields.
|
|
pcs->fAutoHide = _fAutoHide;
|
|
pcs->fNoText = _fCompressed;
|
|
pcs->fList = IS_LIST_STYLE(_btb._hwnd);
|
|
pcs->uiVisible = _nVisibleBands;
|
|
|
|
//only persist the visible bars for web view
|
|
if (!_fShellView)
|
|
{
|
|
_GetVisibleBrowserBar(IDBAR_VERTICAL, &pcs->clsidVerticalBar);
|
|
_GetVisibleBrowserBar(IDBAR_HORIZONTAL, &pcs->clsidHorizontalBar);
|
|
}
|
|
//else pcs->clsid*Bar nulled out by memset above
|
|
|
|
LRESULT lStyle = GetWindowLong(_bs._hwnd, GWL_STYLE);
|
|
pcs->fVertical = BOOLIFY(lStyle & CCS_VERT);
|
|
|
|
pcs->uiMaxTBWidth = _uiMaxTBWidth;
|
|
|
|
rbbi.cbSize = sizeof(REBARBANDINFO);
|
|
rbbi.fMask = RBBIM_STYLE | RBBIM_SIZE | RBBIM_ID;
|
|
int icBands = (int) SendMessage( _bs._hwnd, RB_GETBANDCOUNT, 0, 0 );
|
|
for (int i = 0; i < icBands; i++)
|
|
{
|
|
pcs->bs[i].wID = 0xFFFFFFFF;
|
|
if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
|
|
{
|
|
if (rbbi.wID < CBANDSMAX)
|
|
{
|
|
// desk band objects have the choice of not saving there visibility
|
|
// state
|
|
BANDITEMDATA *pbid = _bs._GetBandItem( i );
|
|
UINT uiMask = rbbi.wID <= CBIDX_LAST ? ( 1 << (rbbi.wID - 1) ) : EXTERNALBAND_VBF_BIT(rbbi.wID - CBIDX_LAST-1);
|
|
if (pbid && pbid->pdb && (pcs->uiVisible & uiMask))
|
|
{
|
|
OLECMD cmd;
|
|
cmd.cmdID = CITIDM_DISABLEVISIBILITYSAVE;
|
|
cmd.cmdf = 0;
|
|
IUnknown_QueryStatus( pbid->pdb, &CGID_PrivCITCommands, 1, &cmd, NULL );
|
|
if ( cmd.cmdf & OLECMDF_ENABLED )
|
|
{
|
|
pcs->uiVisible &= ~uiMask;
|
|
rbbi.fStyle |= RBBS_HIDDEN;
|
|
}
|
|
}
|
|
pcs->bs[i].fStyle = rbbi.fStyle;
|
|
pcs->bs[i].cx = rbbi.cx;
|
|
pcs->bs[i].wID = rbbi.wID;
|
|
if (IS_EXTERNALBAND(rbbi.wID))
|
|
{
|
|
pcs->aclsidExternalBands[MAP_TO_EXTERNAL(rbbi.wID)] = _rgebi[MAP_TO_EXTERNAL(rbbi.wID)].clsid;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Query CShellBrowser for status bar state
|
|
VARIANTARG v = { 0 };
|
|
v.vt = VT_I4;
|
|
IUnknown_Exec(_ptbsite, &CGID_ShellBrowser, FCIDM_GETSTATUSBAR,
|
|
0, NULL, &v);
|
|
pcs->fStatusBar = v.lVal;
|
|
}
|
|
|
|
typedef struct tagCLSID_BANDTYPE
|
|
{
|
|
const CLSID * pclsid;
|
|
DWORD dwBandID;
|
|
} CLSID_BANDTYPE;
|
|
|
|
CLSID_BANDTYPE c_CLSIDsToSave[] =
|
|
{
|
|
{&CLSID_AddressBand, CBIDX_ADDRESS},
|
|
{&CLSID_QuickLinks, CBIDX_LINKS},
|
|
};
|
|
|
|
HRESULT CInternetToolbar::Save(IStream *pstm, BOOL fClearDirty)
|
|
{
|
|
COOLBARSAVE cs;
|
|
HRESULT hr = S_FALSE;
|
|
|
|
// avoid the hit of saving when we are still loading. State will not have
|
|
// changed, at least not enough to justify saving, until after we are loaded.
|
|
if (_fLoading)
|
|
return S_OK;
|
|
|
|
// Check the dirty bit to see if we need to save.
|
|
if (!_fDirty)
|
|
return S_OK;
|
|
|
|
// if we failed during creation, our current state isnt good enough to persist.
|
|
if (_fDontSave)
|
|
return S_OK;
|
|
|
|
ASSERT(!_fTheater);
|
|
_BuildSaveStruct(&cs);
|
|
|
|
if(SUCCEEDED(hr = pstm->Write(&cs, sizeof(COOLBARSAVE), NULL)) && fClearDirty)
|
|
_fDirty = FALSE;
|
|
|
|
REBARBANDINFO rbbi;
|
|
rbbi.cbSize = sizeof(REBARBANDINFO);
|
|
rbbi.fMask = RBBIM_ID;
|
|
|
|
int icBands = (int) SendMessage( _bs._hwnd, RB_GETBANDCOUNT, 0, 0 );
|
|
for (int i = 0; i < icBands; i++)
|
|
{
|
|
if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
|
|
{
|
|
if ((rbbi.wID == CBIDX_ADDRESS) || (rbbi.wID == CBIDX_LINKS) || IS_EXTERNALBAND(rbbi.wID))
|
|
{
|
|
BANDITEMDATA *pbid = _bs._GetBandItem( i );
|
|
if (pbid && pbid->pdb)
|
|
{
|
|
CLSID clsid;
|
|
IPersistStream *pStream;
|
|
if (SUCCEEDED(pbid->pdb->QueryInterface(IID_PPV_ARG(IPersistStream, &pStream))))
|
|
{
|
|
pStream->GetClassID( &clsid );
|
|
IStream * pstm;
|
|
TCHAR szGUID[MAX_PATH];
|
|
SHStringFromGUID( clsid, szGUID, ARRAYSIZE(szGUID) );
|
|
pstm = GetRegStream( _fInitialPidlIsWeb, szGUID, STGM_WRITE | STGM_CREATE );
|
|
if (pstm)
|
|
{
|
|
HRESULT hrInternal = _bs.SaveToStreamBS(pbid->pdb, pstm);
|
|
|
|
// Only return Success values
|
|
if (SUCCEEDED(hrInternal))
|
|
hr = S_OK;
|
|
pstm->Release();
|
|
}
|
|
pStream->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT CInternetToolbar::InitNew(void)
|
|
{
|
|
// This shouldn't get called if Load has already been called, so assert
|
|
// that _cs is uninitialized.
|
|
ASSERT(_cs.cbVer == 0);
|
|
|
|
_LoadDefaultSettings();
|
|
|
|
// Look for any IE3 settings and override defaults with those. (IE3
|
|
// wrote structures directly to registry, rather than via IPersistStream).
|
|
_TryLoadIE3Settings();
|
|
|
|
_LoadDefaultWidths();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
BOOL CInternetToolbar::_SendToToolband(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres)
|
|
{
|
|
return _bs._SendToToolband(hwnd, uMsg, wParam, lParam, plres);
|
|
}
|
|
|
|
|
|
HRESULT CInternetToolbar::IsDirty(void)
|
|
{
|
|
if (_fDirty && !_fLoading)
|
|
return S_OK;
|
|
else
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
HRESULT CInternetToolbar::QueryService(REFGUID guidService,
|
|
REFIID riid, void **ppvObj)
|
|
{
|
|
HRESULT hres = E_NOTIMPL;
|
|
|
|
if (IsEqualIID(guidService, SID_IBandProxy))
|
|
{
|
|
hres = QueryService_SID_IBandProxy(SAFECAST(_ptbsitect, IUnknown *), riid, &_pbp, ppvObj);
|
|
if(!_pbp)
|
|
{
|
|
// We need to create it ourselves since our parent couldn't help
|
|
ASSERT(FALSE == _fCreatedBandProxy);
|
|
|
|
hres = CreateIBandProxyAndSetSite(SAFECAST(_ptbsitect, IUnknown *), riid, &_pbp, ppvObj);
|
|
if(_pbp)
|
|
{
|
|
ASSERT(S_OK == hres);
|
|
_fCreatedBandProxy = TRUE;
|
|
}
|
|
}
|
|
return hres;
|
|
}
|
|
else if (IsEqualGUID(guidService, IID_IBandSite))
|
|
{
|
|
return _bs.QueryInterface(riid, ppvObj);
|
|
}
|
|
else if (IsEqualGUID(guidService, IID_IAddressBand))
|
|
{
|
|
LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
|
|
if (pbid && pbid->pdb)
|
|
{
|
|
return pbid->pdb->QueryInterface(riid, ppvObj);
|
|
}
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
if (_psp)
|
|
return _psp->QueryService(guidService, riid, ppvObj);
|
|
|
|
|
|
return SUPERCLASS::QueryService(guidService, riid, ppvObj);
|
|
}
|
|
|
|
//
|
|
// FEATURE: Do we really need to implement the following two functions?
|
|
// Currently nobody uses them.
|
|
//
|
|
HRESULT CInternetToolbar::GetClassID(GUID *pguid)
|
|
{
|
|
*pguid = CLSID_InternetToolbar;
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CInternetToolbar::GetSizeMax(ULARGE_INTEGER *ulMaxSize)
|
|
{
|
|
ulMaxSize->LowPart = sizeof(COOLBARSAVE);
|
|
ulMaxSize->HighPart = 0;
|
|
return(S_OK);
|
|
}
|
|
|
|
|
|
CInternetToolbar::CITBandSite::CITBandSite() : CBandSite(NULL)
|
|
{
|
|
// HACKHACK: set the initial band ID to something bigger
|
|
// than the number of toolbars that is in this
|
|
// object. Currently those toolbars are not
|
|
// individual bands, but we want CBandSite to
|
|
// at least be aware of them.
|
|
//
|
|
_dwBandIDNext = CBANDSMAX;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::CITBandSite::_OnContextMenu(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _bs, this);
|
|
pitbar->_ShowContextMenu((HWND)wParam, lParam, NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::CITBandSite::_Initialize(HWND hwndParent)
|
|
{
|
|
_hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL,
|
|
RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_REGISTERDROP | RBS_DBLCLKTOGGLE |
|
|
WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPCHILDREN |
|
|
// WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN |
|
|
WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN,
|
|
0, 0, 100, 36, hwndParent, (HMENU) FCIDM_REBAR, HINST_THISDLL, NULL);
|
|
|
|
if (_hwnd)
|
|
{
|
|
Comctl32_SetWindowTheme(_hwnd, TEXT("ExplorerToolbar"));
|
|
SendMessage(_hwnd, RB_SETTEXTCOLOR, 0, CLR_DEFAULT);
|
|
SendMessage(_hwnd, RB_SETBKCOLOR, 0, CLR_DEFAULT);
|
|
SendMessage(_hwnd, CCM_SETVERSION, COMCTL32_VERSION, 0);
|
|
}
|
|
|
|
return CBandSite::_Initialize(hwndParent);
|
|
}
|
|
|
|
|
|
HRESULT CInternetToolbar::CITBandSite::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
|
|
DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
|
|
{
|
|
if (!pguidCmdGroup)
|
|
{
|
|
/*NOTHING*/
|
|
}
|
|
else if (IsEqualGUID(CGID_PrivCITCommands, *pguidCmdGroup))
|
|
{
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _bs, this);
|
|
return pitbar->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
|
|
}
|
|
else if (IsEqualGUID(CGID_Theater, *pguidCmdGroup))
|
|
{
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _bs, this);
|
|
return IUnknown_Exec(pitbar->_ptbsite, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
|
|
}
|
|
return CBandSite::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
|
|
}
|
|
|
|
HRESULT CInternetToolbar::CITBandSite::AddBand(IUnknown *punk)
|
|
{
|
|
HRESULT hres = CBandSite::AddBand(punk);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _bs, this);
|
|
pitbar->_SetBackground();
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
HRESULT CInternetToolbar::CITBandSite::HasFocusIO()
|
|
{
|
|
HRESULT hres = CBandSite::HasFocusIO();
|
|
if (hres == S_FALSE)
|
|
{
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _bs, this);
|
|
if (pitbar->_btb._hwnd == GetFocus())
|
|
hres = S_OK;
|
|
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
// This will remove all the buttons except the first 2
|
|
BOOL TOOLSBANDCLASS::_RemoveAllButtons()
|
|
{
|
|
INT_PTR nCount = SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0L);
|
|
|
|
if (!nCount)
|
|
return FALSE;
|
|
|
|
while (nCount-- > 0)
|
|
{
|
|
SendMessage(_hwnd, TB_DELETEBUTTON, nCount, 0L);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT TOOLSBANDCLASS::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
|
|
DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
|
|
{
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
if (!pguidCmdGroup)
|
|
{
|
|
/*NOTHING*/
|
|
#ifdef DEBUG
|
|
}
|
|
else if (IsEqualGUID(*pguidCmdGroup, IID_IExplorerToolbar))
|
|
{
|
|
switch(nCmdID)
|
|
{
|
|
case ETCMDID_GETBUTTONS:
|
|
// if this rips call tjgreen
|
|
ASSERT(0);
|
|
return E_FAIL;
|
|
}
|
|
#endif
|
|
}
|
|
else if (_IsDocHostGUID(pguidCmdGroup))
|
|
{
|
|
UEMFireEvent(&UEMIID_BROWSER, UEME_UITOOLBAR, UEMF_XEVENT, UIG_INET, nCmdID);
|
|
|
|
if (nCmdexecopt == OLECMDEXECOPT_PROMPTUSER)
|
|
{
|
|
// the user hit the drop down
|
|
if (pitbar->_ptbsitect && pvarargIn && pvarargIn->vt == VT_INT_PTR)
|
|
{
|
|
// v.vt = VT_I4;
|
|
POINT pt;
|
|
RECT* prc = (RECT*)pvarargIn->byref;
|
|
pt.x = prc->left;
|
|
pt.y = prc->bottom;
|
|
|
|
switch (nCmdID)
|
|
{
|
|
#ifdef EDIT_HACK
|
|
case DVIDM_EDITPAGE:
|
|
{
|
|
// Show the edit pop-up
|
|
BSTR bstrURL;
|
|
pitbar->_pdie->get_LocationURL(&bstrURL);
|
|
if (bstrURL)
|
|
{
|
|
USES_CONVERSION;
|
|
pitbar->_aEditVerb.ShowEditMenu(pt, pitbar->_hwnd, W2T(bstrURL));
|
|
SysFreeString(bstrURL);
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
default:
|
|
// if this rips find tjgreen
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
switch(nCmdID)
|
|
{
|
|
case DVIDM_EDITPAGE:
|
|
{
|
|
BSTR bstrURL;
|
|
ULONG fMask = 0;
|
|
TCHAR szCacheFileName[MAX_PATH + MAX_URL_STRING + 2];
|
|
memset(szCacheFileName, 0, sizeof(szCacheFileName));
|
|
|
|
pitbar->_pdie->get_LocationURL(&bstrURL);
|
|
if (NULL == bstrURL)
|
|
break;
|
|
|
|
USES_CONVERSION;
|
|
LPCTSTR szURL = W2T(bstrURL);
|
|
|
|
#ifdef EDIT_HACK
|
|
// Use the default edit verb
|
|
pitbar->_aEditVerb.Edit(szURL);
|
|
#else
|
|
SHELLEXECUTEINFO sei = {0};
|
|
LPTSTR pszTemp = PathFindExtension(szURL);
|
|
|
|
// If we did not find an extension, we assume it is an .htm or .html
|
|
if (*pszTemp != TEXT('.'))
|
|
{
|
|
if (SHVerbExists(TEXT(".htm"), TEXT("edit"), NULL))
|
|
sei.lpClass = TEXT(".htm");
|
|
else
|
|
sei.lpClass = TEXT(".html");
|
|
}
|
|
else
|
|
{
|
|
sei.lpClass = pszTemp;
|
|
}
|
|
|
|
if (PathIsURL(szURL))
|
|
{
|
|
// (reinerf)
|
|
// Some apps (FrontPad, Office99, etc) want the URL passed to
|
|
// them instead of the cache filename. We therefore create a string
|
|
// that has the URL name after the null:
|
|
//
|
|
// "CacheFileName/0UrlName"
|
|
//
|
|
// and pass it as the lpFile parameter to shellexecute.
|
|
// We also pass SEE_MASK_FILEANDURL, so shellexecute can
|
|
// recognize this case.
|
|
int iLength;
|
|
|
|
URLDownloadToCacheFile(NULL, szURL, szCacheFileName, 0, URLOSTRM_USECACHEDCOPY, NULL);
|
|
iLength = lstrlen(szCacheFileName);
|
|
|
|
// copy in the URL name
|
|
StrCpy(&szCacheFileName[iLength + 1], szURL);
|
|
|
|
// add the mask so shellexecute knows to check for the URL, if necessary.
|
|
fMask |= SEE_MASK_FILEANDURL;
|
|
}
|
|
else
|
|
{
|
|
StrCpy(szCacheFileName, szURL);
|
|
}
|
|
|
|
sei.cbSize = sizeof(SHELLEXECUTEINFO);
|
|
sei.fMask = fMask;
|
|
sei.hwnd = NULL;
|
|
sei.lpVerb = TEXT("edit");
|
|
sei.lpFile = szCacheFileName;
|
|
sei.lpParameters = NULL;
|
|
sei.lpDirectory = NULL;
|
|
sei.nShow = SW_SHOWNORMAL;
|
|
sei.hInstApp = NULL;
|
|
|
|
ShellExecuteEx(&sei);
|
|
|
|
SysFreeString(bstrURL);
|
|
#endif //!EDIT_HACK
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// if this rips call tjgreen
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// *** IInputObject methods ***
|
|
HRESULT TOOLSBANDCLASS::TranslateAcceleratorIO(LPMSG lpMsg)
|
|
{
|
|
if (SendMessage(_hwnd, TB_TRANSLATEACCELERATOR, 0, (LPARAM)lpMsg))
|
|
return S_OK;
|
|
|
|
return CToolBand::TranslateAcceleratorIO(lpMsg);
|
|
}
|
|
|
|
// *** IUnknown methods ***
|
|
HRESULT TOOLSBANDCLASS::QueryInterface(REFIID riid, void ** ppvObj)
|
|
{
|
|
static const QITAB qit[] = {
|
|
QITABENT(TOOLSBANDCLASS, IWinEventHandler),
|
|
{ 0 },
|
|
};
|
|
|
|
HRESULT hres = QISearch(this, qit, riid, ppvObj);
|
|
if (FAILED(hres))
|
|
hres = CToolBand::QueryInterface(riid, ppvObj);
|
|
|
|
return hres;
|
|
}
|
|
|
|
// *** IDeskBand methods ***
|
|
HRESULT TOOLSBANDCLASS::GetBandInfo(DWORD dwBandID, DWORD fViewMode, DESKBANDINFO* pdbi)
|
|
{
|
|
|
|
_dwBandID = dwBandID;
|
|
|
|
// set dwModeFlags
|
|
pdbi->dwModeFlags = DBIMF_FIXEDBMP | DBIMF_USECHEVRON;
|
|
|
|
// set ptMinSize
|
|
{
|
|
if (SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0))
|
|
{
|
|
// make our min size just big enough to show the first button
|
|
RECT rc;
|
|
SendMessage(_hwnd, TB_GETITEMRECT, 0, (LPARAM)&rc);
|
|
pdbi->ptMinSize.x = RECTWIDTH(rc);
|
|
pdbi->ptMinSize.y = RECTHEIGHT(rc);
|
|
}
|
|
else
|
|
{
|
|
// we don't have any buttons; so use standard button size
|
|
LONG lButtonSize = (long) SendMessage(_hwnd, TB_GETBUTTONSIZE, 0, 0);
|
|
pdbi->ptMinSize.x = LOWORD(lButtonSize);
|
|
pdbi->ptMinSize.y = HIWORD(lButtonSize);
|
|
}
|
|
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
if (pitbar->_fTheater && (pdbi->ptMinSize.y < (THEATER_CYTOOLBAR - 1)))
|
|
pdbi->ptMinSize.y = (THEATER_CYTOOLBAR - 1);
|
|
}
|
|
|
|
// set ptActual
|
|
{
|
|
SIZE size;
|
|
size.cy = pdbi->ptMinSize.y;
|
|
SendMessage(_hwnd, TB_GETIDEALSIZE, FALSE, (LPARAM)&size);
|
|
pdbi->ptActual.x = size.cx;
|
|
pdbi->ptActual.y = size.cy;
|
|
}
|
|
|
|
// no title
|
|
pdbi->dwMask &= ~DBIM_TITLE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
IOleCommandTarget* TOOLSBANDCLASS::_CommandTargetFromCmdMap(CMDMAP* pcm)
|
|
{
|
|
IOleCommandTarget* pct = NULL;
|
|
|
|
if (pcm)
|
|
{
|
|
if (IsEqualGUID(pcm->guidButtonGroup, CLSID_CommonButtons))
|
|
{
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
pct = SAFECAST(pitbar, IOleCommandTarget*);
|
|
}
|
|
else
|
|
{
|
|
// If either of these rip, the button is stale
|
|
ASSERT(IsEqualGUID(pcm->guidButtonGroup, _guidCurrentButtonGroup));
|
|
ASSERT(_pctCurrentButtonGroup);
|
|
|
|
pct = _pctCurrentButtonGroup;
|
|
}
|
|
}
|
|
|
|
return pct;
|
|
}
|
|
|
|
BOOL ShiftRectToEdgeOfMonitor(RECT *prc)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
POINT pt = {prc->left, prc->top};
|
|
|
|
HMONITOR hmon = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
|
|
if (hmon)
|
|
{
|
|
MONITORINFO mi = {sizeof(MONITORINFO)};
|
|
if (GetMonitorInfo(hmon, &mi))
|
|
{
|
|
// get the different between the monitor's left edge and the rect's left edge
|
|
int iShift = mi.rcMonitor.left - prc->left;
|
|
if (iShift > 0)
|
|
{
|
|
prc->left += iShift;
|
|
prc->right += iShift;
|
|
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
LRESULT TOOLSBANDCLASS::_OnToolbarDropDown(TBNOTIFY *ptbn)
|
|
{
|
|
if (ptbn->hdr.hwndFrom == _hwnd)
|
|
{
|
|
CMDMAP* pcm = _GetCmdMapByID(ptbn->iItem);
|
|
IOleCommandTarget* pct = _CommandTargetFromCmdMap(pcm);
|
|
|
|
if (pct)
|
|
{
|
|
VARIANTARG var;
|
|
var.vt = VT_I4;
|
|
var.lVal = ptbn->iItem;
|
|
|
|
// REARCHITECT: use VARIANT[TO/FROM]BUFFER here to fix win64 problem
|
|
|
|
VARIANT v = {VT_INT_PTR};
|
|
v.byref = &ptbn->rcButton;
|
|
|
|
MapWindowRect(_hwnd, HWND_DESKTOP, &ptbn->rcButton);
|
|
|
|
//
|
|
// If this window is mirrored, then let's take the
|
|
// other coordinate [samera]
|
|
//
|
|
if (IS_WINDOW_RTL_MIRRORED(_hwnd))
|
|
{
|
|
int iTmp = ptbn->rcButton.right;
|
|
ptbn->rcButton.right = ptbn->rcButton.left;
|
|
ptbn->rcButton.left = iTmp;
|
|
}
|
|
|
|
// TrackMenuPopup is lame when confronted with negative co-ordinates... lets clip to the edge of the screen.
|
|
ShiftRectToEdgeOfMonitor(&ptbn->rcButton);
|
|
|
|
#ifdef EDIT_HACK
|
|
// FEATURE: temp code -- edit code moving to dochost.cpp
|
|
if (_IsDocHostGUID(&pcm->guidButtonGroup) && pcm->nCmdID == DVIDM_EDITPAGE)
|
|
Exec(&pcm->guidButtonGroup, (DWORD)pcm->nCmdID, OLECMDEXECOPT_PROMPTUSER, &v, &var);
|
|
else
|
|
#endif
|
|
pct->Exec(&pcm->guidButtonGroup, (DWORD)pcm->nCmdID, OLECMDEXECOPT_PROMPTUSER, &v, &var);
|
|
}
|
|
}
|
|
|
|
return TBDDRET_DEFAULT;
|
|
}
|
|
|
|
LRESULT TOOLSBANDCLASS::_TryShowBackForwardMenu(DWORD dwItemSpec, LPPOINT ppt, LPRECT prcExclude)
|
|
{
|
|
LRESULT lres = 0;
|
|
|
|
GUID guid;
|
|
UINT id;
|
|
if (SUCCEEDED(_ConvertCmd(NULL, dwItemSpec, &guid, &id)))
|
|
{
|
|
// If the user right clicked on the the back or forward button, show the context menu
|
|
// On all other buttons show the regular shortcut menu
|
|
if (IsEqualGUID(guid, CLSID_CommonButtons))
|
|
{
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
if (id == TBIDM_BACK)
|
|
{
|
|
pitbar->_ShowBackForwardMenu(FALSE, *ppt, prcExclude);
|
|
lres = 1;
|
|
}
|
|
else if (id == TBIDM_FORWARD)
|
|
{
|
|
pitbar->_ShowBackForwardMenu(TRUE, *ppt, prcExclude);
|
|
lres = 1;
|
|
}
|
|
}
|
|
}
|
|
return lres;
|
|
}
|
|
|
|
LRESULT TOOLSBANDCLASS::_OnNotify(LPNMHDR pnmh)
|
|
{
|
|
LRESULT lres = 0;
|
|
|
|
ASSERT(pnmh->idFrom == FCIDM_TOOLBAR);
|
|
|
|
switch (pnmh->code)
|
|
{
|
|
|
|
case NM_RCLICK:
|
|
{
|
|
NMCLICK * pnm = (LPNMCLICK)pnmh;
|
|
|
|
if (!pnm)
|
|
break;
|
|
|
|
// Convert to Screen coordinates
|
|
MapWindowPoints(pnmh->hwndFrom, HWND_DESKTOP, &pnm->pt, 1);
|
|
|
|
if (pnmh->hwndFrom == _hwnd)
|
|
lres = _TryShowBackForwardMenu((DWORD)pnm->dwItemSpec, &pnm->pt, NULL);
|
|
}
|
|
break;
|
|
|
|
case TBN_DROPDOWN:
|
|
lres = _OnToolbarDropDown((TBNOTIFY *)pnmh);
|
|
break;
|
|
|
|
case TBN_DELETINGBUTTON:
|
|
_OnDeletingButton((TBNOTIFY*)pnmh);
|
|
break;
|
|
|
|
case TBN_SAVE:
|
|
case TBN_RESET:
|
|
case TBN_INITCUSTOMIZE:
|
|
case TBN_RESTORE:
|
|
case TBN_BEGINADJUST:
|
|
case TBN_GETBUTTONINFO:
|
|
case TBN_ENDADJUST:
|
|
case TBN_QUERYDELETE:
|
|
case TBN_QUERYINSERT:
|
|
case TBN_TOOLBARCHANGE:
|
|
if (pnmh->hwndFrom == _hwnd)
|
|
lres = _ToolsCustNotify (pnmh);
|
|
break;
|
|
|
|
case TBN_GETOBJECT:
|
|
{
|
|
NMOBJECTNOTIFY *pnmon = (NMOBJECTNOTIFY *)pnmh;
|
|
if (IsEqualIID(*pnmon->piid, IID_IDropTarget))
|
|
{
|
|
if (pnmh->hwndFrom == _hwnd)
|
|
{
|
|
UINT uiCmd;
|
|
GUID guid;
|
|
_ConvertCmd(NULL, pnmon->iItem, &guid, &uiCmd);
|
|
|
|
if (IsEqualGUID(guid, CLSID_CommonButtons) &&
|
|
(uiCmd == TBIDM_HOME || uiCmd == TBIDM_FAVORITES))
|
|
{
|
|
CITBarDropTarget *pdtgt = new CITBarDropTarget(_hwnd, uiCmd);
|
|
if (pdtgt)
|
|
{
|
|
pnmon->pObject = SAFECAST(pdtgt, IDropTarget*);
|
|
pnmon->hResult = NOERROR;
|
|
}
|
|
}
|
|
else // pass back CDropDummy to handle basics.
|
|
{
|
|
CDropDummy *pdtgt = new CDropDummy(_hwnd);
|
|
if (pdtgt)
|
|
{
|
|
pnmon->pObject = SAFECAST(pdtgt, IDropTarget*);
|
|
pnmon->hResult = NOERROR;
|
|
}
|
|
}
|
|
|
|
}
|
|
lres = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
lres = CToolbarBand::_OnNotify(pnmh);
|
|
break;
|
|
}
|
|
|
|
return lres;
|
|
}
|
|
|
|
LRESULT TOOLSBANDCLASS::_OnContextMenu(LPARAM lParam, WPARAM wParam)
|
|
{
|
|
LRESULT lres = 0;
|
|
|
|
if (IS_WM_CONTEXTMENU_KEYBOARD(lParam))
|
|
{
|
|
// keyboard context menu. figure out where to pop up menu and
|
|
// which context menu to use, and tell itbar to pop it up.
|
|
RECT rc;
|
|
BOOL fBackForward = FALSE;
|
|
|
|
// figure out coordinates to use
|
|
INT_PTR iBtn = SendMessage(_hwnd, TB_GETHOTITEM, 0, 0);
|
|
if (iBtn != -1)
|
|
{
|
|
// use lower left corner of current hot button
|
|
SendMessage(_hwnd, TB_GETITEMRECT, iBtn, (LPARAM)&rc);
|
|
}
|
|
else
|
|
{
|
|
// no hot button; use top left corner of tools window
|
|
SetRect(&rc, 0, 0, 0, 0);
|
|
}
|
|
MapWindowPoints(_hwnd, HWND_DESKTOP, (LPPOINT)&rc, 2);
|
|
|
|
if (iBtn != -1)
|
|
{
|
|
// get hot button's command
|
|
TBBUTTONINFO tbbi;
|
|
tbbi.cbSize = sizeof(TBBUTTONINFO);
|
|
tbbi.dwMask = TBIF_BYINDEX | TBIF_COMMAND;
|
|
SendMessage(_hwnd, TB_GETBUTTONINFO, iBtn, (LPARAM)&tbbi);
|
|
|
|
POINT pt = {rc.left, rc.bottom};
|
|
|
|
// try popping up the back/forward context menu
|
|
if (_TryShowBackForwardMenu(tbbi.idCommand, &pt, &rc))
|
|
fBackForward = TRUE;
|
|
}
|
|
|
|
if (!fBackForward)
|
|
{
|
|
// pop up the standard context menu
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
pitbar->_ShowContextMenu((HWND)wParam, MAKELONG(rc.left, rc.bottom), (iBtn == -1 ? NULL : &rc));
|
|
}
|
|
|
|
lres = 1;
|
|
}
|
|
return lres;
|
|
}
|
|
|
|
void TOOLSBANDCLASS::_RecalcButtonWidths()
|
|
{
|
|
// We need the toolbars buttons to use ONLY exactly as much space as is needed.
|
|
// By setting the size a a really small number like 10, and then setting it to
|
|
// the real number we can accomplish this.
|
|
// If we don't use do this, then when we add new buttons after doing this
|
|
// RemoveAllButtons(), the new buttons will be at least as wide as the widest
|
|
// button that existed on the last set of buttons (the ones we are just removing)
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
SendMessage(_hwnd, TB_SETBUTTONWIDTH, 0, (LPARAM)MAKELONG(0, 10));
|
|
SendMessage(_hwnd, TB_SETBUTTONWIDTH, 0, (LPARAM)(pitbar->_fCompressed ? MAKELONG(0, MAX_TB_COMPRESSED_WIDTH) : MAKELONG(0, pitbar->_uiMaxTBWidth)));
|
|
}
|
|
|
|
// *** IWinEventHandler methods ***
|
|
HRESULT TOOLSBANDCLASS::OnWinEvent(HWND hwnd, UINT dwMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres)
|
|
{
|
|
HRESULT hres = S_OK;
|
|
|
|
switch (dwMsg)
|
|
{
|
|
case WM_CONTEXTMENU:
|
|
*plres = _OnContextMenu(lParam, wParam);
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
*plres = _OnNotify((LPNMHDR)lParam);
|
|
break;
|
|
|
|
case WM_WININICHANGE:
|
|
*plres = SendMessage(_hwnd, dwMsg, wParam, lParam);
|
|
if (wParam == SPI_SETNONCLIENTMETRICS)
|
|
{
|
|
_RecalcButtonWidths();
|
|
_BandInfoChanged();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
hres = CToolbarBand::OnWinEvent(hwnd, dwMsg, wParam, lParam, plres);
|
|
break;
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
CMDMAP* TOOLSBANDCLASS::_GetCmdMap(int i, BOOL fByIndex)
|
|
{
|
|
TBBUTTONINFO tbbi;
|
|
tbbi.cbSize = sizeof(tbbi);
|
|
tbbi.dwMask = TBIF_LPARAM;
|
|
tbbi.lParam = 0;
|
|
if (fByIndex)
|
|
tbbi.dwMask |= TBIF_BYINDEX;
|
|
SendMessage(_hwnd, TB_GETBUTTONINFO, i, (LPARAM)&tbbi);
|
|
return (CMDMAP*)(void*)tbbi.lParam;
|
|
}
|
|
|
|
|
|
void TOOLSBANDCLASS::_FreeCmdMap(CMDMAP* pcm)
|
|
{
|
|
if (pcm)
|
|
LocalFree(pcm);
|
|
}
|
|
|
|
void TOOLSBANDCLASS::_OnDeletingButton(TBNOTIFY* ptbn)
|
|
{
|
|
CMDMAP *pcm = (CMDMAP*)(void*)ptbn->tbButton.dwData;
|
|
_FreeCmdMap(pcm);
|
|
}
|
|
|
|
LONG_PTR TOOLSBANDCLASS::_AddString(LPWSTR pwstr)
|
|
{
|
|
LONG_PTR lOffset;
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
pitbar->AddString(&_guidCurrentButtonGroup, 0, (UINT_PTR)pwstr, &lOffset);
|
|
|
|
return lOffset;
|
|
}
|
|
|
|
#define PPBS_LOOKINTOOLBAR 0x00000001
|
|
#define PPBS_EXTERNALBUTTON 0x00000002
|
|
|
|
void TOOLSBANDCLASS::_PreProcessButtonString(TBBUTTON *ptbn, DWORD dwFlags)
|
|
{
|
|
// Caller should have checked this.
|
|
ASSERT(!(ptbn->fsStyle & BTNS_SEP));
|
|
|
|
// If we don't have a command target, we shouldn't have any external buttons.
|
|
ASSERT(_pctCurrentButtonGroup || !(dwFlags & PPBS_EXTERNALBUTTON));
|
|
|
|
if (ptbn->iString < 0 && ptbn->iBitmap <= MAX_SHELLGLYPHINDEX)
|
|
{
|
|
// total hack
|
|
// we're hard coding the strings in to match
|
|
// the bitmap. so if anyone uses the shell bitmaps,
|
|
// they're going to get our text labels
|
|
// also hacking in that the bitmap array and string array are
|
|
// matched
|
|
// who designed reviewed this???
|
|
|
|
ptbn->iString = ptbn->iBitmap;
|
|
}
|
|
else if (!ptbn->iString && (dwFlags & PPBS_EXTERNALBUTTON))
|
|
{
|
|
// Some Extensions are giving us bogus string ids (Font ext sends 0)
|
|
ptbn->iString = -1;
|
|
}
|
|
else if (ptbn->iString != -1 && !IS_INTRESOURCE(ptbn->iString))
|
|
{
|
|
// It's a string pointer. The customization mechanism requires that all buttons
|
|
// use strings from the tb string pool. So add the string to the pool and set
|
|
// iString to the pool index.
|
|
ptbn->iString = _AddString((LPWSTR)ptbn->iString);
|
|
}
|
|
|
|
if (ptbn->iString == -1 && IsFlagSet(dwFlags, PPBS_LOOKINTOOLBAR | PPBS_EXTERNALBUTTON))
|
|
{
|
|
// If we're building the customization dsa rather than adding new buttons to the
|
|
// toolbar, we may already have this button in the toolbar. If so, use that string.
|
|
|
|
UINT idCommand;
|
|
if (SUCCEEDED(_ConvertCmd(&_guidCurrentButtonGroup, ptbn->idCommand, NULL, &idCommand)))
|
|
{
|
|
TBBUTTON tbb;
|
|
if (SendMessage(_hwnd, TB_GETBUTTON, idCommand, (LPARAM)&tbb))
|
|
ptbn->iString = tbb.iString;
|
|
}
|
|
}
|
|
|
|
if (ptbn->iString == -1 && (dwFlags & PPBS_EXTERNALBUTTON))
|
|
{
|
|
// Still don't have a string for this puppy. Last resort is to ask via QueryStatus.
|
|
OLECMDTEXTV<MAX_TOOLTIP_STRING> cmdtv;
|
|
OLECMDTEXT *pcmdText = &cmdtv;
|
|
|
|
pcmdText->cwBuf = MAX_TOOLTIP_STRING;
|
|
pcmdText->cmdtextf = OLECMDTEXTF_NAME;
|
|
pcmdText->cwActual = 0;
|
|
|
|
OLECMD rgcmd = {ptbn->idCommand, 0};
|
|
|
|
HRESULT hr = _pctCurrentButtonGroup->QueryStatus(&_guidCurrentButtonGroup, 1, &rgcmd, pcmdText);
|
|
if (SUCCEEDED(hr) && (pcmdText->cwActual))
|
|
ptbn->iString = _AddString(pcmdText->rgwz);
|
|
}
|
|
|
|
// If it's an internal button, we'd better have found a string for it.
|
|
ASSERT(ptbn->iString != -1 || (dwFlags & PPBS_EXTERNALBUTTON));
|
|
}
|
|
|
|
void TOOLSBANDCLASS::_PreProcessExternalTBButton(TBBUTTON *ptbn)
|
|
{
|
|
if (!(ptbn->fsStyle & BTNS_SEP))
|
|
{
|
|
CMDMAP* pcm = (CMDMAP*)LocalAlloc(LPTR, sizeof(CMDMAP));
|
|
if (pcm)
|
|
{
|
|
pcm->guidButtonGroup = _guidCurrentButtonGroup;
|
|
pcm->nCmdID = ptbn->idCommand;
|
|
|
|
_PreProcessButtonString(ptbn, PPBS_EXTERNALBUTTON);
|
|
|
|
_nNextCommandID++;
|
|
pcm->lParam = ptbn->dwData;
|
|
}
|
|
|
|
ptbn->dwData = (LPARAM)pcm;
|
|
}
|
|
else
|
|
{
|
|
ptbn->dwData = 0;
|
|
|
|
// override default toolbar width for separators; iBitmap member of
|
|
// TBBUTTON struct is a union of bitmap index & separator width
|
|
ptbn->iBitmap = CX_SEPARATOR;
|
|
}
|
|
}
|
|
|
|
UINT TOOLSBANDCLASS::_ProcessExternalButtons(PTBBUTTON ptbb, UINT cButtons)
|
|
{
|
|
cButtons = RemoveHiddenButtons(ptbb, cButtons);
|
|
|
|
for (UINT i = 0; i < cButtons; i++)
|
|
_PreProcessExternalTBButton(&ptbb[i]);
|
|
|
|
return cButtons;
|
|
}
|
|
|
|
void TOOLSBANDCLASS::_GetButtons(IOleCommandTarget* pct, const GUID* pguid, HDSA hdsa)
|
|
{
|
|
LONG lCount;
|
|
VARIANTARG v1;
|
|
VariantInit(&v1);
|
|
v1.vt = VT_BYREF | VT_I4;
|
|
v1.plVal = &lCount;
|
|
|
|
VARIANTARG v2;
|
|
VariantInit(&v2);
|
|
if (SUCCEEDED(pct->Exec(&IID_IExplorerToolbar, ETCMDID_GETBUTTONS, 0, &v1, &v2)) && v2.vt == VT_BYREF)
|
|
{
|
|
CMDMAPCUSTOMIZE cmc;
|
|
TBBUTTON* pbtn = (TBBUTTON*)v2.byref;
|
|
|
|
cmc.cm.guidButtonGroup = *pguid;
|
|
|
|
DWORD dwFlags = PPBS_LOOKINTOOLBAR;
|
|
|
|
if (!IsEqualGUID(*pguid, CLSID_CommonButtons))
|
|
dwFlags |= PPBS_EXTERNALBUTTON;
|
|
|
|
for (long l = 0; l < lCount; l++)
|
|
{
|
|
cmc.btn = pbtn[l];
|
|
if (!(cmc.btn.fsStyle & BTNS_SEP))
|
|
{
|
|
cmc.cm.nCmdID = pbtn[l].idCommand;
|
|
|
|
_PreProcessButtonString(&cmc.btn, dwFlags);
|
|
|
|
if (FAILED(_ConvertCmd(pguid, cmc.cm.nCmdID, NULL, (UINT*)&cmc.btn.idCommand)))
|
|
{
|
|
// not already in the toolbar, generate a new id
|
|
cmc.btn.idCommand = _nNextCommandID++;
|
|
}
|
|
|
|
DSA_AppendItem(hdsa, &cmc);
|
|
}
|
|
else
|
|
{
|
|
cmc.btn.dwData = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TOOLSBANDCLASS::_OnEndCustomize()
|
|
{
|
|
|
|
if (_pcinfo)
|
|
{
|
|
// loop through and make sure that any items added have the appropriate cmdmap
|
|
int i;
|
|
INT_PTR nCount = SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0L);
|
|
_pcinfo->fAdjust = FALSE;
|
|
for(i = 0; i < nCount; i++)
|
|
{
|
|
CMDMAP* pcm = _GetCmdMapByIndex(i);
|
|
if (!pcm)
|
|
{
|
|
// no command map for this item
|
|
// find the corresponding CMDMAP in our hdsa, clone it and give it to this button.
|
|
|
|
// the command id's are the same, so get the toolbar command id, find the corresponding
|
|
// one in the hdsa and clone away.
|
|
TBBUTTONINFO tbbi;
|
|
tbbi.cbSize = sizeof(tbbi);
|
|
tbbi.dwMask = TBIF_COMMAND | TBIF_BYINDEX;
|
|
SendMessage(_hwnd, TB_GETBUTTONINFO, i, (LPARAM)&tbbi);
|
|
|
|
int j;
|
|
for (j = 0; j < DSA_GetItemCount(_pcinfo->hdsa); j++)
|
|
{
|
|
CMDMAPCUSTOMIZE* pcmc = (CMDMAPCUSTOMIZE*)DSA_GetItemPtr(_pcinfo->hdsa, j);
|
|
ASSERT(pcmc);
|
|
if (pcmc->btn.idCommand == tbbi.idCommand)
|
|
{
|
|
// found it!
|
|
|
|
// clone the cmdmap
|
|
CMDMAP *pcm = (CMDMAP*)LocalAlloc(LPTR, sizeof(CMDMAP));
|
|
if (pcm)
|
|
{
|
|
*pcm = pcmc->cm;
|
|
tbbi.lParam = (LPARAM)pcm;
|
|
tbbi.dwMask = TBIF_LPARAM | TBIF_BYINDEX;
|
|
SendMessage(_hwnd, TB_SETBUTTONINFO, i, (LPARAM)&tbbi);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_pcinfo->fDirty)
|
|
_SaveRestoreToolbar(TRUE);
|
|
|
|
_FreeCustomizeInfo();
|
|
|
|
_RecalcButtonWidths();
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
|
|
#ifdef EDIT_HACK
|
|
pitbar->_InitEditButtonStyle();
|
|
#endif
|
|
if (g_fSmallIcons != _UseSmallIcons())
|
|
{
|
|
SendShellIEBroadcastMessage(WM_WININICHANGE, 0, (LPARAM)SZ_REGKEY_SMALLICONS, 3000);
|
|
|
|
// Resize the Theater Controls based upon the icon changes.
|
|
IUnknown_Exec( _punkSite, &CGID_Theater, THID_RECALCSIZING, 0, NULL, NULL );
|
|
}
|
|
|
|
pitbar->_UpdateToolbar(TRUE);
|
|
}
|
|
}
|
|
|
|
void TOOLSBANDCLASS::_FreeCustomizeInfo()
|
|
{
|
|
if (_pcinfo)
|
|
{
|
|
DSA_Destroy(_pcinfo->hdsa);
|
|
_pcinfo->hdsa = NULL;
|
|
LocalFree(_pcinfo);
|
|
_pcinfo = NULL;
|
|
}
|
|
}
|
|
|
|
CMDMAPCUSTOMIZE* TOOLSBANDCLASS::_GetCmdMapCustomize(GUID* pguid, UINT nCmdID)
|
|
{
|
|
int j;
|
|
for (j = 0; j < DSA_GetItemCount(_pcinfo->hdsa); j++)
|
|
{
|
|
CMDMAPCUSTOMIZE* pcmc = (CMDMAPCUSTOMIZE*)DSA_GetItemPtr(_pcinfo->hdsa, j);
|
|
|
|
if (pcmc->cm.nCmdID == nCmdID &&
|
|
IsEqualGUID(*pguid, pcmc->cm.guidButtonGroup))
|
|
{
|
|
return pcmc;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
BOOL TOOLSBANDCLASS::_BuildButtonDSA()
|
|
{
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
|
|
ASSERT(!_pcinfo);
|
|
_pcinfo = (CUSTOMIZEINFO*)LocalAlloc(LPTR, sizeof(CUSTOMIZEINFO));
|
|
|
|
if (_pcinfo)
|
|
{
|
|
// build a CMDMAP array of all the buttons available
|
|
_pcinfo->hdsa = DSA_Create(sizeof(CMDMAPCUSTOMIZE), 4);
|
|
|
|
if (_pcinfo->hdsa)
|
|
{
|
|
// add the common set (back,forward, stop, refresh, home and search
|
|
_GetButtons(pitbar, &CLSID_CommonButtons, _pcinfo->hdsa);
|
|
_GetButtons(_pctCurrentButtonGroup, &_guidCurrentButtonGroup, _pcinfo->hdsa);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
_FreeCustomizeInfo();
|
|
return FALSE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void TOOLSBANDCLASS::_UpdateTextSettings(INT_PTR ids)
|
|
{
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
|
|
BOOL fText, fList;
|
|
|
|
switch (ids)
|
|
{
|
|
case IDS_TEXTLABELS:
|
|
fList = FALSE;
|
|
fText = TRUE;
|
|
break;
|
|
|
|
case IDS_PARTIALTEXT:
|
|
fList = TRUE;
|
|
fText = TRUE;
|
|
break;
|
|
|
|
case IDS_NOTEXTLABELS:
|
|
fList = FALSE; // (but we really don't care)
|
|
fText = FALSE;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
fList = FALSE;
|
|
fText = FALSE;
|
|
break;
|
|
}
|
|
|
|
pitbar->_UpdateToolsStyle(fList);
|
|
|
|
// (_fCompressed == TRUE means no text labels)
|
|
pitbar->_UpdateToolbarDisplay(UTD_TEXTLABEL, 0, !fText, TRUE);
|
|
}
|
|
|
|
const static DWORD c_aBtnAttrHelpIDs[] = {
|
|
IDC_SHOWTEXT, IDH_BROWSEUI_TB_TEXTOPTNS,
|
|
IDC_SMALLICONS, IDH_BROWSEUI_TB_ICONOPTNS,
|
|
0, 0
|
|
};
|
|
|
|
BOOL_PTR CALLBACK TOOLSBANDCLASS::_BtnAttrDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CInternetToolbar* pitbar = (CInternetToolbar*)GetWindowPtr(hDlg, DWLP_USER);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
SetWindowLongPtr(hDlg, DWLP_USER, lParam); /* LPADJUSTDLGDATA pointer */
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
if (GET_WM_COMMAND_ID(wParam, lParam) == IDC_SHOWTEXT)
|
|
{
|
|
if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELENDOK ||
|
|
GET_WM_COMMAND_CMD(wParam, lParam) == CBN_CLOSEUP)
|
|
{
|
|
// what'd they pick?
|
|
HWND hwndText = GET_WM_COMMAND_HWND(wParam, lParam);
|
|
INT_PTR iSel = SendMessage(hwndText, CB_GETCURSEL, 0, 0);
|
|
INT_PTR idsSel = SendMessage(hwndText, CB_GETITEMDATA, iSel, 0);
|
|
|
|
pitbar->_btb._UpdateTextSettings(idsSel);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
SHWinHelpOnDemandWrap((HWND) wParam, c_szHelpFile,
|
|
HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR) c_aBtnAttrHelpIDs);
|
|
return TRUE;
|
|
|
|
case WM_HELP:
|
|
SHWinHelpOnDemandWrap((HWND) ((LPHELPINFO) lParam)->hItemHandle, c_szHelpFile,
|
|
HELP_WM_HELP, (DWORD_PTR)(LPTSTR) c_aBtnAttrHelpIDs);
|
|
return TRUE;
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
#define SZ_YES TEXT("yes")
|
|
#define SZ_NO TEXT("no")
|
|
|
|
HWND hwndIcons = GetDlgItem(hDlg, IDC_SMALLICONS);
|
|
if (TPTR(hwndIcons))
|
|
{
|
|
INT_PTR iSel = SendMessage(hwndIcons, CB_GETCURSEL, 0, 0);
|
|
BOOL fSmallIcons = (SendMessage(hwndIcons, CB_GETITEMDATA, iSel, 0) == IDS_SMALLICONS);
|
|
|
|
LPCTSTR szData;
|
|
DWORD cbData;
|
|
|
|
if (fSmallIcons)
|
|
{
|
|
szData = SZ_YES;
|
|
cbData = sizeof(SZ_YES);
|
|
}
|
|
else
|
|
{
|
|
szData = SZ_NO;
|
|
cbData = sizeof(SZ_NO);
|
|
}
|
|
SHRegSetUSValue(SZ_REGKEY_SMALLICONS, SZ_REGVALUE_SMALLICONS, REG_SZ, (void*)szData, cbData, SHREGSET_FORCE_HKCU);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void TOOLSBANDCLASS::_PopulateComboBox(HWND hwnd, const int iResource[], UINT cResources)
|
|
{
|
|
TCHAR sz[256];
|
|
|
|
// loop through iResource[], load each string resource and insert into combobox
|
|
for (UINT i = 0; i < cResources; i++)
|
|
{
|
|
if (MLLoadString(iResource[i], sz, ARRAYSIZE(sz)))
|
|
{
|
|
INT_PTR iIndex = SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)sz);
|
|
SendMessage(hwnd, CB_SETITEMDATA, iIndex, iResource[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TOOLSBANDCLASS::_SetComboSelection(HWND hwnd, int iCurOption)
|
|
{
|
|
INT_PTR cItems = SendMessage(hwnd, CB_GETCOUNT, 0, 0);
|
|
|
|
while (cItems--)
|
|
{
|
|
INT_PTR iItemData = SendMessage(hwnd, CB_GETITEMDATA, cItems, 0);
|
|
|
|
if (iItemData == iCurOption)
|
|
{
|
|
SendMessage(hwnd, CB_SETCURSEL, cItems, 0);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// iCurOption should be in list somewhere;
|
|
// assert that we're not done looking
|
|
ASSERT(cItems);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TOOLSBANDCLASS::_SetDialogSelections(HWND hDlg, BOOL fSmallIcons)
|
|
{
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
|
|
int iCurOption;
|
|
HWND hwnd;
|
|
|
|
hwnd = GetDlgItem(hDlg, IDC_SHOWTEXT);
|
|
|
|
if (pitbar->_fCompressed)
|
|
iCurOption = IDS_NOTEXTLABELS;
|
|
else if (IS_LIST_STYLE(_hwnd))
|
|
iCurOption = IDS_PARTIALTEXT;
|
|
else
|
|
iCurOption = IDS_TEXTLABELS;
|
|
|
|
_SetComboSelection(hwnd, iCurOption);
|
|
if (pitbar->_fTheater)
|
|
SHSetWindowBits(hwnd, GWL_STYLE, WS_DISABLED, WS_DISABLED);
|
|
|
|
hwnd = GetDlgItem(hDlg, IDC_SMALLICONS);
|
|
iCurOption = (fSmallIcons ? IDS_SMALLICONS : IDS_LARGEICONS);
|
|
_SetComboSelection(hwnd, iCurOption);
|
|
}
|
|
|
|
static const int c_iTextOptions[] = {
|
|
IDS_TEXTLABELS,
|
|
IDS_PARTIALTEXT,
|
|
IDS_NOTEXTLABELS,
|
|
};
|
|
|
|
static const int c_iIconOptions[] = {
|
|
IDS_SMALLICONS,
|
|
IDS_LARGEICONS,
|
|
};
|
|
|
|
void TOOLSBANDCLASS::_PopulateDialog(HWND hDlg)
|
|
{
|
|
HWND hwnd;
|
|
|
|
hwnd = GetDlgItem(hDlg, IDC_SHOWTEXT);
|
|
_PopulateComboBox(hwnd, c_iTextOptions, ARRAYSIZE(c_iTextOptions));
|
|
|
|
hwnd = GetDlgItem(hDlg, IDC_SMALLICONS);
|
|
_PopulateComboBox(hwnd, c_iIconOptions, ARRAYSIZE(c_iIconOptions));
|
|
}
|
|
|
|
void TOOLSBANDCLASS::_OnBeginCustomize(LPNMTBCUSTOMIZEDLG pnm)
|
|
{
|
|
CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
|
|
HWND hwnd = (HWND) GetProp(pnm->hDlg, SZ_PROP_CUSTDLG);
|
|
|
|
if (!hwnd)
|
|
{
|
|
//
|
|
// hasn't been initialized.
|
|
//
|
|
// we need to check this because this init will be called
|
|
// when the user hits reset as well
|
|
|
|
hwnd = CreateDialogParam(MLGetHinst(), MAKEINTRESOURCE(DLG_TEXTICONOPTIONS), pnm->hDlg, _BtnAttrDlgProc, (LPARAM)pitbar);
|
|
if (hwnd)
|
|
{
|
|
// store hwnd of our dialog as property on tb cust dialog
|
|
SetProp(pnm->hDlg, SZ_PROP_CUSTDLG, hwnd);
|
|
|
|
// populate dialog controls
|
|
_PopulateDialog(hwnd);
|
|
|
|
// initialize dialog control selection states
|
|
_SetDialogSelections(hwnd, g_fSmallIcons);
|
|
|
|
RECT rc, rcWnd, rcClient;
|
|
GetWindowRect(pnm->hDlg, &rcWnd);
|
|
GetClientRect(pnm->hDlg, &rcClient);
|
|
GetWindowRect(hwnd, &rc);
|
|
|
|
// enlarge tb dialog to make room for our dialog
|
|
SetWindowPos(pnm->hDlg, NULL, rcWnd.left, rcWnd.top + 64, RECTWIDTH(rcWnd), RECTHEIGHT(rcWnd) + RECTHEIGHT(rc), SWP_NOZORDER);
|
|
|
|
// position our dialog at the bottom of the tb dialog
|
|
SetWindowPos(hwnd, HWND_TOP, rcClient.left, rcClient.bottom, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
|
|
}
|
|
}
|
|
|
|
if (_BuildButtonDSA())
|
|
{
|
|
_pcinfo->fAdjust = TRUE;
|
|
}
|
|
}
|
|
|
|
class CBitmapPreload : public IRunnableTask
|
|
{
|
|
public:
|
|
STDMETHOD ( QueryInterface ) ( REFIID riid, void ** ppvObj );
|
|
STDMETHOD_( ULONG, AddRef ) ();
|
|
STDMETHOD_( ULONG, Release ) ();
|
|
|
|
STDMETHOD (Run)( void );
|
|
STDMETHOD (Kill)( BOOL fWait );
|
|
STDMETHOD (Suspend)( );
|
|
STDMETHOD (Resume)( );
|
|
STDMETHOD_( ULONG, IsRunning )( void );
|
|
|
|
protected:
|
|
friend HRESULT CBitmapPreload_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi);
|
|
|
|
CBitmapPreload();
|
|
~CBitmapPreload();
|
|
|
|
LONG m_cRef;
|
|
LONG m_lState;
|
|
};
|
|
|
|
STDAPI CBitmapPreload_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
|
|
{
|
|
// aggregation checking and *ppunk zeroing are handled in class factory
|
|
ASSERT(pUnkOuter == NULL);
|
|
|
|
CBitmapPreload* pbp = new CBitmapPreload();
|
|
|
|
if (pbp)
|
|
{
|
|
*ppunk = SAFECAST(pbp, IRunnableTask*);
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
*ppunk = NULL; // redundant but doesn't hurt
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
|
|
CBitmapPreload::CBitmapPreload() : m_cRef(1)
|
|
{
|
|
m_lState = IRTIR_TASK_NOT_RUNNING;
|
|
}
|
|
|
|
|
|
CBitmapPreload::~CBitmapPreload()
|
|
{
|
|
}
|
|
|
|
|
|
STDMETHODIMP CBitmapPreload::QueryInterface (REFIID riid, void ** ppv)
|
|
{
|
|
static const QITAB qit[] = {
|
|
QITABENT(CBitmapPreload, IRunnableTask),
|
|
{ 0 },
|
|
};
|
|
return QISearch(this, qit, riid, ppv);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_( ULONG ) CBitmapPreload:: AddRef ()
|
|
{
|
|
return InterlockedIncrement( &m_cRef );
|
|
}
|
|
|
|
STDMETHODIMP_( ULONG ) CBitmapPreload:: Release ()
|
|
{
|
|
if (InterlockedDecrement( &m_cRef ) == 0 )
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_cRef;
|
|
}
|
|
|
|
STDMETHODIMP CBitmapPreload::Run ( void )
|
|
{
|
|
if ( m_lState != IRTIR_TASK_NOT_RUNNING )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
InterlockedExchange( &m_lState, IRTIR_TASK_RUNNING );
|
|
|
|
CInternetToolbar_Preload( );
|
|
|
|
InterlockedExchange( &m_lState, IRTIR_TASK_FINISHED );
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CBitmapPreload::Kill ( BOOL fWait )
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CBitmapPreload::Suspend ( )
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CBitmapPreload::Resume ( )
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_( ULONG ) CBitmapPreload:: IsRunning ( void )
|
|
{
|
|
return m_lState;
|
|
}
|
|
|
|
|
|
|
|
#ifdef EDIT_HACK
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------------------------
|
|
CInternetToolbar::CEditVerb::CEditVerb()
|
|
{
|
|
ASSERT(_nElements == 0);
|
|
ASSERT(_nDefault == 0);
|
|
ASSERT(_pVerb == NULL);
|
|
ASSERT(_lpfnOldWndProc == NULL);
|
|
ASSERT(_pszDefaultEditor == NULL);
|
|
ASSERT(_fInitEditor == FALSE);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Destructor
|
|
//--------------------------------------------------------------------------
|
|
CInternetToolbar::CEditVerb::~CEditVerb()
|
|
{
|
|
if (_pVerb) RemoveAll();
|
|
SetStr(&_pszDefaultEditor, NULL);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Removes all cached edit verbs and associated memory
|
|
//--------------------------------------------------------------------------
|
|
void CInternetToolbar::CEditVerb::RemoveAll()
|
|
{
|
|
if (_nElements > 0)
|
|
{
|
|
for (UINT i=0; i < _nElements; ++i)
|
|
{
|
|
EDITVERB& rVerb = _pVerb[i];
|
|
|
|
SetStr(&rVerb.pszDesc, NULL);
|
|
SetStr(&rVerb.pszMenuText, NULL);
|
|
SetStr(&rVerb.pszExe, NULL);
|
|
if (rVerb.hkeyProgID)
|
|
{
|
|
RegCloseKey(rVerb.hkeyProgID);
|
|
}
|
|
_ClearMSAAMenuInfo(rVerb);
|
|
}
|
|
|
|
LocalFree(_pVerb);
|
|
|
|
_pVerb = NULL;
|
|
_nElements = 0;
|
|
_nDefault = 0;
|
|
}
|
|
}
|
|
|
|
void _AddToOpenWithList(HKEY hkeyProgid, LPCWSTR pszVerb, LPCWSTR pszFileExt)
|
|
{
|
|
ASSERT(hkeyProgid);
|
|
ASSERT(pszVerb);
|
|
ASSERT(pszFileExt);
|
|
|
|
// First get the name of the exe
|
|
WCHAR szPath[MAX_PATH];
|
|
|
|
if (SUCCEEDED(AssocQueryStringByKey(ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, hkeyProgid,
|
|
pszVerb, szPath, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szPath)))))
|
|
{
|
|
// Now see if it is in the openwith list for the given file extension
|
|
LPCWSTR pszExe = PathFindFileName(szPath);
|
|
|
|
WCHAR szKey[MAX_PATH];
|
|
wnsprintf(szKey, ARRAYSIZE(szKey), L"%s\\OpenWithList\\%s", pszFileExt, pszExe);
|
|
HKEY hkey;
|
|
|
|
DWORD dwDisp;
|
|
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CLASSES_ROOT, szKey, 0, L"", REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_WRITE, NULL, &hkey, &dwDisp))
|
|
{
|
|
// If we create a new key, we then need to check that verb is registered
|
|
// for this app
|
|
if (dwDisp == REG_CREATED_NEW_KEY)
|
|
{
|
|
AssocMakeApplicationByKey(ASSOCMAKEF_VERIFY, hkeyProgid, pszVerb);
|
|
}
|
|
RegCloseKey(hkey);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Check registry for a default mhtml editor. If a new editor is detected,
|
|
// it is added to the mhtml openwith list.
|
|
//--------------------------------------------------------------------------
|
|
void CInternetToolbar::CEditVerb::_InitDefaultMHTMLEditor()
|
|
{
|
|
//
|
|
// Check for a default MHTML editor.
|
|
//
|
|
HKEY hkeyEdit = NULL;
|
|
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_DEFAULT_MHTML_EDITOR, 0, KEY_READ | KEY_WRITE, &hkeyEdit))
|
|
{
|
|
// Migrate hklm setting to hkcu
|
|
HKEY hkeySrc;
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_DEFAULT_MHTML_EDITOR, 0, KEY_READ, &hkeySrc))
|
|
{
|
|
HKEY hkeyDest;
|
|
if (ERROR_SUCCESS == RegCreateKey(HKEY_CURRENT_USER, REGSTR_PATH_DEFAULT_MHTML_EDITOR, &hkeyDest))
|
|
{
|
|
SHCopyKey(hkeySrc, NULL, hkeyDest, 0);
|
|
hkeyEdit = hkeyDest;
|
|
}
|
|
RegCloseKey(hkeySrc);
|
|
}
|
|
}
|
|
|
|
if (hkeyEdit)
|
|
{
|
|
// If the mhtml editor has changed, copy it into the mhtml openwithlist
|
|
DWORD dwType;
|
|
WCHAR szCurrent[MAX_PATH];
|
|
DWORD cb = sizeof(szCurrent);
|
|
if (ERROR_SUCCESS == SHGetValue(hkeyEdit, L"shell\\edit\\command", NULL, &dwType, szCurrent, &cb) &&
|
|
dwType == REG_SZ)
|
|
{
|
|
WCHAR szLast[MAX_PATH];
|
|
DWORD cb = sizeof(szLast);
|
|
if (ERROR_SUCCESS != SHGetValue(hkeyEdit, NULL, L"Last", &dwType, szLast, &cb) ||
|
|
(dwType == REG_SZ && StrCmp(szLast, szCurrent) != 0))
|
|
{
|
|
// Copy the MHTML editor into our MHTML openwithlist
|
|
_AddToOpenWithList(hkeyEdit, L"edit", L".mhtml");
|
|
|
|
// Remember that we migrated this key. Copying to the openwithlist can be slow
|
|
// because we need to hit the disk to verify the exe name. So it's worth the effort
|
|
// to avoid doing this unecessarily.
|
|
SHSetValue(hkeyEdit, NULL, L"Last", REG_SZ, szCurrent, CbFromCch(lstrlen(szCurrent) +1));
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkeyEdit);
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Check registry for the friendly name of the default html editor. This
|
|
// editor is configured by inetcpl or by office 2000. If necessary, the
|
|
// associated verb is moved to the OpenWithList for .htm files.
|
|
//--------------------------------------------------------------------------
|
|
void CInternetToolbar::CEditVerb::InitDefaultEditor(HKEY hkey)
|
|
{
|
|
//
|
|
// First see if the default editor is in HKCU
|
|
//
|
|
HKEY hkeyEdit = hkey;
|
|
if (hkey ||
|
|
ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_DEFAULT_HTML_EDITOR,
|
|
0, KEY_READ | KEY_WRITE, &hkeyEdit))
|
|
{
|
|
//
|
|
// See if we have a default editor selected
|
|
//
|
|
WCHAR szBuf[MAX_PATH];
|
|
DWORD cbBuf = sizeof(szBuf);
|
|
if (ERROR_SUCCESS == SHGetValue(hkeyEdit, NULL, L"Description", NULL, szBuf, &cbBuf))
|
|
{
|
|
// We got it! Save the friendly name.
|
|
PathRemoveBlanks(szBuf);
|
|
SetStr(&_pszDefaultEditor, szBuf);
|
|
}
|
|
else
|
|
{
|
|
// No default editor description, so check to see if an edit verb was added.
|
|
// (Office/inetcpl deletes the description key to signal to us that something changed).
|
|
IQueryAssociations *pqa;
|
|
|
|
if (SUCCEEDED(AssocCreate(CLSID_QueryAssociations, IID_PPV_ARG(IQueryAssociations, &pqa))))
|
|
{
|
|
if (SUCCEEDED(pqa->Init(0, NULL, hkeyEdit, NULL)) &&
|
|
( SUCCEEDED(pqa->GetString(ASSOCF_VERIFY, ASSOCSTR_FRIENDLYAPPNAME, L"edit", szBuf, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szBuf))))
|
|
|| SUCCEEDED(pqa->GetString(ASSOCF_VERIFY, ASSOCSTR_FRIENDLYAPPNAME, NULL, szBuf, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szBuf))))))
|
|
{
|
|
PathRemoveBlanks(szBuf);
|
|
|
|
// Save the name of the default editor
|
|
SetStr(&_pszDefaultEditor, szBuf);
|
|
SHSetValue(hkeyEdit, NULL, L"Description", REG_SZ, szBuf, CbFromCch(lstrlen(szBuf) +1));
|
|
|
|
// Add it to our openwithlist for .htm files
|
|
_AddToOpenWithList(hkeyEdit, L"edit", L".htm");
|
|
}
|
|
|
|
pqa->Release();
|
|
}
|
|
}
|
|
|
|
// Close the key if it wasn't passed in
|
|
if (hkeyEdit && NULL == hkey)
|
|
{
|
|
RegCloseKey(hkeyEdit);
|
|
}
|
|
}
|
|
|
|
// During setup, Office places the orginial edit verb in HKLM. We need to copy this to HKCU.
|
|
else if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_DEFAULT_HTML_EDITOR, 0, KEY_READ, &hkeyEdit))
|
|
{
|
|
// Migrate this key into HKCU
|
|
HKEY hkeyDest;
|
|
if (ERROR_SUCCESS == RegCreateKey(HKEY_CURRENT_USER, REGSTR_PATH_DEFAULT_HTML_EDITOR, &hkeyDest))
|
|
{
|
|
SHCopyKey(hkeyEdit, NULL, hkeyDest, 0);
|
|
|
|
// Try again
|
|
InitDefaultEditor(hkeyDest);
|
|
RegCloseKey(hkeyDest);
|
|
}
|
|
RegCloseKey(hkeyEdit);
|
|
}
|
|
|
|
//
|
|
// Check for a default MHTML editor.
|
|
//
|
|
if (hkey == NULL) // Don't do on recursion
|
|
{
|
|
_InitDefaultMHTMLEditor();
|
|
}
|
|
}
|
|
|
|
BOOL _GetAppKey(LPCWSTR pszApp, HKEY *phkApp)
|
|
{
|
|
ASSERT(pszApp && *pszApp);
|
|
WCHAR szKey[MAX_PATH];
|
|
StrCpy(szKey, L"Applications\\");
|
|
StrCatBuff(szKey, pszApp, SIZECHARS(szKey));
|
|
|
|
return (NOERROR == RegOpenKeyEx(
|
|
HKEY_CLASSES_ROOT,
|
|
szKey,
|
|
0L,
|
|
MAXIMUM_ALLOWED,
|
|
phkApp));
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Make sure that notepad is registered in the OpenWithList for .htm files.
|
|
// This is called when this dll is registered (at setup time)
|
|
//--------------------------------------------------------------------------
|
|
void AddNotepadToOpenWithList()
|
|
{
|
|
// Add notepad to the openwith list for .htm files
|
|
HKEY hkeyOpenWith;
|
|
DWORD dwDisp;
|
|
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CLASSES_ROOT, L".htm\\OpenWithList\\notepad.exe", 0, L"",
|
|
REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hkeyOpenWith, &dwDisp))
|
|
{
|
|
// Add the edit verb for notepad
|
|
// if (g_fRunningOnNT) // didn't work on nt4
|
|
// {
|
|
// const WCHAR szPath[] = L"%SystemRoot%\\notepad.exe %1";
|
|
// SHSetValue(HKEY_CLASSES_ROOT, L"Applications\\notepad.exe\\shell\\edit\\command", NULL, REG_EXPAND_SZ, szPath, sizeof(szPath));
|
|
// }
|
|
// else
|
|
{
|
|
WCHAR szPath[MAX_PATH];
|
|
GetWindowsDirectory(szPath, ARRAYSIZE(szPath));
|
|
PathAddBackslash(szPath);
|
|
StrCatBuff(szPath, L"notepad.exe %1", ARRAYSIZE(szPath));
|
|
SHSetValue(HKEY_CLASSES_ROOT, L"Applications\\notepad.exe\\shell\\edit\\command", NULL, REG_SZ, szPath, (lstrlen(szPath)+1) * sizeof(WCHAR));
|
|
}
|
|
|
|
// Add a localizable name for the edit verb
|
|
TCHAR szEditVerb[MAX_PATH];
|
|
int cch = MLLoadShellLangString(IDS_EDITVERB, szEditVerb, ARRAYSIZE(szEditVerb));
|
|
if (cch > 0)
|
|
{
|
|
SHSetValue(HKEY_CLASSES_ROOT, L"Applications\\notepad.exe\\shell\\edit", NULL, REG_SZ, szEditVerb, (cch + 1) * sizeof(WCHAR));
|
|
}
|
|
|
|
RegCloseKey(hkeyOpenWith);
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Returns the friendly name of the default HTML editor
|
|
//--------------------------------------------------------------------------
|
|
LPCTSTR CInternetToolbar::CEditVerb::_GetDefaultEditor()
|
|
{
|
|
// Do a lazy init of the default editor
|
|
if (!_fInitEditor)
|
|
{
|
|
InitDefaultEditor();
|
|
_fInitEditor = TRUE;
|
|
}
|
|
return _pszDefaultEditor;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Gets the path of the exe associated with the verb and stores the
|
|
// result in rVerb. The caller is responsible for freeing the string
|
|
// returned.
|
|
//--------------------------------------------------------------------------
|
|
LPCTSTR CInternetToolbar::CEditVerb::_GetExePath(EDITVERB& rVerb)
|
|
{
|
|
// If we already have the path, simply return it
|
|
if (NULL == rVerb.pszExe)
|
|
{
|
|
ASSERT(rVerb.hkeyProgID);
|
|
TCHAR sz[MAX_PATH];
|
|
if (SUCCEEDED(AssocQueryStringByKey(ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, rVerb.hkeyProgID,
|
|
rVerb.fUseOpenVerb ? NULL : L"edit", sz, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(sz)))))
|
|
rVerb.pszExe = StrDup(sz);
|
|
}
|
|
|
|
return rVerb.pszExe;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Returns TRUE if path of the exe associated with the verb is not found in
|
|
// any of the existing verbs.
|
|
//--------------------------------------------------------------------------
|
|
BOOL CInternetToolbar::CEditVerb::_IsUnique(EDITVERB& rNewVerb)
|
|
{
|
|
// Get the friendly name of the new element
|
|
LPCTSTR pszNewDesc = _GetDescription(rNewVerb);
|
|
if (NULL == pszNewDesc)
|
|
{
|
|
// Executable must not exist
|
|
return FALSE;
|
|
}
|
|
|
|
// Scan existing elements for the same executable
|
|
for (UINT i=0; i < _nElements; ++i)
|
|
{
|
|
LPCTSTR pszDesc = _GetDescription(_pVerb[i]);
|
|
if (pszDesc && (StrCmpI(pszNewDesc, pszDesc) == 0))
|
|
{
|
|
// Match found, so free the friendly name for the new verb
|
|
SetStr(&rNewVerb.pszDesc, NULL);
|
|
|
|
// If the new item shows its icon on the button, make the duplicate
|
|
// do the same.
|
|
if (rNewVerb.fShowIcon)
|
|
{
|
|
_pVerb[i].fShowIcon = TRUE;
|
|
_nDefault = i;
|
|
}
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Some programs such as msothmed.exe act as stubs that redirect the edit
|
|
// command to the appropriate executable. This function returns true if
|
|
// the path contains the name of a known stub.
|
|
//--------------------------------------------------------------------------
|
|
BOOL CInternetToolbar::CEditVerb::_IsHtmlStub
|
|
(
|
|
LPCWSTR pszPath
|
|
)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
|
|
// Get the MULTISZ list of known redirectors
|
|
TCHAR szRedir[MAX_PATH];
|
|
ZeroInit(szRedir, ARRAYSIZE(szRedir)); // Protect against non-multisz strings in the reg
|
|
DWORD dwType;
|
|
DWORD cb = sizeof(szRedir) - 4;
|
|
if (ERROR_SUCCESS != SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_PATH_DEFAULT_HTML_EDITOR, L"Stubs", &dwType, szRedir, &cb))
|
|
{
|
|
// Nothing in registry, so default to ignore the Office redirector
|
|
StrCpyN(szRedir, L"msohtmed.exe\0", ARRAYSIZE(szRedir));
|
|
}
|
|
|
|
// See if the path contains the name of a redirectors
|
|
// Note that PathFindFileName doesn't work well for pathes with parameters so we just
|
|
// check for the exe name in the path)
|
|
for (LPTSTR p = szRedir; *p != NULL; p += lstrlen(p) + 1)
|
|
{
|
|
if (StrStrI(pszPath, p))
|
|
{
|
|
fRet = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Adds a new edit verb. Returns a pointer to the new verb if it
|
|
// successfully added.
|
|
//--------------------------------------------------------------------------
|
|
CInternetToolbar::CEditVerb::EDITVERB* CInternetToolbar::CEditVerb::_Add
|
|
(
|
|
HKEY hkeyProgID, // location of of verb
|
|
BOOL fPermitOpenVerb, // permit open as well as edit verb
|
|
BOOL fCheckForOfficeApp,// redirect to office app
|
|
BOOL fShowIcon // if button face icon should be customized
|
|
)
|
|
{
|
|
EDITVERB* pNewVerb = NULL;
|
|
|
|
if (hkeyProgID)
|
|
{
|
|
BOOL fUseOpenVerb = FALSE;
|
|
|
|
//
|
|
// See if an appropriate verb exists.
|
|
//
|
|
TCHAR szCommand[MAX_PATH];
|
|
HRESULT hr = AssocQueryStringByKey(0, ASSOCSTR_COMMAND, hkeyProgID, L"edit", szCommand, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szCommand)));
|
|
if (FAILED(hr) && fPermitOpenVerb)
|
|
{
|
|
hr = AssocQueryStringByKey(0, ASSOCSTR_COMMAND, hkeyProgID, NULL, szCommand, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szCommand)));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
fUseOpenVerb = TRUE;
|
|
}
|
|
}
|
|
|
|
// If no verb or if this is the office redirector, ignore this progid
|
|
// Otherwise we can get two entries that do the same thing.
|
|
if (FAILED(hr) || _IsHtmlStub(szCommand))
|
|
{
|
|
RegCloseKey(hkeyProgID);
|
|
return NULL;
|
|
}
|
|
|
|
if (fCheckForOfficeApp)
|
|
{
|
|
ASSERT(*szCommand);
|
|
|
|
//
|
|
// HACK: Office2000 needs us to call a special proxy to get around thier DDE bugs and
|
|
// to check the HTML document for the name of the original document. These problems
|
|
// should be fixed in the apps themselves.
|
|
//
|
|
// So if this is an office app, we will redirect to the appropriate progid. Note that
|
|
// we don't need to do this if a progid was from the html meta tag because this progid
|
|
// already supports the proxy.
|
|
//
|
|
struct OfficeHackery {LPCWSTR pszApp; LPCWSTR pszProgID;};
|
|
|
|
// Must not have been a progid passed in.
|
|
static const OfficeHackery exeToProgID[] =
|
|
{
|
|
{L"winword", L"Word.Document"},
|
|
{L"excel", L"Excel.Sheet"},
|
|
{L"powerpnt", L"PowerPoint.Slide"},
|
|
{L"msaccess", L"Access.Application"},
|
|
{L"frontpg", L"FrontPage.Editor.Document"},
|
|
};
|
|
|
|
for (int i=0; i < ARRAYSIZE(exeToProgID); ++i)
|
|
{
|
|
if (StrStrI(szCommand, exeToProgID[i].pszApp))
|
|
{
|
|
// Match found!
|
|
HKEY hkeyOffice = NULL;
|
|
if (SUCCEEDED(AssocQueryKey(0, ASSOCKEY_SHELLEXECCLASS, exeToProgID[i].pszProgID, NULL, &hkeyOffice)))
|
|
{
|
|
// Redirect to the office progid
|
|
RegCloseKey(hkeyProgID);
|
|
hkeyProgID = hkeyOffice;
|
|
|
|
// The office apps always use the open verb
|
|
fUseOpenVerb = TRUE;
|
|
|
|
// The icon is shown on the button face for office apps
|
|
fShowIcon = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
EDITVERB newVerb = {0};
|
|
newVerb.hkeyProgID = hkeyProgID;
|
|
newVerb.fUseOpenVerb = fUseOpenVerb;
|
|
newVerb.fShowIcon = fShowIcon;
|
|
|
|
// Ignore it if we have another verb to the same exe.
|
|
if (!_IsUnique(newVerb))
|
|
{
|
|
RegCloseKey(hkeyProgID);
|
|
}
|
|
else
|
|
{
|
|
EDITVERB* pVerbsNew;
|
|
if (_pVerb == NULL)
|
|
{
|
|
pVerbsNew = (EDITVERB*)LocalAlloc(LPTR, sizeof(EDITVERB));
|
|
}
|
|
else
|
|
{
|
|
pVerbsNew = (EDITVERB*)LocalReAlloc(_pVerb, (_nElements+1) * sizeof(EDITVERB), LMEM_MOVEABLE | LMEM_ZEROINIT);
|
|
}
|
|
|
|
if (pVerbsNew == NULL)
|
|
{
|
|
RegCloseKey(hkeyProgID);
|
|
}
|
|
else
|
|
{
|
|
_pVerb = pVerbsNew;
|
|
pNewVerb = &_pVerb[_nElements];
|
|
*pNewVerb = newVerb;
|
|
|
|
//
|
|
// If the description of the executable matches that of the default editor, make
|
|
// it our default edit verb. If we are not checking for the office app, we
|
|
// can assume that this verb was from a progid in an html file and we will also
|
|
// make it our default.
|
|
//
|
|
LPCWSTR pszDefDesc = _GetDefaultEditor();
|
|
LPCWSTR pszNewDesc = _GetDescription(*pNewVerb);
|
|
|
|
if (!fCheckForOfficeApp ||
|
|
(pszDefDesc && pszNewDesc && StrCmp(pszDefDesc, pNewVerb->pszDesc) == 0))
|
|
{
|
|
_nDefault = _nElements;
|
|
}
|
|
|
|
++_nElements;
|
|
}
|
|
}
|
|
}
|
|
|
|
return pNewVerb;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Adds a new edit verb. Returns TRUE if a verb was successfully added.
|
|
//--------------------------------------------------------------------------
|
|
BOOL CInternetToolbar::CEditVerb::Add
|
|
(
|
|
LPTSTR pszProgID // program id or file extension associated with verb
|
|
)
|
|
{
|
|
ASSERT(pszProgID);
|
|
|
|
BOOL fRet = FALSE;
|
|
BOOL fFileExt = (pszProgID[0] == TEXT('.'));
|
|
|
|
//
|
|
// Open the associated reg key and try to add it to our list of verbs
|
|
//
|
|
BOOL fUseOpenVerb = FALSE;
|
|
HKEY hkeyProgID = NULL;
|
|
BOOL fPermitOpenVerb = !fFileExt;
|
|
BOOL fShowIcon = !fFileExt; // If a progid was passed in, we will show the icon on the button face
|
|
|
|
if (SUCCEEDED(AssocQueryKey(0, ASSOCKEY_SHELLEXECCLASS, pszProgID, NULL, &hkeyProgID)))
|
|
{
|
|
EDITVERB* pNewVerb = _Add(hkeyProgID, fPermitOpenVerb, fFileExt, fShowIcon);
|
|
if (pNewVerb)
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If a file extension was passed in, we also add the alternative editors from the
|
|
// OpenWithList
|
|
//
|
|
if (fFileExt)
|
|
{
|
|
WCHAR szOpenWith[MAX_PATH];
|
|
StrCpyN(szOpenWith, pszProgID, ARRAYSIZE(szOpenWith));
|
|
StrCatBuff(szOpenWith, L"\\OpenWithList", ARRAYSIZE(szOpenWith));
|
|
|
|
HKEY hkeyOpenWithList;
|
|
|
|
// See if there is an OpenWithList
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szOpenWith, 0, KEY_READ, &hkeyOpenWithList))
|
|
{
|
|
DWORD dwIndex = 0;
|
|
DWORD dwSize = ARRAYSIZE(szOpenWith);
|
|
HKEY hkeyOpenWith = NULL;
|
|
while (ERROR_SUCCESS == RegEnumKeyEx(hkeyOpenWithList, dwIndex, szOpenWith, &dwSize, NULL, NULL, NULL, NULL))
|
|
{
|
|
if (_GetAppKey(szOpenWith, &hkeyOpenWith))
|
|
{
|
|
// We only permit the edit verbs from here
|
|
EDITVERB* pNewVerb = _Add(hkeyOpenWith, FALSE, TRUE, FALSE);
|
|
if (pNewVerb)
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
|
|
++dwIndex;
|
|
|
|
// Note that we don't close hkeyOpenWith here. It is either closed if it was not added, or
|
|
// it will be closed later.
|
|
}
|
|
else
|
|
{
|
|
// Invalid entry, so try to fix it (may be old format):
|
|
//
|
|
// In IE5.0 we use to store the friendly names of apps in the openwithlist. For shell compatibility, we need
|
|
// to convert these entries to store the exe name instead:
|
|
//
|
|
// ----> permanent entries are stored un HKCR
|
|
// HKCR
|
|
// \.Ext
|
|
// \OpenWithList
|
|
// \app.exe
|
|
//
|
|
// ----> and applications or the system can write app association here
|
|
// \Applications
|
|
// \APP.EXE
|
|
// \shell...
|
|
// \foo.exe
|
|
// \shell...
|
|
//
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkeyOpenWithList, szOpenWith, 0, KEY_READ, &hkeyOpenWith))
|
|
{
|
|
_AddToOpenWithList(hkeyOpenWith, L"edit", L".htm");
|
|
|
|
// Remove the invalid entry
|
|
if (ERROR_SUCCESS != SHDeleteKey(hkeyOpenWith, L""))
|
|
{
|
|
// NOTE (andrewgu): ie5.5 b#108551 - on locked-down nt5 this will fail
|
|
// and if dwIndex is not incremented, will result in an infinite loop.
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey(hkeyOpenWith);
|
|
}
|
|
}
|
|
dwSize = ARRAYSIZE(szOpenWith);
|
|
}
|
|
|
|
RegCloseKey(hkeyOpenWithList);
|
|
}
|
|
|
|
//
|
|
// If a ".htm" or ".html" was passed in, add our default html editor
|
|
//
|
|
if ((StrCmpI(pszProgID, L".htm") == 0 || StrCmpI(pszProgID, L".html") == 0) &&
|
|
_GetDefaultEditor())
|
|
{
|
|
HKEY hkeyDefault;
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_DEFAULT_HTML_EDITOR, 0, KEY_READ, &hkeyDefault))
|
|
{
|
|
if (_Add(hkeyDefault, TRUE, TRUE, FALSE))
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Returns the tooltip for the default edit verb
|
|
//--------------------------------------------------------------------------
|
|
BOOL CInternetToolbar::CEditVerb::GetToolTip
|
|
(
|
|
LPTSTR pszToolTip,
|
|
UINT cchMax,
|
|
BOOL fStripAmpersands
|
|
)
|
|
{
|
|
if (_nElements == 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Use the menu text for the tooltip.
|
|
_FormatMenuText(_nDefault);
|
|
|
|
// Copy text stripping out any ampersands
|
|
LPWSTR pszDest = pszToolTip;
|
|
LPWSTR pszSrc = _GetVerb(_nDefault).pszMenuText;
|
|
if (0 < cchMax)
|
|
{
|
|
// Leave room for the null terminator
|
|
while (0 < --cchMax)
|
|
{
|
|
// strip out '&'
|
|
if (fStripAmpersands)
|
|
{
|
|
while (*pszSrc == L'&')
|
|
{
|
|
++pszSrc;
|
|
}
|
|
}
|
|
|
|
if ( !(*pszDest++ = *pszSrc++) )
|
|
{
|
|
--pszDest;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (0 == cchMax)
|
|
*pszDest = L'\0';
|
|
|
|
ASSERT(*pszDest == 0);
|
|
|
|
//
|
|
// In some locals, the accelerator is identified in brackets at the
|
|
// end of the string, so if we strip ampersands, we strip these too.
|
|
//
|
|
if (fStripAmpersands && --pszDest >= pszToolTip && *pszDest == L')')
|
|
{
|
|
while (--pszDest >= pszToolTip)
|
|
{
|
|
if (*pszDest == L'(')
|
|
{
|
|
*pszDest = L'\0';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// "Lazy-fetches" the verb info, and returns the desired info.
|
|
//--------------------------------------------------------------------------
|
|
CInternetToolbar::CEditVerb::EDITVERB& CInternetToolbar::CEditVerb::_GetVerb(UINT nIndex)
|
|
{
|
|
ASSERT(nIndex < _nElements);
|
|
|
|
// We fetch the info when first asked for it.
|
|
if (!_pVerb[nIndex].fInit)
|
|
{
|
|
_FetchInfo(nIndex);
|
|
_pVerb[nIndex].fInit = TRUE;
|
|
}
|
|
return _pVerb[nIndex];
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Gets the name of the app associated with the verb.
|
|
//--------------------------------------------------------------------------
|
|
LPCTSTR CInternetToolbar::CEditVerb::_GetDescription(EDITVERB& rVerb)
|
|
{
|
|
// If we already have a description, we are done
|
|
if (NULL == rVerb.pszDesc)
|
|
{
|
|
ASSERT(rVerb.hkeyProgID);
|
|
|
|
TCHAR sz[MAX_PATH];
|
|
if (SUCCEEDED(AssocQueryStringByKey(ASSOCF_VERIFY, ASSOCSTR_FRIENDLYAPPNAME, rVerb.hkeyProgID,
|
|
rVerb.fUseOpenVerb ? NULL : L"edit", sz, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(sz)))))
|
|
{
|
|
rVerb.pszDesc = StrDup(sz);
|
|
if (rVerb.pszDesc)
|
|
{
|
|
// Remove preceeding and trailing blanks
|
|
PathRemoveBlanks(rVerb.pszDesc);
|
|
}
|
|
}
|
|
}
|
|
|
|
return rVerb.pszDesc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Reads the info associated with the progid at the given index. This
|
|
// function allows us to do a lazy fetch of the info when requested.
|
|
//--------------------------------------------------------------------------
|
|
void CInternetToolbar::CEditVerb::_FetchInfo(UINT nIndex)
|
|
{
|
|
ASSERT(nIndex < _nElements);
|
|
ASSERT(_pVerb[nIndex].hkeyProgID != NULL);
|
|
|
|
EDITVERB& rVerb = _pVerb[nIndex];
|
|
|
|
//
|
|
// Get the path to the edit verb's exe
|
|
//
|
|
if (_GetExePath(rVerb))
|
|
{
|
|
ASSERT(rVerb.pszExe);
|
|
|
|
// Note that we fetched the friendly name earlier
|
|
ASSERT(rVerb.pszDesc);
|
|
|
|
// Now get the icon
|
|
rVerb.iIcon = Shell_GetCachedImageIndex(rVerb.pszExe, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
rVerb.iIcon = -1;
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// SetMSAAMenuInfo()
|
|
//
|
|
// Fills in MSAAMenuInfo part of EDITVERB from the other fields of the rVerb
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CInternetToolbar::CEditVerb::_SetMSAAMenuInfo( EDITVERB& rVerb )
|
|
{
|
|
|
|
#ifdef UNICODE
|
|
|
|
// If we're UNICODE, we can just refer to the m_pName of the MenuEntry itself...
|
|
rVerb.m_MSAA.m_CharLen = lstrlen( rVerb.pszMenuText );
|
|
rVerb.m_MSAA.m_pWStr = rVerb.pszMenuText;
|
|
|
|
#else // UNICODE
|
|
|
|
// If we're ANSI, need to create a UNICODE string for the MSAA text...
|
|
|
|
// Call MultiByteToWideChar first with 0 to get the size needed. (Assumes
|
|
// m_pName is ASCII NUL terminated - cChars will include the terminating NUL)
|
|
int cChars = MultiByteToWideChar( CP_ACP, 0, rVerb.pszMenuText, -1, NULL, 0 );
|
|
|
|
// Don't want to include NUL in character length, so subtract one...
|
|
rVerb.m_MSAA.m_CharLen = cChars - 1;
|
|
|
|
// Now call MultiByteToWideChar to do the conversion.
|
|
// MultiByteToWideChar adds the terminating WIDE-NUL for us, so we don't have to
|
|
// add it explicitly...
|
|
rVerb.m_MSAA.m_pWStr = new WCHAR [ cChars ];
|
|
if (rVerb.m_MSAA.m_pWStr)
|
|
{
|
|
// Note - we don't delete[] the above allocated memory in this sample
|
|
// code because we know that in this case it will be reclaimed by the system on
|
|
// exit and won't give a leak.
|
|
MultiByteToWideChar( CP_ACP, 0, rVerb.pszMenuText, -1, rVerb.m_MSAA.m_pWStr, cChars );
|
|
}
|
|
|
|
#endif // UNICODE
|
|
|
|
// Finally, add MSAAINFO signature...
|
|
rVerb.m_MSAA.m_MSAASig = MSAA_MENU_SIG;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// ClearMSAAMenuInfo()
|
|
//
|
|
// Clean up MSAAMenuInfo - specifically, release the allocated
|
|
// UNICODE string, if appropriate...
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CInternetToolbar::CEditVerb::_ClearMSAAMenuInfo( EDITVERB& rVerb )
|
|
{
|
|
// Paranoia - clear signature...
|
|
rVerb.m_MSAA.m_MSAASig = 0;
|
|
|
|
#ifdef UNICODE
|
|
|
|
// We're unicode - nothing to do, since we didn't allocate anything.
|
|
|
|
#else // UNICODE
|
|
|
|
// We're ANSI - release allocated UNICODE string...
|
|
delete [] rVerb.m_MSAA.m_pWStr;
|
|
|
|
#endif // UNICODE
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Shows the edit pop-up menu.
|
|
//--------------------------------------------------------------------------
|
|
BOOL CInternetToolbar::CEditVerb::ShowEditMenu(POINT pt, HWND hwnd, LPTSTR pszURL)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
HMENU hmEdit = CreatePopupMenu();
|
|
|
|
if (hmEdit)
|
|
{
|
|
UINT idCmd = FCIDM_EDITFIRST;
|
|
UINT nMax = FCIDM_EDITLAST - FCIDM_EDITFIRST;
|
|
|
|
// Add each verb to the menu
|
|
for (UINT i=0; i<_nElements && i < nMax; ++i)
|
|
{
|
|
EDITVERB& rVerb = _GetVerb(i);
|
|
_FormatMenuText(i);
|
|
rVerb.idCmd = idCmd;
|
|
AppendMenu(hmEdit, MF_OWNERDRAW, idCmd, (LPCTSTR) &rVerb );
|
|
|
|
// Fix up MSAAMenuInfo part...
|
|
_SetMSAAMenuInfo( rVerb );
|
|
|
|
++idCmd;
|
|
}
|
|
|
|
// Temporarily subclass the hwnd to intercept the owner-draw messages
|
|
if (SetProp(hwnd, SZ_EDITVERB_PROP, this))
|
|
{
|
|
ASSERT(!_lpfnOldWndProc);
|
|
_lpfnOldWndProc = (WNDPROC) SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) _WndProc);
|
|
|
|
idCmd = ITBar_TrackPopupMenuEx(hmEdit, TPM_RETURNCMD, pt.x, pt.y, hwnd, NULL);
|
|
|
|
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)_lpfnOldWndProc);
|
|
_lpfnOldWndProc = NULL;
|
|
RemoveProp(hwnd, SZ_EDITVERB_PROP);
|
|
|
|
if (InRange(idCmd, FCIDM_EDITFIRST, FCIDM_EDITLAST))
|
|
{
|
|
// Execute the selected edit verb
|
|
_Edit(pszURL, idCmd - FCIDM_EDITFIRST);
|
|
}
|
|
}
|
|
|
|
DestroyMenu(hmEdit);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Creates a menu string from the progid's description
|
|
//--------------------------------------------------------------------------
|
|
void CInternetToolbar::CEditVerb::_FormatMenuText(UINT nIndex)
|
|
{
|
|
ASSERT(nIndex < _nElements);
|
|
|
|
EDITVERB& rVerb = _GetVerb(nIndex);
|
|
if (rVerb.pszMenuText == NULL)
|
|
{
|
|
if (_GetDescription(rVerb))
|
|
{
|
|
TCHAR szFormat[100];
|
|
TCHAR szMenuText[200];
|
|
|
|
MLLoadString(IDS_EDITWITH, szFormat, ARRAYSIZE(szFormat));
|
|
wnsprintf(szMenuText, ARRAYSIZE(szMenuText), szFormat, rVerb.pszDesc);
|
|
SetStr(&((EDITVERB&)rVerb).pszMenuText, szMenuText);
|
|
}
|
|
else
|
|
{
|
|
// Things are really messed up
|
|
ASSERT(FALSE);
|
|
SetStr(&((EDITVERB&)rVerb).pszMenuText, TEXT(""));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Executes the edit verb indicated by nIndex.
|
|
//--------------------------------------------------------------------------
|
|
void CInternetToolbar::CEditVerb::_Edit
|
|
(
|
|
LPCTSTR pszURL, // url assocated with the verb
|
|
UINT nIndex // verb to execute
|
|
)
|
|
{
|
|
ASSERT(pszURL);
|
|
|
|
if (nIndex >= _nElements)
|
|
{
|
|
return;
|
|
}
|
|
|
|
EDITVERB& rVerb = _pVerb[nIndex];
|
|
int fMask = SEE_MASK_CLASSKEY;
|
|
|
|
SHELLEXECUTEINFO sei = {0};
|
|
|
|
TCHAR szCacheFileName[MAX_PATH + MAX_URL_STRING + 2];
|
|
memset(szCacheFileName, 0, sizeof(szCacheFileName));
|
|
|
|
if (PathIsURL(pszURL))
|
|
{
|
|
// We pass the url if the app has register that it wants this
|
|
if ((WhichPlatform() == PLATFORM_BROWSERONLY) && DoesAppWantUrl(rVerb.pszExe))
|
|
{
|
|
//
|
|
// Old versions of shell32 (PLATFORM_BROWSERONLY) ignore the SEE_MASK_FILEANDURL
|
|
// flag, so on these platforms we check ourselves to see if the app
|
|
// wants the url instead of the cache file name.
|
|
//
|
|
StrCpyN(szCacheFileName, pszURL, ARRAYSIZE(szCacheFileName));
|
|
sei.lpFile = szCacheFileName;
|
|
}
|
|
else
|
|
{
|
|
// (reinerf)
|
|
// Some apps (FrontPad, Office99, etc) want the URL passed to
|
|
// them instead of the cache filename. We therefore create a string
|
|
// that has the URL name after the null:
|
|
//
|
|
// "CacheFileName/0UrlName"
|
|
//
|
|
// and pass it as the lpFile parameter to shellexecute.
|
|
// We also pass SEE_MASK_FILEANDURL, so shellexecute can
|
|
// recognize this case.
|
|
//
|
|
int iLength;
|
|
|
|
if (FAILED(URLToCacheFile(pszURL, szCacheFileName, ARRAYSIZE(szCacheFileName))))
|
|
{
|
|
// Frontpage express crashes if we pass a null file name, so if the app doesn't
|
|
// prefer the url instead, we bail.
|
|
if (!DoesAppWantUrl(rVerb.pszExe))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
iLength = lstrlen(szCacheFileName);
|
|
|
|
// copy in the URL name
|
|
StrCpyN(&szCacheFileName[iLength + 1], pszURL, ARRAYSIZE(szCacheFileName) - (iLength + 1));
|
|
|
|
// add the mask so shellexecute knows to check for the URL, if necessary.
|
|
fMask |= SEE_MASK_FILEANDURL;
|
|
sei.lpFile = szCacheFileName;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Not a URL, so pass the filename
|
|
StrCpyN(szCacheFileName, pszURL, ARRAYSIZE(szCacheFileName));
|
|
sei.lpFile = szCacheFileName;
|
|
}
|
|
|
|
// Hack for IE5 bug 50033 - Can remove when fpxpress fixes mru buffer overrun
|
|
_GetExePath(rVerb);
|
|
if(StrStr(rVerb.pszExe, TEXT("fpxpress.exe")) != NULL)
|
|
szCacheFileName[256] = TEXT('\0');
|
|
|
|
sei.cbSize = sizeof(SHELLEXECUTEINFO);
|
|
sei.fMask = fMask;
|
|
sei.hwnd = NULL;
|
|
sei.lpVerb = rVerb.fUseOpenVerb ? NULL : TEXT("edit");
|
|
// sei.lpFile = szCacheFileName;
|
|
// sei.lpParameters = NULL;
|
|
sei.lpDirectory = NULL;
|
|
sei.nShow = SW_SHOWNORMAL;
|
|
sei.hInstApp = NULL;
|
|
sei.hkeyClass= rVerb.hkeyProgID;
|
|
|
|
//
|
|
// The office guys want us to call a special proxy to get around some DDE problems
|
|
// and to sniff the html file for the original document name. Hackers! So let's
|
|
// see if it is registered.
|
|
//
|
|
HKEY hkeyProxy = NULL;
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(rVerb.hkeyProgID, TEXT("HTML Handler"), 0, KEY_READ, &hkeyProxy))
|
|
{
|
|
DWORD cch;
|
|
if (SUCCEEDED(AssocQueryStringByKey(0, ASSOCSTR_COMMAND, hkeyProxy, L"edit", NULL, &cch)))
|
|
{
|
|
sei.lpVerb = L"edit";
|
|
sei.hkeyClass = hkeyProxy;
|
|
}
|
|
else if (SUCCEEDED(AssocQueryStringByKey(0, ASSOCSTR_COMMAND, hkeyProxy, NULL, NULL, &cch)))
|
|
{
|
|
sei.lpVerb = NULL;
|
|
sei.hkeyClass = hkeyProxy;
|
|
}
|
|
}
|
|
|
|
ShellExecuteEx(&sei);
|
|
|
|
if (hkeyProxy)
|
|
{
|
|
RegCloseKey(hkeyProxy);
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// This window procedure intercepts owner-draw menu messages when the edit
|
|
// pop-up menu is displayed.
|
|
//--------------------------------------------------------------------------
|
|
LRESULT CALLBACK CInternetToolbar::CEditVerb::_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CEditVerb* pThis = (CEditVerb*)GetProp(hwnd, SZ_EDITVERB_PROP);
|
|
|
|
if (!pThis)
|
|
return DefWindowProcWrap(hwnd, uMsg, wParam, lParam);
|
|
|
|
switch(uMsg)
|
|
{
|
|
case WM_DRAWITEM:
|
|
case WM_MEASUREITEM:
|
|
{
|
|
UINT idCmd;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_DRAWITEM:
|
|
idCmd = ((EDITVERB*)((DRAWITEMSTRUCT*)lParam)->itemData)->idCmd;
|
|
break;
|
|
case WM_MEASUREITEM:
|
|
idCmd = ((EDITVERB*)((MEASUREITEMSTRUCT*)lParam)->itemData)->idCmd;
|
|
break;
|
|
}
|
|
|
|
if (InRange(idCmd, FCIDM_EDITFIRST, FCIDM_EDITLAST))
|
|
{
|
|
// do our own measuring
|
|
UINT index = idCmd - FCIDM_EDITFIRST;
|
|
const EDITVERB& rVerb = pThis->_GetVerb(index);
|
|
|
|
// We don't want the same accelerator on all items,
|
|
// so remove underlines
|
|
WCHAR wzBuf[MAX_PATH];
|
|
UINT cchMax = ARRAYSIZE(wzBuf);
|
|
LPWSTR pszTo = wzBuf;
|
|
LPWSTR pszFrom = rVerb.pszMenuText;
|
|
if (pszFrom)
|
|
{
|
|
while (0 < --cchMax)
|
|
{
|
|
if (*pszFrom == L'&')
|
|
{
|
|
pszFrom++;
|
|
continue;
|
|
}
|
|
|
|
if ( !(*pszTo++ = *pszFrom++) )
|
|
{
|
|
--pszTo;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (0 == cchMax)
|
|
*pszTo = L'\0';
|
|
|
|
//
|
|
// In some locals, the accelerator is identified in brackets at the
|
|
// end of the string, so if we strip ampersands, we strip these too.
|
|
//
|
|
if (--pszTo >= wzBuf && *pszTo == L')')
|
|
{
|
|
while (--pszTo >= wzBuf)
|
|
{
|
|
if (*pszTo == L'(')
|
|
{
|
|
*pszTo = L'\0';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wzBuf[0] = 0;
|
|
}
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_MEASUREITEM:
|
|
MeasureMenuItem((MEASUREITEMSTRUCT *)lParam, wzBuf);
|
|
break;
|
|
case WM_DRAWITEM:
|
|
int iIcon = (rVerb.iIcon != -1) ? rVerb.iIcon : 0;
|
|
DrawMenuItem((LPDRAWITEMSTRUCT)lParam, wzBuf, iIcon);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
default:
|
|
return CallWindowProc(pThis->_lpfnOldWndProc, hwnd, uMsg, wParam, lParam);
|
|
}
|
|
return 0L;
|
|
}
|
|
|
|
#endif // EDIT_HACK
|