|
|
#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
|