781 lines
20 KiB
C++
781 lines
20 KiB
C++
|
#include "priv.h"
|
||
|
#include <varutil.h>
|
||
|
|
||
|
#ifdef ENABLE_CHANNELS
|
||
|
#include "channel.h"
|
||
|
#include "bands.h"
|
||
|
#include "isfband.h"
|
||
|
#include "itbar.h"
|
||
|
#include "qlink.h"
|
||
|
#define WANT_CBANDSITE_CLASS
|
||
|
#include "bandsite.h"
|
||
|
#include "resource.h"
|
||
|
#include "deskbar.h"
|
||
|
#include "dpastuff.h"
|
||
|
|
||
|
#include "dbapp.h"
|
||
|
#include "chanbar.h"
|
||
|
|
||
|
#include "subsmgr.h"
|
||
|
#include "chanmgr.h"
|
||
|
#include "chanmgrp.h"
|
||
|
|
||
|
#include "mluisupp.h"
|
||
|
|
||
|
void FrameTrack(HDC hdc, LPRECT prc, UINT uFlags);
|
||
|
|
||
|
HRESULT Channel_GetFolder(LPTSTR pszPath, int cchPath)
|
||
|
{
|
||
|
TCHAR szChannel[MAX_PATH];
|
||
|
TCHAR szFav[MAX_PATH];
|
||
|
ULONG cbChannel = sizeof(szChannel);
|
||
|
|
||
|
if (SHGetSpecialFolderPath(NULL, szFav, CSIDL_FAVORITES, TRUE))
|
||
|
{
|
||
|
//
|
||
|
// Get the potentially localized name of the Channel folder from the
|
||
|
// registry if it is there. Otherwise just read it from the resource.
|
||
|
// Then tack this on the favorites path.
|
||
|
//
|
||
|
|
||
|
if (ERROR_SUCCESS != SHRegGetUSValue(L"Software\\Microsoft\\Windows\\CurrentVersion",
|
||
|
L"ChannelFolderName", NULL, (void*)szChannel,
|
||
|
&cbChannel, TRUE, NULL, 0))
|
||
|
{
|
||
|
MLLoadString(IDS_CHANNEL, szChannel, ARRAYSIZE(szChannel));
|
||
|
}
|
||
|
|
||
|
PathCombine(pszPath, szFav, szChannel);
|
||
|
|
||
|
//
|
||
|
// For IE5+ use the channels dir if it exists - else use favorites
|
||
|
//
|
||
|
if (!PathFileExists(pszPath))
|
||
|
StrCpyN(pszPath, szFav, cchPath);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
LPITEMIDLIST Channel_GetFolderPidl()
|
||
|
{
|
||
|
LPITEMIDLIST pidl = NULL;
|
||
|
TCHAR szPath[MAX_PATH];
|
||
|
if (SUCCEEDED(Channel_GetFolder(szPath, ARRAYSIZE(szPath))))
|
||
|
{
|
||
|
pidl = ILCreateFromPath(szPath);
|
||
|
if (!pidl && CreateDirectory(szPath, NULL)) {
|
||
|
pidl = ILCreateFromPath(szPath);
|
||
|
}
|
||
|
}
|
||
|
return pidl;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT ChannelBand_CreateInstance(IUnknown** ppunk)
|
||
|
{
|
||
|
*ppunk = NULL;
|
||
|
|
||
|
HRESULT hr = E_OUTOFMEMORY;
|
||
|
LPITEMIDLIST pidl = Channel_GetFolderPidl();
|
||
|
if (pidl)
|
||
|
{
|
||
|
IFolderBandPriv *pfbp;
|
||
|
hr = CISFBand_CreateEx(NULL, pidl, IID_PPV_ARG(IFolderBandPriv, &pfbp));
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = pfbp->SetCascade(TRUE);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = pfbp->QueryInterface(IID_PPV_ARG(IUnknown, ppunk));
|
||
|
}
|
||
|
pfbp->Release();
|
||
|
}
|
||
|
ILFree(pidl);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Navigates the left browser pane to the channels directory.
|
||
|
//
|
||
|
void NavigateBrowserBarToChannels(IWebBrowser2* pwb)
|
||
|
{
|
||
|
ASSERT(pwb);
|
||
|
|
||
|
IChannelMgrPriv* pIChannelMgrPriv;
|
||
|
|
||
|
if (SUCCEEDED(CoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER,
|
||
|
IID_IChannelMgrPriv, (void**)&pIChannelMgrPriv)))
|
||
|
{
|
||
|
ASSERT(pIChannelMgrPriv);
|
||
|
|
||
|
LPITEMIDLIST pidl;
|
||
|
|
||
|
if (SUCCEEDED(pIChannelMgrPriv->GetChannelFolder(&pidl, IChannelMgrPriv::CF_CHANNEL)))
|
||
|
{
|
||
|
ASSERT(pidl);
|
||
|
|
||
|
VARIANT varPath;
|
||
|
|
||
|
if (SUCCEEDED(InitVariantFromIDList(&varPath, pidl)))
|
||
|
{
|
||
|
VARIANT varFlags;
|
||
|
|
||
|
varFlags.vt = VT_I4;
|
||
|
varFlags.lVal = navBrowserBar;
|
||
|
|
||
|
pwb->Navigate2(&varPath, &varFlags, PVAREMPTY, PVAREMPTY, PVAREMPTY);
|
||
|
|
||
|
VariantClear(&varPath);
|
||
|
}
|
||
|
|
||
|
ILFree(pidl);
|
||
|
}
|
||
|
|
||
|
pIChannelMgrPriv->Release();
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDAPI NavigateToPIDL(IWebBrowser2* pwb, LPCITEMIDLIST pidl)
|
||
|
{
|
||
|
ASSERT(pwb);
|
||
|
ASSERT(pidl);
|
||
|
|
||
|
VARIANT varThePidl;
|
||
|
HRESULT hr = InitVariantFromIDList(&varThePidl, pidl);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = pwb->Navigate2(&varThePidl, PVAREMPTY, PVAREMPTY, PVAREMPTY, PVAREMPTY);
|
||
|
VariantClear(&varThePidl); // Needed to free the copy of the PIDL in varThePidl.
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Implements the IE4 channel quick launch shell control file functionality.
|
||
|
// This gets called from shdoc401 on pre-NT5 platforms and from shell32 on
|
||
|
// Nt5 or greater.
|
||
|
//
|
||
|
HRESULT Channel_QuickLaunch(void)
|
||
|
{
|
||
|
IWebBrowser2* pIWebBrowser2;
|
||
|
|
||
|
HRESULT hr = Channels_OpenBrowser(&pIWebBrowser2, FALSE);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
ASSERT(pIWebBrowser2);
|
||
|
|
||
|
NavigateBrowserBarToChannels(pIWebBrowser2);
|
||
|
|
||
|
LPITEMIDLIST pidl;
|
||
|
TCHAR szURL[MAX_URL_STRING] = TEXT("");
|
||
|
|
||
|
GetFirstUrl(szURL, SIZEOF(szURL));
|
||
|
|
||
|
if (szURL[0])
|
||
|
{
|
||
|
hr = IECreateFromPath(szURL, &pidl);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
ASSERT(pidl);
|
||
|
|
||
|
hr = NavigateToPIDL(pIWebBrowser2, pidl);
|
||
|
|
||
|
ILFree(pidl);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
|
||
|
pIWebBrowser2->Release();
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/////////////////////////////////////
|
||
|
////// Browser only channel band support
|
||
|
|
||
|
|
||
|
// the CProxyWin95Desktop class implements an OleWindow
|
||
|
// to represent the win95 desktop
|
||
|
// the browseronly channel band will use this as its host
|
||
|
|
||
|
|
||
|
class CProxyWin95Desktop :
|
||
|
public IOleWindow
|
||
|
{
|
||
|
public:
|
||
|
// *** IUnknown ***
|
||
|
virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
|
||
|
virtual STDMETHODIMP_(ULONG) AddRef(void);
|
||
|
virtual STDMETHODIMP_(ULONG) Release(void);
|
||
|
|
||
|
// *** IOleWindow methods ***
|
||
|
virtual STDMETHODIMP GetWindow(HWND * lphwnd);
|
||
|
virtual STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode) { return E_NOTIMPL; }
|
||
|
|
||
|
CProxyWin95Desktop(HWND hwnd);
|
||
|
|
||
|
protected:
|
||
|
|
||
|
UINT _cRef;
|
||
|
HWND _hwnd;
|
||
|
};
|
||
|
|
||
|
CProxyWin95Desktop::CProxyWin95Desktop(HWND hwnd) : _cRef(1), _hwnd(hwnd)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
ULONG CProxyWin95Desktop::AddRef()
|
||
|
{
|
||
|
_cRef++;
|
||
|
return _cRef;
|
||
|
}
|
||
|
|
||
|
ULONG CProxyWin95Desktop::Release()
|
||
|
{
|
||
|
ASSERT(_cRef > 0);
|
||
|
_cRef--;
|
||
|
|
||
|
if (_cRef > 0)
|
||
|
return _cRef;
|
||
|
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
HRESULT CProxyWin95Desktop::QueryInterface(REFIID riid, LPVOID * ppvObj)
|
||
|
{
|
||
|
if (IsEqualIID(riid, IID_IUnknown) ||
|
||
|
IsEqualIID(riid, IID_IOleWindow) ||
|
||
|
IsEqualIID(riid, SID_SShellDesktop) // private hack for deskbar.cpp
|
||
|
) {
|
||
|
*ppvObj = SAFECAST(this, IOleWindow*);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*ppvObj = NULL;
|
||
|
return E_NOINTERFACE;
|
||
|
}
|
||
|
|
||
|
AddRef();
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CProxyWin95Desktop::GetWindow(HWND * lphwnd)
|
||
|
{
|
||
|
*lphwnd = _hwnd;
|
||
|
if (_hwnd)
|
||
|
return S_OK;
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
void Channels_InitState(IUnknown* punkBar)
|
||
|
{
|
||
|
// initialize properties
|
||
|
CDeskBarPropertyBag* ppb = new CDeskBarPropertyBag();
|
||
|
if (ppb) {
|
||
|
// Get the default rc
|
||
|
CISSTRUCT cis;
|
||
|
DWORD cbSize = sizeof(CISSTRUCT);
|
||
|
RECT *prc = &cis.rc;
|
||
|
|
||
|
cis.iVer = 1; // set version number to 1
|
||
|
SystemParametersInfoA(SPI_GETWORKAREA, 0, prc, 0);
|
||
|
prc->bottom = min(prc->bottom - 20, prc->top + 12*38 + 28); // 12 icons + caption
|
||
|
|
||
|
if(IS_BIDI_LOCALIZED_SYSTEM())
|
||
|
{
|
||
|
prc->right = prc->left + 90;
|
||
|
OffsetRect(prc, 20, 10);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
prc->left = prc->right - 90;
|
||
|
OffsetRect(prc, -20, 10);
|
||
|
}
|
||
|
|
||
|
// query registry for persisted state
|
||
|
SHRegGetUSValue(SZ_REGKEY_CHANBAR, SZ_REGVALUE_CHANBAR, NULL,
|
||
|
(LPVOID)&cis, &cbSize, FALSE, (LPVOID)&cis, cbSize);
|
||
|
|
||
|
// set ppb by prc
|
||
|
ppb->SetDataDWORD(PROPDATA_MODE, WBM_FLOATING | WBMF_BROWSER);
|
||
|
ppb->SetDataDWORD(PROPDATA_X, prc->left);
|
||
|
ppb->SetDataDWORD(PROPDATA_Y, prc->top);
|
||
|
ppb->SetDataDWORD(PROPDATA_CX, RECTWIDTH(*prc));
|
||
|
ppb->SetDataDWORD(PROPDATA_CY, RECTHEIGHT(*prc));
|
||
|
SHLoadFromPropertyBag(punkBar, ppb);
|
||
|
ppb->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Channels_MainLoop(IDockingWindow *pdw)
|
||
|
{
|
||
|
MSG msg;
|
||
|
HWND hwnd;
|
||
|
// loop while the window exists
|
||
|
do {
|
||
|
GetMessage(&msg, NULL, 0, 0);
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
pdw->GetWindow(&hwnd);
|
||
|
} while (hwnd);
|
||
|
}
|
||
|
|
||
|
void Channels_SetBandInfoSFB(IUnknown* punkBand)
|
||
|
{
|
||
|
BANDINFOSFB bi;
|
||
|
|
||
|
// Set band startup conditions
|
||
|
bi.dwMask = ISFB_MASK_STATE | ISFB_MASK_VIEWMODE;
|
||
|
bi.dwStateMask = ISFB_STATE_CHANNELBAR | ISFB_STATE_NOSHOWTEXT;
|
||
|
bi.dwState = ISFB_STATE_CHANNELBAR | ISFB_STATE_NOSHOWTEXT;
|
||
|
bi.wViewMode = ISFBVIEWMODE_LOGOS;
|
||
|
|
||
|
IUnknown_SetBandInfoSFB(punkBand, &bi);
|
||
|
}
|
||
|
|
||
|
// from isfband.cpp
|
||
|
extern IDeskBand * ChannelBand_Create( LPCITEMIDLIST pidl );
|
||
|
|
||
|
// this does the desktop channel in browser only mode
|
||
|
void DesktopChannel()
|
||
|
{
|
||
|
_InitComCtl32();
|
||
|
|
||
|
// Don't show channel bar:
|
||
|
// *. in integrated mode with active desktop turned on, or
|
||
|
// *. NoChannelUI restriction is set, or
|
||
|
// *. there is already one on desktop
|
||
|
|
||
|
if (SHRestricted2(REST_NoChannelUI, NULL, 0))
|
||
|
return;
|
||
|
|
||
|
if (WhichPlatform() == PLATFORM_INTEGRATED) {
|
||
|
SHELLSTATE ss = { 0 };
|
||
|
|
||
|
SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE); // Get the setting
|
||
|
if (ss.fDesktopHTML) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (FindWindowEx(GetShellWindow(), NULL, TEXT("BaseBar"), TEXT("ChanApp")) ||
|
||
|
FindWindowEx(NULL, NULL, TEXT("BaseBar"), TEXT("ChanApp"))) // can be a toplevel window
|
||
|
return;
|
||
|
|
||
|
LPITEMIDLIST pidl = Channel_GetFolderPidl();
|
||
|
if (pidl) {
|
||
|
IUnknown* punk = (IUnknown *) ChannelBand_Create( pidl );
|
||
|
if (punk) {
|
||
|
|
||
|
Channels_SetBandInfoSFB(punk);
|
||
|
|
||
|
IUnknown* punkBar;
|
||
|
IUnknown* punkBandSite;
|
||
|
|
||
|
HRESULT hres = ChannelDeskBarApp_Create(&punkBar, &punkBandSite);
|
||
|
if (SUCCEEDED(hres)) {
|
||
|
CProxyWin95Desktop* pow = new CProxyWin95Desktop(GetShellWindow());
|
||
|
if (pow) {
|
||
|
IBandSite* pbs;
|
||
|
IDockingWindow* pdw;
|
||
|
|
||
|
Channels_InitState(punkBar);
|
||
|
|
||
|
// these are always our own guys, so these QI's MUST succeed if the creation succeeded
|
||
|
punkBandSite->QueryInterface(IID_IBandSite, (LPVOID*)&pbs);
|
||
|
punkBar->QueryInterface(IID_IDockingWindow, (LPVOID*)&pdw);
|
||
|
ASSERT(pbs && pdw);
|
||
|
|
||
|
hres = pbs->AddBand(punk);
|
||
|
IUnknown_SetSite(pdw, (IOleWindow*)pow);
|
||
|
|
||
|
pbs->SetBandState((DWORD)-1, BSSF_NOTITLE, BSSF_NOTITLE);
|
||
|
|
||
|
pdw->ShowDW(TRUE);
|
||
|
|
||
|
Channels_MainLoop(pdw);
|
||
|
|
||
|
pdw->Release();
|
||
|
pbs->Release();
|
||
|
pow->Release();
|
||
|
}
|
||
|
punkBar->Release();
|
||
|
punkBandSite->Release();
|
||
|
}
|
||
|
|
||
|
punk->Release();
|
||
|
}
|
||
|
ILFree(pidl);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT Channels_OpenBrowser(IWebBrowser2 **ppwb, BOOL fInPlace)
|
||
|
{
|
||
|
HRESULT hres;
|
||
|
IWebBrowser2* pwb;
|
||
|
|
||
|
if (fInPlace) {
|
||
|
ASSERT(ppwb && *ppwb != NULL);
|
||
|
pwb = *ppwb;
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
else {
|
||
|
#ifndef UNIX
|
||
|
hres = CoCreateInstance(CLSID_InternetExplorer, NULL,
|
||
|
CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (void **)&pwb);
|
||
|
#else
|
||
|
hres = CoCreateInternetExplorer( IID_IWebBrowser2,
|
||
|
CLSCTX_LOCAL_SERVER,
|
||
|
(LPVOID*) &pwb );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hres))
|
||
|
{
|
||
|
SA_BSTRGUID strGuid;
|
||
|
VARIANT vaGuid;
|
||
|
|
||
|
// Don't special case full-screen mode for channels post IE4. Use the
|
||
|
// browser's full screen setting.
|
||
|
//
|
||
|
//BOOL fTheater = SHRegGetBoolUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Channels"),
|
||
|
BOOL fTheater = SHRegGetBoolUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
|
||
|
TEXT("FullScreen"), FALSE, FALSE);
|
||
|
pwb->put_TheaterMode( fTheater ? VARIANT_TRUE : VARIANT_FALSE);
|
||
|
pwb->put_Visible(VARIANT_TRUE);
|
||
|
|
||
|
|
||
|
if (!SHRestricted2(REST_NoChannelUI, NULL, 0))
|
||
|
{
|
||
|
#ifdef ENABLE_CHANNELPANE
|
||
|
StringFromGUID2(CLSID_ChannelBand, strGuid.wsz, ARRAYSIZE(strGuid.wsz));
|
||
|
#else
|
||
|
StringFromGUID2(CLSID_FavBand, strGuid.wsz, ARRAYSIZE(strGuid.wsz));
|
||
|
#endif
|
||
|
|
||
|
strGuid.cb = lstrlenW(strGuid.wsz) * SIZEOF(WCHAR);
|
||
|
|
||
|
vaGuid.vt = VT_BSTR;
|
||
|
vaGuid.bstrVal = strGuid.wsz;
|
||
|
|
||
|
pwb->ShowBrowserBar(&vaGuid, PVAREMPTY, PVAREMPTY);
|
||
|
}
|
||
|
|
||
|
// don't release, we're going to return pwb.
|
||
|
}
|
||
|
|
||
|
if (ppwb)
|
||
|
*ppwb = pwb;
|
||
|
else if (pwb)
|
||
|
pwb->Release();
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
BOOL GetFirstUrl(TCHAR szURL[], DWORD cb)
|
||
|
{
|
||
|
//BOOL fFirst = FALSE;
|
||
|
DWORD dwType;
|
||
|
|
||
|
// Don't special case first channel click post IE4.
|
||
|
/*if (SHRegGetUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"), TEXT("ChannelsFirstURL"),
|
||
|
&dwType, szURL, &cb, FALSE, NULL, 0) == ERROR_SUCCESS)
|
||
|
{
|
||
|
HUSKEY hUSKey;
|
||
|
|
||
|
if (SHRegOpenUSKey(TEXT("Software\\Microsoft\\Internet Explorer\\Main"), KEY_WRITE, NULL,
|
||
|
&hUSKey, FALSE) == ERROR_SUCCESS)
|
||
|
{
|
||
|
SHRegDeleteUSValue(hUSKey, TEXT("ChannelsFirstURL"), SHREGDEL_HKCU);
|
||
|
SHRegCloseUSKey(hUSKey);
|
||
|
}
|
||
|
fFirst = TRUE;
|
||
|
}
|
||
|
else if (SHRegGetUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"), TEXT("ChannelsURL"),
|
||
|
&dwType, szURL, &cb, FALSE, NULL, 0) == ERROR_SUCCESS)
|
||
|
{
|
||
|
// nothing
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// BUGBUG if code is ever revived, this res:// needs to be
|
||
|
// accessed through MLBuildResURLWrap because of pluggable UI
|
||
|
szURL = lstrcpy(szURL, TEXT("res://ie4tour.dll/channels.htm"));
|
||
|
}*/
|
||
|
|
||
|
SHRegGetUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
|
||
|
TEXT("ChannelsURL"), &dwType, szURL, &cb, FALSE, NULL, 0);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
//
|
||
|
// ChannelBand
|
||
|
//
|
||
|
// This is a special band that only looks at the channels folder.
|
||
|
// It overrides several functions from CISFBand.
|
||
|
//
|
||
|
|
||
|
#undef SUPERCLASS
|
||
|
#define SUPERCLASS CISFBand
|
||
|
|
||
|
class ChannelBand : public SUPERCLASS
|
||
|
{
|
||
|
public:
|
||
|
virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
|
||
|
virtual STDMETHODIMP OnChange(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
|
||
|
virtual HRESULT OnDropDDT (IDropTarget *pdt, IDataObject *pdtobj, DWORD * pgrfKeyState, POINTL pt, DWORD *pdwEffect);
|
||
|
|
||
|
protected:
|
||
|
ChannelBand();
|
||
|
friend IDeskBand * ChannelBand_Create(LPCITEMIDLIST pidl);
|
||
|
|
||
|
virtual HRESULT _LoadOrderStream();
|
||
|
|
||
|
virtual HWND _CreatePager(HWND hwndParent);
|
||
|
|
||
|
virtual LRESULT _OnCustomDraw(NMCUSTOMDRAW* pnmcd);
|
||
|
|
||
|
virtual void _Dropped(int nIndex, BOOL fDroppedOnSource);
|
||
|
virtual HRESULT _AfterLoad();
|
||
|
virtual void _OnDragBegin(int iItem, DWORD dwPreferedEffect);
|
||
|
} ;
|
||
|
|
||
|
|
||
|
#define COLORBK RGB(0,0,0)
|
||
|
ChannelBand::ChannelBand() :
|
||
|
SUPERCLASS()
|
||
|
{
|
||
|
_lEvents |= SHCNE_EXTENDED_EVENT;
|
||
|
_dwStyle |= TBSTYLE_CUSTOMERASE;
|
||
|
|
||
|
_crBkgnd = COLORBK; // i see a channelband and i want to paint it black
|
||
|
_fHaveBkColor = TRUE;
|
||
|
}
|
||
|
|
||
|
HWND ChannelBand::_CreatePager(HWND hwndParent)
|
||
|
{
|
||
|
// we do want a pager for this band, so
|
||
|
// override isfband's implementation w/ grandpa's
|
||
|
return CSFToolbar::_CreatePager(hwndParent);
|
||
|
}
|
||
|
|
||
|
HRESULT ChannelBand::QueryInterface(REFIID riid, void **ppvObj)
|
||
|
{
|
||
|
*ppvObj = NULL;
|
||
|
if (IsEqualIID(riid, IID_IContextMenu))
|
||
|
return E_NOINTERFACE;
|
||
|
|
||
|
|
||
|
return SUPERCLASS::QueryInterface(riid, ppvObj);
|
||
|
}
|
||
|
|
||
|
|
||
|
IDeskBand * ChannelBand_Create(LPCITEMIDLIST pidlDefault)
|
||
|
{
|
||
|
ChannelBand * pBand = NULL;
|
||
|
LPITEMIDLIST pidl = NULL;
|
||
|
|
||
|
if (!pidlDefault)
|
||
|
{
|
||
|
pidl = Channel_GetFolderPidl();
|
||
|
pidlDefault = pidl;
|
||
|
}
|
||
|
if (EVAL(pidlDefault))
|
||
|
{
|
||
|
pBand = new ChannelBand;
|
||
|
|
||
|
if (pBand)
|
||
|
{
|
||
|
if (FAILED(pBand->InitializeSFB(NULL, pidlDefault)))
|
||
|
{
|
||
|
ATOMICRELEASE(pBand);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ILFree(pidl);
|
||
|
}
|
||
|
|
||
|
return pBand;
|
||
|
}
|
||
|
|
||
|
HRESULT ChannelBand::_AfterLoad()
|
||
|
{
|
||
|
HRESULT hres = SUPERCLASS::_AfterLoad();
|
||
|
|
||
|
_LoadOrderStream();
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
HRESULT ChannelBand::_LoadOrderStream()
|
||
|
{
|
||
|
OrderList_Destroy(&_hdpaOrder);
|
||
|
|
||
|
COrderList_GetOrderList(&_hdpaOrder, _pidl, _psf);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT ChannelBand::OnChange(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
|
||
|
{
|
||
|
HRESULT hres = E_FAIL;
|
||
|
|
||
|
switch (lEvent)
|
||
|
{
|
||
|
case SHCNE_EXTENDED_EVENT:
|
||
|
{
|
||
|
SHChangeMenuAsIDList UNALIGNED * pdwidl = (SHChangeMenuAsIDList UNALIGNED *)pidl1;
|
||
|
if ( pdwidl->dwItem1 == SHCNEE_ORDERCHANGED )
|
||
|
{
|
||
|
if (SHChangeMenuWasSentByMe(this, pidl1))
|
||
|
{
|
||
|
// We sent this order change, ignore it
|
||
|
TraceMsg(TF_BAND, "ChannelBand::OnChange SHCNEE_ORDERCHANGED skipped (we're source)");
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
else if (EVAL(pidl2) && _pidl)
|
||
|
{
|
||
|
if (ILIsEqual(_pidl, pidl2))
|
||
|
{
|
||
|
TraceMsg(TF_BAND, "ChannelBand::OnChange SHCNEE_ORDERCHANGED accepted");
|
||
|
|
||
|
_LoadOrderStream();
|
||
|
|
||
|
if (_fShow)
|
||
|
_FillToolbar();
|
||
|
|
||
|
hres = S_OK;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
// if it wasn't SHCNEE_ORDERCHANGED, then drop through to pass to the base class..
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
hres = SUPERCLASS::OnChange(lEvent, pidl1, pidl2);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return hres;
|
||
|
}
|
||
|
|
||
|
HRESULT ChannelBand::OnDropDDT(IDropTarget *pdt, IDataObject *pdtobj, DWORD * pgrfKeyState, POINTL pt, DWORD *pdwEffect)
|
||
|
{
|
||
|
if (_iDragSource >= 0)
|
||
|
{
|
||
|
return SUPERCLASS::OnDropDDT(pdt, pdtobj, pgrfKeyState, pt, pdwEffect);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// we don't call superclass in this case 'cuz we want to undo
|
||
|
// it's "always use shortcut" override.
|
||
|
//
|
||
|
_fDropping = TRUE;
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LRESULT ChannelBand::_OnCustomDraw(NMCUSTOMDRAW* pnmcd)
|
||
|
{
|
||
|
NMTBCUSTOMDRAW * ptbcd = (NMTBCUSTOMDRAW *)pnmcd;
|
||
|
LRESULT lres;
|
||
|
|
||
|
lres = SUPERCLASS::_OnCustomDraw(pnmcd);
|
||
|
|
||
|
switch (pnmcd->dwDrawStage)
|
||
|
{
|
||
|
case CDDS_PREPAINT:
|
||
|
lres |= CDRF_NOTIFYITEMDRAW;
|
||
|
break;
|
||
|
|
||
|
case CDDS_PREERASE:
|
||
|
// Channel band has a darker background color
|
||
|
{
|
||
|
RECT rc;
|
||
|
GetClientRect(_hwndTB, &rc);
|
||
|
// BUGBUG perf: use SHFillRectClr not SetBk/ExtText/SetBk
|
||
|
COLORREF old = SetBkColor(pnmcd->hdc, _crBkgnd);
|
||
|
ExtTextOut(pnmcd->hdc,0,0,ETO_OPAQUE,&rc,NULL,0,NULL);
|
||
|
SetBkColor(pnmcd->hdc, old);
|
||
|
lres = CDRF_SKIPDEFAULT;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case CDDS_ITEMPREPAINT:
|
||
|
// Channel band doesn't draw as buttons
|
||
|
lres |= TBCDRF_NOEDGES | TBCDRF_NOOFFSET | TBCDRF_NOMARK |
|
||
|
CDRF_NOTIFYPOSTPAINT;
|
||
|
break;
|
||
|
|
||
|
case CDDS_ITEMPOSTPAINT:
|
||
|
// Channel band draws the hot item (CDIS_HOT)
|
||
|
//
|
||
|
|
||
|
pnmcd->rc.top++;
|
||
|
pnmcd->rc.left++;
|
||
|
if (pnmcd->uItemState & CDIS_SELECTED)
|
||
|
// Mark the selected item
|
||
|
FrameTrack(pnmcd->hdc, &(pnmcd->rc), TRACKNOCHILD);
|
||
|
else if (pnmcd->uItemState & CDIS_HOT)
|
||
|
// Mark the hot item
|
||
|
FrameTrack(pnmcd->hdc, &(pnmcd->rc), TRACKHOT);
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
return lres;
|
||
|
}
|
||
|
|
||
|
void ChannelBand::_Dropped(int nIndex, BOOL fDroppedOnSource)
|
||
|
{
|
||
|
ASSERT(_fDropping);
|
||
|
|
||
|
// I'm not changing this to match the other derivatives (ISFBand, mnfolder, quick links),
|
||
|
// because this structure is slightly different
|
||
|
_fDropped = TRUE;
|
||
|
|
||
|
// Persist the new order out to the registry
|
||
|
if (SUCCEEDED(COrderList_SetOrderList(_hdpa, _pidl, _psf)))
|
||
|
{
|
||
|
// Notify everyone that the order changed
|
||
|
SHSendChangeMenuNotify(this, SHCNEE_ORDERCHANGED, 0, _pidl);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ChannelBand::_OnDragBegin(int iItem, DWORD dwPreferedEffect)
|
||
|
{
|
||
|
//
|
||
|
// Don't allow drag if REST_NoRemovingChannels is enabled.
|
||
|
//
|
||
|
|
||
|
if (!SHRestricted2(REST_NoRemovingChannels, NULL, 0))
|
||
|
SUPERCLASS::_OnDragBegin(iItem, dwPreferedEffect);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#endif // ENABLE_CHANNELS
|