Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

777 lines
21 KiB

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