Source code of Windows XP (NT5)
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.

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