channel.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 21k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "priv.h"
  2. #ifdef ENABLE_CHANNELS
  3. #include "channel.h"
  4. #include "bands.h"
  5. #include "isfband.h"
  6. #include "itbar.h"
  7. #include "qlink.h"
  8. #define WANT_CBANDSITE_CLASS
  9. #include "bandsite.h"
  10. #include "resource.h"
  11. #include "deskbar.h"
  12. #include "../lib/dpastuff.h"
  13. #include "dbapp.h"
  14. #include "chanbar.h"
  15. #include "subsmgr.h"
  16. #include "chanmgr.h"
  17. #include "chanmgrp.h"
  18. #include "mluisupp.h"
  19. void FrameTrack(HDC hdc, LPRECT prc, UINT uFlags);
  20. HRESULT Channel_GetFolder(LPTSTR pszPath, int cchPath)
  21. {
  22.     TCHAR szChannel[MAX_PATH];
  23.     TCHAR szFav[MAX_PATH];
  24.     ULONG cbChannel = sizeof(szChannel);
  25.     
  26.     if (SHGetSpecialFolderPath(NULL, szFav, CSIDL_FAVORITES, TRUE))
  27.     {
  28.         //
  29.         // Get the potentially localized name of the Channel folder from the
  30.         // registry if it is there.  Otherwise just read it from the resource.
  31.         // Then tack this on the favorites path.
  32.         //
  33.         if (ERROR_SUCCESS != SHRegGetUSValue(L"Software\Microsoft\Windows\CurrentVersion",
  34.                                              L"ChannelFolderName", NULL, (void*)szChannel,
  35.                                              &cbChannel, TRUE, NULL, 0))
  36.         {
  37.             MLLoadString(IDS_CHANNEL, szChannel, ARRAYSIZE(szChannel));
  38.         }
  39.         PathCombine(pszPath, szFav, szChannel);
  40.         //
  41.         // For IE5+ use the channels dir if it exists - else use favorites
  42.         //
  43.         if (!PathFileExists(pszPath))
  44.             StrCpyN(pszPath, szFav, cchPath);
  45.         return S_OK;
  46.     }    
  47.     
  48.     return E_FAIL;
  49. }
  50. LPITEMIDLIST Channel_GetFolderPidl()
  51. {
  52.     LPITEMIDLIST pidl = NULL;
  53.     TCHAR szPath[MAX_PATH];
  54.     if (SUCCEEDED(Channel_GetFolder(szPath, ARRAYSIZE(szPath))))
  55.     {
  56.         pidl = ILCreateFromPath(szPath);
  57.         if (!pidl && CreateDirectory(szPath, NULL)) {
  58.             pidl = ILCreateFromPath(szPath);
  59.         }
  60.     }
  61.     return pidl;
  62. }
  63. HRESULT ChannelBand_CreateInstance(IUnknown** ppunk)
  64. {
  65.     LPITEMIDLIST pidl = Channel_GetFolderPidl();
  66.     if (pidl)
  67.     {
  68.         CISFBand* pb = CISFBand_CreateEx(NULL, pidl);
  69.         ILFree(pidl);
  70.         if (pb)
  71.         {
  72.             pb->SetCascade(TRUE);
  73.             *ppunk = SAFECAST(pb, IContextMenu*);
  74.             return S_OK;
  75.         }
  76.     }
  77.     *ppunk = NULL;
  78.     return E_FAIL;
  79. }
  80. //
  81. // Navigates the left browser pane to the channels directory.
  82. //
  83. void NavigateBrowserBarToChannels(IWebBrowser2* pwb)
  84. {
  85.     ASSERT(pwb);
  86.     IChannelMgrPriv* pIChannelMgrPriv;
  87.     if (SUCCEEDED(CoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER,
  88.                                     IID_IChannelMgrPriv, (void**)&pIChannelMgrPriv)))
  89.     {
  90.         ASSERT(pIChannelMgrPriv);
  91.         LPITEMIDLIST pidl;
  92.         if (SUCCEEDED(pIChannelMgrPriv->GetChannelFolder(&pidl, IChannelMgrPriv::CF_CHANNEL)))
  93.         {
  94.             ASSERT(pidl);
  95.             VARIANT varPath;
  96.             if (InitVariantFromIDList(&varPath, pidl))
  97.             {
  98.                 VARIANT varFlags;
  99.                 varFlags.vt   = VT_I4;
  100.                 varFlags.lVal = navBrowserBar;
  101.                 pwb->Navigate2(&varPath, &varFlags, PVAREMPTY, PVAREMPTY, PVAREMPTY);
  102.                 VariantClear(&varPath);
  103.             }
  104.             ILFree(pidl);
  105.         }
  106.         pIChannelMgrPriv->Release();
  107.     }
  108.     return;
  109. }
  110. STDAPI NavigateToPIDL(IWebBrowser2* pwb, LPCITEMIDLIST pidl)
  111. {
  112.     ASSERT(pwb);
  113.     ASSERT(pidl);
  114.     HRESULT hr;
  115.     VARIANT varThePidl;
  116.     if (InitVariantFromIDList(&varThePidl, pidl))
  117.     {
  118.         hr = pwb->Navigate2(&varThePidl, PVAREMPTY, PVAREMPTY, PVAREMPTY, PVAREMPTY);
  119.         VariantClear(&varThePidl);       // Needed to free the copy of the PIDL in varThePidl.
  120.     }
  121.     else
  122.         hr = E_OUTOFMEMORY;
  123.     return hr;
  124. }
  125. //
  126. // Implements the IE4 channel quick launch shell control file functionality.
  127. // This gets called from shdoc401 on pre-NT5 platforms and from shell32 on
  128. // Nt5 or greater.
  129. //
  130. HRESULT Channel_QuickLaunch(void)
  131. {
  132.     HRESULT hr;
  133.     IWebBrowser2* pIWebBrowser2;
  134.     hr = Channels_OpenBrowser(&pIWebBrowser2, FALSE);
  135.     if (SUCCEEDED(hr))
  136.     {
  137.         ASSERT(pIWebBrowser2);
  138.         NavigateBrowserBarToChannels(pIWebBrowser2);
  139.         LPITEMIDLIST pidl;
  140.         TCHAR szURL[MAX_URL_STRING] = TEXT("");
  141.         GetFirstUrl(szURL, SIZEOF(szURL));
  142.         if (szURL[0])
  143.         {
  144.             hr = IECreateFromPath(szURL, &pidl);
  145.             if (SUCCEEDED(hr))
  146.             {
  147.                 ASSERT(pidl);
  148.                 hr = NavigateToPIDL(pIWebBrowser2, pidl);
  149.                 ILFree(pidl);
  150.             }
  151.         }
  152.         else
  153.         {
  154.             hr = E_FAIL;
  155.         }
  156.         pIWebBrowser2->Release();
  157.     }
  158.     return hr;
  159. }
  160. /////////////////////////////////////
  161. ////// Browser only channel band support
  162. // the CProxyWin95Desktop class implements an OleWindow 
  163. // to represent the win95 desktop
  164. // the browseronly channel band will use this as its host
  165. class CProxyWin95Desktop : 
  166.    public IOleWindow
  167. {
  168. public:
  169.     // *** IUnknown ***
  170.     virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  171.     virtual STDMETHODIMP_(ULONG) AddRef(void);
  172.     virtual STDMETHODIMP_(ULONG) Release(void);
  173.     // *** IOleWindow methods ***
  174.     virtual STDMETHODIMP GetWindow(HWND * lphwnd);
  175.     virtual STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode) { return E_NOTIMPL; }
  176.     CProxyWin95Desktop(HWND hwnd);
  177.     
  178. protected:
  179.     
  180.     UINT _cRef;
  181.     HWND _hwnd;
  182. };
  183. CProxyWin95Desktop::CProxyWin95Desktop(HWND hwnd) : _cRef(1), _hwnd(hwnd)
  184. {
  185. }
  186. ULONG CProxyWin95Desktop::AddRef()
  187. {
  188.     _cRef++;
  189.     return _cRef;
  190. }
  191. ULONG CProxyWin95Desktop::Release()
  192. {
  193.     ASSERT(_cRef > 0);
  194.     _cRef--;
  195.     if (_cRef > 0)
  196.         return _cRef;
  197.     delete this;
  198.     return 0;
  199. }
  200. HRESULT CProxyWin95Desktop::QueryInterface(REFIID riid, LPVOID * ppvObj)
  201. {
  202.     if (IsEqualIID(riid, IID_IUnknown) ||
  203.         IsEqualIID(riid, IID_IOleWindow) ||
  204.         IsEqualIID(riid, SID_SShellDesktop)  // private hack for deskbar.cpp
  205.        ) {
  206.         *ppvObj = SAFECAST(this, IOleWindow*);
  207.     }
  208.     else
  209.     {
  210.         *ppvObj = NULL;
  211.         return E_NOINTERFACE;
  212.     }
  213.     
  214.     AddRef();
  215.     return S_OK;
  216. }
  217. HRESULT CProxyWin95Desktop::GetWindow(HWND * lphwnd) 
  218. {
  219.     *lphwnd = _hwnd; 
  220.     if (_hwnd)
  221.         return S_OK; 
  222.     return E_FAIL;
  223. }
  224. void Channels_InitState(IUnknown* punkBar)
  225. {
  226.     // initialize properties
  227.     CDeskBarPropertyBag* ppb = new CDeskBarPropertyBag();
  228.     if (ppb) {
  229.         // Get the default rc
  230.         CISSTRUCT cis;
  231.         DWORD     cbSize = sizeof(CISSTRUCT);
  232.         RECT     *prc = &cis.rc;
  233.         cis.iVer = 1;  // set version number to 1
  234.         SystemParametersInfoA(SPI_GETWORKAREA, 0, prc, 0);
  235.         prc->bottom = min(prc->bottom - 20, prc->top + 12*38 + 28); // 12 icons + caption
  236.         if(IS_BIDI_LOCALIZED_SYSTEM())
  237.         {
  238.             prc->right = prc->left + 90;
  239.             OffsetRect(prc, 20, 10);
  240.         }
  241.         else
  242.         {
  243.             prc->left = prc->right - 90;
  244.             OffsetRect(prc, -20, 10);
  245.         }
  246.         // query registry for persisted state
  247.         SHRegGetUSValue(SZ_REGKEY_CHANBAR, SZ_REGVALUE_CHANBAR, NULL, 
  248.                         (LPVOID)&cis, &cbSize, FALSE, (LPVOID)&cis, cbSize);
  249.         // set ppb by prc
  250.         ppb->SetDataDWORD(PROPDATA_MODE, WBM_FLOATING | WBMF_BROWSER);
  251.         ppb->SetDataDWORD(PROPDATA_X, prc->left);
  252.         ppb->SetDataDWORD(PROPDATA_Y, prc->top);
  253.         ppb->SetDataDWORD(PROPDATA_CX, RECTWIDTH(*prc));
  254.         ppb->SetDataDWORD(PROPDATA_CY, RECTHEIGHT(*prc));
  255.         SHLoadFromPropertyBag(punkBar, ppb);
  256.         ppb->Release();
  257.     }
  258. }
  259. void Channels_MainLoop(IDockingWindow *pdw)
  260. {
  261.     MSG msg;
  262.     HWND hwnd;
  263.     // loop while the window exists
  264.     do {
  265.         GetMessage(&msg, NULL, 0, 0);
  266.         TranslateMessage(&msg);
  267.         DispatchMessage(&msg);
  268.         pdw->GetWindow(&hwnd);
  269.     } while (hwnd);
  270. }
  271. void Channels_SetBandInfoSFB(IUnknown* punkBand)
  272. {
  273.     BANDINFOSFB bi;
  274.     // Set band startup conditions
  275.     bi.dwMask = ISFB_MASK_STATE | ISFB_MASK_VIEWMODE;
  276.     bi.dwStateMask = ISFB_STATE_CHANNELBAR | ISFB_STATE_NOSHOWTEXT;
  277.     bi.dwState = ISFB_STATE_CHANNELBAR | ISFB_STATE_NOSHOWTEXT;
  278.     bi.wViewMode = ISFBVIEWMODE_LOGOS;
  279.     IUnknown_SetBandInfoSFB(punkBand, &bi);
  280. }
  281. // from isfband.cpp
  282. extern IDeskBand * ChannelBand_Create( LPCITEMIDLIST pidl );
  283. // this does the desktop channel in browser only mode
  284. void DesktopChannel()
  285. {
  286.     _InitComCtl32();
  287.     // Don't show channel bar:
  288.     //      *. in integrated mode with active desktop turned on, or
  289.     //      *. NoChannelUI restriction is set, or
  290.     //      *. there is already one on desktop
  291.     
  292.     if (SHRestricted2(REST_NoChannelUI, NULL, 0))
  293.         return;
  294.         
  295.     if (WhichPlatform() == PLATFORM_INTEGRATED) {
  296.         SHELLSTATE  ss = { 0 };
  297.         SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE); // Get the setting
  298.         if (ss.fDesktopHTML) {
  299.             return;
  300.         }
  301.     }
  302.         
  303.     if (FindWindowEx(GetShellWindow(), NULL, TEXT("BaseBar"), TEXT("ChanApp")) ||
  304.         FindWindowEx(NULL, NULL, TEXT("BaseBar"), TEXT("ChanApp"))) // can be a toplevel window
  305.         return;
  306.     LPITEMIDLIST pidl = Channel_GetFolderPidl();
  307.     if (pidl) {
  308.         IUnknown* punk = (IUnknown *) ChannelBand_Create( pidl );
  309.         if (punk) {
  310.             Channels_SetBandInfoSFB(punk);
  311.             IUnknown* punkBar;
  312.             IUnknown* punkBandSite;
  313.             HRESULT hres = ChannelDeskBarApp_Create(&punkBar, &punkBandSite);
  314.             if (SUCCEEDED(hres)) {
  315.                 CProxyWin95Desktop* pow = new CProxyWin95Desktop(GetShellWindow());
  316.                 if (pow) {
  317.                     IBandSite* pbs;
  318.                     IDockingWindow* pdw;
  319.                     Channels_InitState(punkBar);
  320.                     // these are always our own guys, so these QI's MUST succeed if the creation succeeded
  321.                     punkBandSite->QueryInterface(IID_IBandSite, (LPVOID*)&pbs);
  322.                     punkBar->QueryInterface(IID_IDockingWindow, (LPVOID*)&pdw);
  323.                     ASSERT(pbs && pdw);
  324.                     hres = pbs->AddBand(punk);
  325.                     IUnknown_SetSite(pdw, (IOleWindow*)pow);
  326.                     pbs->SetBandState((DWORD)-1, BSSF_NOTITLE, BSSF_NOTITLE);
  327.                     pdw->ShowDW(TRUE);
  328.                     Channels_MainLoop(pdw);
  329.                     pdw->Release();
  330.                     pbs->Release();
  331.                     pow->Release();
  332.                 }
  333.                 punkBar->Release();
  334.                 punkBandSite->Release();
  335.             }
  336.             punk->Release();
  337.         }
  338.         ILFree(pidl);
  339.     }
  340. }
  341. HRESULT Channels_OpenBrowser(IWebBrowser2 **ppwb, BOOL fInPlace)
  342. {
  343.     HRESULT hres;
  344.     IWebBrowser2* pwb;
  345.     if (fInPlace) {
  346.         ASSERT(ppwb && *ppwb != NULL);
  347.         pwb = *ppwb;
  348.         hres = S_OK;
  349.     }
  350.     else {
  351. #ifndef UNIX
  352.         hres = CoCreateInstance(CLSID_InternetExplorer, NULL,
  353.                                     CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (void **)&pwb);
  354. #else
  355.         hres = CoCreateInternetExplorer( IID_IWebBrowser2,
  356.                                          CLSCTX_LOCAL_SERVER,
  357.                                          (LPVOID*) &pwb );
  358. #endif
  359.     }
  360.     
  361.     if (SUCCEEDED(hres))
  362.     {
  363.         SA_BSTRGUID  strGuid;
  364.         VARIANT      vaGuid;
  365.         // Don't special case full-screen mode for channels post IE4.  Use the
  366.         // browser's full screen setting.
  367.         // 
  368.         //BOOL fTheater = SHRegGetBoolUSValue(TEXT("Software\Microsoft\Internet Explorer\Channels"),
  369.         BOOL fTheater = SHRegGetBoolUSValue(TEXT("Software\Microsoft\Internet Explorer\Main"),
  370.                                             TEXT("FullScreen"), FALSE, FALSE);
  371.         pwb->put_TheaterMode( fTheater ? VARIANT_TRUE : VARIANT_FALSE);
  372.         pwb->put_Visible(VARIANT_TRUE);
  373.         if (!SHRestricted2(REST_NoChannelUI, NULL, 0))
  374.         {
  375. #ifdef ENABLE_CHANNELPANE
  376.             StringFromGUID2(CLSID_ChannelBand, strGuid.wsz, ARRAYSIZE(strGuid.wsz));
  377. #else
  378.             StringFromGUID2(CLSID_FavBand, strGuid.wsz, ARRAYSIZE(strGuid.wsz));
  379. #endif
  380.             strGuid.cb = lstrlenW(strGuid.wsz) * SIZEOF(WCHAR);
  381.             vaGuid.vt = VT_BSTR;
  382.             vaGuid.bstrVal = strGuid.wsz;
  383.             pwb->ShowBrowserBar(&vaGuid, PVAREMPTY, PVAREMPTY);
  384.         }
  385.         
  386.         // don't release, we're going to return pwb.
  387.     }
  388.     
  389.     if (ppwb)
  390.         *ppwb = pwb;
  391.     else if (pwb)
  392.         pwb->Release();
  393.     
  394.     return hres;
  395. }
  396. BOOL GetFirstUrl(TCHAR szURL[], DWORD cb)
  397. {
  398.     //BOOL fFirst = FALSE;
  399.     DWORD dwType;
  400.     // Don't special case first channel click post IE4.
  401.     /*if (SHRegGetUSValue(TEXT("Software\Microsoft\Internet Explorer\Main"), TEXT("ChannelsFirstURL"), 
  402.             &dwType, szURL, &cb, FALSE, NULL, 0) == ERROR_SUCCESS) 
  403.     {        
  404.         HUSKEY hUSKey;
  405.                 
  406.         if (SHRegOpenUSKey(TEXT("Software\Microsoft\Internet Explorer\Main"), KEY_WRITE, NULL, 
  407.                 &hUSKey, FALSE) == ERROR_SUCCESS)
  408.         {
  409.             SHRegDeleteUSValue(hUSKey, TEXT("ChannelsFirstURL"), SHREGDEL_HKCU);
  410.             SHRegCloseUSKey(hUSKey);
  411.         }
  412.         fFirst = TRUE;
  413.     } 
  414.     else if (SHRegGetUSValue(TEXT("Software\Microsoft\Internet Explorer\Main"), TEXT("ChannelsURL"), 
  415.         &dwType, szURL, &cb, FALSE, NULL, 0) == ERROR_SUCCESS)
  416.     {
  417.         // nothing
  418.     }
  419.     else
  420.     {
  421.         // BUGBUG if code is ever revived, this res:// needs to be
  422.         // accessed through MLBuildResURLWrap because of pluggable UI
  423.         szURL = lstrcpy(szURL, TEXT("res://ie4tour.dll/channels.htm"));
  424.     }*/
  425.     SHRegGetUSValue(TEXT("Software\Microsoft\Internet Explorer\Main"),
  426.                     TEXT("ChannelsURL"), &dwType, szURL, &cb, FALSE, NULL, 0);
  427.     return FALSE; 
  428. }
  429. //////////////////////////////////////////////////
  430. //
  431. // ChannelBand
  432. //
  433. // This is a special band that only looks at the channels folder.
  434. // It overrides several functions from CISFBand.
  435. //
  436. #undef  SUPERCLASS
  437. #define SUPERCLASS CISFBand
  438. class ChannelBand : public SUPERCLASS
  439. {
  440. public:
  441.     virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  442.     virtual STDMETHODIMP OnChange(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
  443.     virtual HRESULT OnDropDDT (IDropTarget *pdt, IDataObject *pdtobj, DWORD * pgrfKeyState, POINTL pt, DWORD *pdwEffect);
  444. protected:
  445.     ChannelBand();
  446.     friend IDeskBand * ChannelBand_Create(LPCITEMIDLIST pidl);
  447.     virtual HRESULT _LoadOrderStream();
  448.     virtual HWND _CreatePager(HWND hwndParent);
  449.     virtual LRESULT _OnCustomDraw(NMCUSTOMDRAW* pnmcd);
  450.     virtual void _Dropped(int nIndex, BOOL fDroppedOnSource);
  451.     virtual HRESULT _AfterLoad();
  452.     virtual void _OnDragBegin(int iItem, DWORD dwPreferedEffect);
  453. } ;
  454. #define COLORBK     RGB(0,0,0)
  455. ChannelBand::ChannelBand() :
  456.     SUPERCLASS()
  457. {
  458.     _lEvents |= SHCNE_EXTENDED_EVENT;
  459.     _dwStyle |= TBSTYLE_CUSTOMERASE;
  460.     _crBkgnd = COLORBK;     // i see a channelband and i want to paint it black
  461.     _fHaveBkColor = TRUE;
  462. }
  463. HWND ChannelBand::_CreatePager(HWND hwndParent)
  464. {
  465.     // we do want a pager for this band, so
  466.     // override isfband's implementation w/ grandpa's
  467.     return CSFToolbar::_CreatePager(hwndParent);
  468. }
  469. HRESULT ChannelBand::QueryInterface(REFIID riid, void **ppvObj)
  470. {
  471.     *ppvObj = NULL;
  472.     if (IsEqualIID(riid, IID_IContextMenu))
  473.         return E_NOINTERFACE;
  474.     
  475.     
  476.     return SUPERCLASS::QueryInterface(riid, ppvObj);
  477. }
  478. IDeskBand * ChannelBand_Create(LPCITEMIDLIST pidlDefault)
  479. {
  480.     ChannelBand * pBand = NULL;
  481.     LPITEMIDLIST pidl = NULL;
  482.     if (!pidlDefault)
  483.     {
  484.         pidl = Channel_GetFolderPidl();
  485.         pidlDefault = pidl;
  486.     }
  487.     if (EVAL(pidlDefault))
  488.     {
  489.         pBand = new ChannelBand;
  490.         if (pBand)
  491.         {
  492.             if (FAILED(pBand->InitializeSFB(NULL, pidlDefault)))
  493.             {
  494.                 ATOMICRELEASE(pBand);
  495.             }
  496.         }
  497.         ILFree(pidl);
  498.     }
  499.     return pBand;
  500. }
  501. HRESULT ChannelBand::_AfterLoad()
  502. {
  503.     HRESULT hres = SUPERCLASS::_AfterLoad();
  504.     _LoadOrderStream();
  505.     return hres;
  506. }
  507. HRESULT ChannelBand::_LoadOrderStream()
  508. {
  509.     OrderList_Destroy(&_hdpaOrder);
  510.     COrderList_GetOrderList(&_hdpaOrder, _pidl, _psf);
  511.     return S_OK;
  512. }
  513. HRESULT ChannelBand::OnChange(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  514. {
  515.     HRESULT hres = E_FAIL;
  516.     switch (lEvent)
  517.     {
  518.     case SHCNE_EXTENDED_EVENT:
  519.     {
  520.         SHChangeMenuAsIDList UNALIGNED * pdwidl = (SHChangeMenuAsIDList UNALIGNED *)pidl1;
  521.         if ( pdwidl->dwItem1 == SHCNEE_ORDERCHANGED )
  522.         {
  523.             if (SHChangeMenuWasSentByMe(this, pidl1))
  524.             {
  525.                 // We sent this order change, ignore it
  526.                 TraceMsg(TF_BAND, "ChannelBand::OnChange SHCNEE_ORDERCHANGED skipped (we're source)");
  527.                 hres = S_OK;
  528.             }
  529.             else if (EVAL(pidl2) && _pidl)
  530.             {
  531.                 if (ILIsEqual(_pidl, pidl2))
  532.                 {
  533.                     TraceMsg(TF_BAND, "ChannelBand::OnChange SHCNEE_ORDERCHANGED accepted");
  534.                     _LoadOrderStream();
  535.                     if (_fShow)
  536.                         _FillToolbar();
  537.                     hres = S_OK;
  538.                 }
  539.             }
  540.             break;
  541.         }
  542.         // if it wasn't SHCNEE_ORDERCHANGED, then drop through to pass to the base class..
  543.     }
  544.     default:
  545.         hres = SUPERCLASS::OnChange(lEvent, pidl1, pidl2);
  546.         break;
  547.     }
  548.     return hres;
  549. }
  550. HRESULT ChannelBand::OnDropDDT(IDropTarget *pdt, IDataObject *pdtobj, DWORD * pgrfKeyState, POINTL pt, DWORD *pdwEffect)
  551. {
  552.     if (_iDragSource >= 0)
  553.     {
  554.         return SUPERCLASS::OnDropDDT(pdt, pdtobj, pgrfKeyState, pt, pdwEffect);
  555.     }
  556.     else
  557.     {
  558.         // we don't call superclass in this case 'cuz we want to undo
  559.         // it's "always use shortcut" override.
  560.         //
  561.         _fDropping = TRUE;
  562.         return S_OK;
  563.     }
  564. }
  565. LRESULT ChannelBand::_OnCustomDraw(NMCUSTOMDRAW* pnmcd)
  566. {
  567.     NMTBCUSTOMDRAW * ptbcd = (NMTBCUSTOMDRAW *)pnmcd;
  568.     LRESULT lres;
  569.     lres = SUPERCLASS::_OnCustomDraw(pnmcd);
  570.         
  571.     switch (pnmcd->dwDrawStage)
  572.     {
  573.     case CDDS_PREPAINT:
  574.         lres |= CDRF_NOTIFYITEMDRAW;
  575.         break;
  576.     case CDDS_PREERASE:
  577.         // Channel band has a darker background color
  578.         {
  579.             RECT rc;
  580.             GetClientRect(_hwndTB, &rc);
  581.             // BUGBUG perf: use SHFillRectClr not SetBk/ExtText/SetBk
  582.             COLORREF old = SetBkColor(pnmcd->hdc, _crBkgnd);
  583.             ExtTextOut(pnmcd->hdc,0,0,ETO_OPAQUE,&rc,NULL,0,NULL);
  584.             SetBkColor(pnmcd->hdc, old);
  585.             lres = CDRF_SKIPDEFAULT;                
  586.         }
  587.         break;
  588.     case CDDS_ITEMPREPAINT:
  589.         // Channel band doesn't draw as buttons
  590.         lres |= TBCDRF_NOEDGES | TBCDRF_NOOFFSET | TBCDRF_NOMARK |
  591.                 CDRF_NOTIFYPOSTPAINT;
  592.         break;
  593.     case CDDS_ITEMPOSTPAINT:
  594.         // Channel band draws the hot item (CDIS_HOT)
  595.         //
  596.         
  597.         pnmcd->rc.top++;
  598.         pnmcd->rc.left++;
  599.         if (pnmcd->uItemState & CDIS_SELECTED)
  600.             // Mark the selected item 
  601.             FrameTrack(pnmcd->hdc,  &(pnmcd->rc), TRACKNOCHILD);                           
  602.         else if (pnmcd->uItemState & CDIS_HOT)
  603.             // Mark the hot item 
  604.             FrameTrack(pnmcd->hdc,  &(pnmcd->rc), TRACKHOT);                           
  605.         break;
  606.     }
  607.     
  608.     return lres;
  609. }
  610. void ChannelBand::_Dropped(int nIndex, BOOL fDroppedOnSource)
  611. {
  612.     ASSERT(_fDropping);
  613.     // I'm not changing this to match the other derivatives (ISFBand, mnfolder, quick links),
  614.     // because this structure is slightly different
  615.     _fDropped = TRUE;
  616.     // Persist the new order out to the registry
  617.     if (SUCCEEDED(COrderList_SetOrderList(_hdpa, _pidl, _psf)))
  618.     {
  619.         // Notify everyone that the order changed
  620.         SHSendChangeMenuNotify(this, SHCNEE_ORDERCHANGED, 0, _pidl);
  621.     }
  622. }
  623. void ChannelBand::_OnDragBegin(int iItem, DWORD dwPreferedEffect)
  624. {
  625.     //
  626.     // Don't allow drag if REST_NoRemovingChannels is enabled.
  627.     //
  628.     if (!SHRestricted2(REST_NoRemovingChannels, NULL, 0))
  629.         SUPERCLASS::_OnDragBegin(iItem, dwPreferedEffect);
  630.     return;
  631. }
  632. #endif // ENABLE_CHANNELS