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.

2859 lines
82 KiB

  1. // fldricon.cpp : Implementation of CWebViewFolderIcon
  2. #include "priv.h"
  3. #include <shsemip.h>
  4. #include <shellp.h>
  5. #include <mshtml.h>
  6. #include <mshtmdid.h>
  7. #include <dvocx.h>
  8. #include <fldricon.h>
  9. #include <exdispid.h>
  10. #include <shguidp.h>
  11. #include <hlink.h>
  12. #include <shlwapi.h>
  13. #include <windowsx.h>
  14. #include <wchar.h>
  15. #include <shdocvw.h> // for IEParseDisplayNameW() & IEGetNameAndFlags()
  16. #include <wingdi.h>
  17. #include <varutil.h>
  18. #define UNINITIALIZE_BOOL 5
  19. const CLSID CLSID_WebViewFolderIconOld = {0xe5df9d10,0x3b52,0x11d1,{0x83,0xe8,0x00,0xa0,0xc9,0x0d,0xc8,0x49}}; // retired from service, so made private
  20. // PERF: Shell allocator, inserted here because SHRealloc
  21. // isn't imported into webvw, this module's hosting executable.
  22. // If we get SHRealloc, the following block can be removed:
  23. #define _EXPL_SHELL_ALLOCATOR_
  24. #ifdef _EXPL_SHELL_ALLOCATOR_
  25. #define SHRealloc(pv, cb) shrealloc(pv, cb)
  26. void* shrealloc(void* pv, size_t cb)
  27. {
  28. void *pvRet = NULL;
  29. IMalloc* pMalloc;
  30. if (SUCCEEDED(SHGetMalloc(&pMalloc)))
  31. {
  32. pvRet = pMalloc->Realloc(pv, cb);
  33. pMalloc->Release();
  34. }
  35. return pvRet;
  36. }
  37. #endif _EXPL_SHELL_ALLOCATOR_
  38. // For registering the window class
  39. const TCHAR * const g_szWindowClassName = TEXT("WebViewFolderIcon view messaging");
  40. DWORD IntSqrt(DWORD dwNum)
  41. {
  42. // This code came from "drawpie.c"
  43. DWORD dwSqrt = 0;
  44. DWORD dwRemain = 0;
  45. DWORD dwTry = 0;
  46. for (int i=0; i<16; ++i)
  47. {
  48. dwRemain = (dwRemain<<2) | (dwNum>>30);
  49. dwSqrt <<= 1;
  50. dwTry = dwSqrt*2 + 1;
  51. if (dwRemain >= dwTry)
  52. {
  53. dwRemain -= dwTry;
  54. dwSqrt |= 0x01;
  55. }
  56. dwNum <<= 2;
  57. }
  58. return dwSqrt;
  59. }
  60. // Make sure you don't begin a drag with random clicking
  61. BOOL CheckForDragBegin(HWND hwnd, int x, int y)
  62. {
  63. RECT rc;
  64. int dxClickRect = GetSystemMetrics(SM_CXDRAG);
  65. int dyClickRect = GetSystemMetrics(SM_CYDRAG);
  66. ASSERT((dxClickRect > 1) && (dyClickRect > 1));
  67. // See if the user moves a certain number of pixels in any direction
  68. SetRect(&rc, x - dxClickRect, y - dyClickRect, x + dxClickRect, y + dyClickRect);
  69. MapWindowRect(hwnd, NULL, &rc);
  70. SetCapture(hwnd);
  71. do
  72. {
  73. MSG msg;
  74. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  75. {
  76. // See if the application wants to process the message...
  77. if (CallMsgFilter(&msg, MSGF_COMMCTRL_BEGINDRAG) != 0)
  78. continue;
  79. switch (msg.message)
  80. {
  81. case WM_LBUTTONUP:
  82. case WM_RBUTTONUP:
  83. PostMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam);
  84. ReleaseCapture();
  85. return FALSE;
  86. case WM_LBUTTONDOWN:
  87. case WM_RBUTTONDOWN:
  88. ReleaseCapture();
  89. return FALSE;
  90. case WM_MOUSEMOVE:
  91. if (!PtInRect(&rc, msg.pt))
  92. {
  93. ReleaseCapture();
  94. return TRUE;
  95. }
  96. break;
  97. default:
  98. if (GetCapture() != hwnd)
  99. ReleaseCapture();
  100. TranslateMessage(&msg);
  101. DispatchMessage(&msg);
  102. break;
  103. }
  104. }
  105. else WaitMessage(); /* Don't chew 100% CPU */
  106. // WM_CANCELMODE messages will unset the capture, in that
  107. // case I want to exit this loop
  108. } while (GetCapture() == hwnd);
  109. return FALSE;
  110. }
  111. ///////////////////////////////////
  112. //
  113. // CWebViewFolderIcon functions
  114. //
  115. ///////////////////////////////////
  116. CWebViewFolderIcon::CWebViewFolderIcon() :
  117. m_pccpDV(NULL),
  118. m_hIcon(0),
  119. m_iIconIndex(-1),
  120. m_hbm(NULL),
  121. m_pthumb(NULL),
  122. m_pidl(NULL),
  123. m_msgHwnd(NULL),
  124. m_pdispWindow(NULL),
  125. m_dwThumbnailID(0),
  126. m_bHilite(FALSE)
  127. {
  128. m_percentScale = 100;
  129. m_lImageWidth = 0;
  130. m_lImageHeight = 0;
  131. m_sizLabel.cx = m_sizLabel.cy = 0;
  132. m_pszDisplayName = NULL;
  133. m_bHasRect = FALSE;
  134. m_ViewUser = VIEW_LARGEICON;
  135. m_ViewCurrent = VIEW_LARGEICON;
  136. m_clickStyle = 2; // Default is double-click
  137. m_fUseSystemColors = TRUE;
  138. m_bAdvPropsOn = VARIANT_TRUE;
  139. m_bRegWndClass = FALSE;
  140. m_ullFreeSpace = 0;
  141. m_ullUsedSpace = 0;
  142. m_ullTotalSpace = 0;
  143. m_highestIndexSlice = 0;
  144. m_fTabRecieved = FALSE;
  145. m_pcm3 = NULL;
  146. m_pDropTargetCache = NULL;
  147. m_fIsHostWebView = UNINITIALIZE_BOOL;
  148. m_hdc = NULL;
  149. m_fRectAdjusted = 0;
  150. m_hbmDrag = NULL;
  151. m_hdsaSlices = DSA_Create(sizeof(PieSlice_S), SLICE_NUM_GROW);
  152. /*
  153. * Listview puts a SM_CXEDGE between the icon and the label,
  154. * so we will default to that value. (Clients can adjust with
  155. * labelGap property.)
  156. */
  157. m_cxLabelGap = GetSystemMetrics(SM_CXEDGE);
  158. m_pfont = NULL;
  159. m_hfAmbient = NULL;
  160. }
  161. CWebViewFolderIcon::~CWebViewFolderIcon()
  162. {
  163. _ClearLabel();
  164. _ClearAmbientFont();
  165. if (m_hIcon)
  166. {
  167. DestroyIcon(m_hIcon);
  168. m_hIcon = NULL;
  169. }
  170. if (m_hdc)
  171. {
  172. DeleteDC(m_hdc);
  173. m_hdc = NULL;
  174. }
  175. if (m_hbmDrag)
  176. {
  177. DeleteObject(m_hbmDrag);
  178. m_hbmDrag = NULL;
  179. }
  180. ILFree(m_pidl);
  181. if (m_hbm)
  182. {
  183. DeleteObject(m_hbm);
  184. m_hbm = NULL;
  185. }
  186. if (m_hfAmbient)
  187. {
  188. DeleteObject(m_hfAmbient);
  189. m_hfAmbient = NULL;
  190. }
  191. ATOMICRELEASE(m_pDropTargetCache);
  192. ATOMICRELEASE(m_pthumb);
  193. DSA_Destroy(m_hdsaSlices);
  194. if (m_msgHwnd)
  195. ::DestroyWindow(m_msgHwnd);
  196. if (m_bRegWndClass)
  197. {
  198. UnregisterClass(g_szWindowClassName, _Module.GetModuleInstance());
  199. }
  200. }
  201. HRESULT CWebViewFolderIcon::_SetupWindow(void)
  202. {
  203. // On the first time register the messaging window
  204. if (!m_bRegWndClass)
  205. {
  206. // Create Window Class for messaging
  207. m_msgWc.style = 0;
  208. m_msgWc.lpfnWndProc = CWebViewFolderIcon::WndProc;
  209. m_msgWc.cbClsExtra = 0;
  210. m_msgWc.cbWndExtra = 0;
  211. m_msgWc.hInstance = _Module.GetModuleInstance();
  212. m_msgWc.hIcon = NULL;
  213. m_msgWc.hCursor = NULL;
  214. m_msgWc.hbrBackground = NULL;
  215. m_msgWc.lpszMenuName = NULL;
  216. m_msgWc.lpszClassName = g_szWindowClassName;
  217. m_bRegWndClass = RegisterClass(&m_msgWc);
  218. }
  219. if (!m_msgHwnd)
  220. {
  221. m_msgHwnd = CreateWindow(g_szWindowClassName, NULL, WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  222. CW_USEDEFAULT, NULL, NULL, _Module.GetModuleInstance(), this);
  223. }
  224. return m_msgHwnd ? S_OK : E_FAIL;
  225. }
  226. // Must be called before using the IThumbnail. Also sets up the thumbnail message window
  227. HRESULT CWebViewFolderIcon::SetupIThumbnail(void)
  228. {
  229. HRESULT hr = _SetupWindow();
  230. if (SUCCEEDED(hr))
  231. {
  232. if (m_pthumb)
  233. hr = S_OK;
  234. else
  235. {
  236. hr = CoCreateInstance(CLSID_Thumbnail, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IThumbnail2, &m_pthumb));
  237. if (SUCCEEDED(hr))
  238. hr = m_pthumb->Init(m_msgHwnd, WM_HTML_BITMAP);
  239. }
  240. }
  241. return hr;
  242. }
  243. // General functions
  244. HRESULT CWebViewFolderIcon::_InvokeOnThumbnailReady()
  245. {
  246. // Fire off "OnThumbnailReady" event to our connection points to indicate that
  247. // either a thumbnail has been computed or we have no thumbnail for this file.
  248. DISPPARAMS dp = {0, NULL, 0, NULL}; // no parameters
  249. //Lock();
  250. for (IUnknown** pp = m_vec.begin(); pp < m_vec.end(); pp++)
  251. {
  252. if (pp)
  253. {
  254. IDispatch* pDispatch = SAFECAST(*pp, IDispatch*);
  255. pDispatch->Invoke(DISPID_WEBVIEWFOLDERICON_ONTHUMBNAILREADY, IID_NULL,
  256. LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dp, NULL, NULL, NULL);
  257. }
  258. }
  259. //Unlock();
  260. FireViewChange();
  261. return S_OK;
  262. }
  263. // The S_FALSE return value indicates that this function has succeeded, but the out pidl is still NULL
  264. HRESULT CWebViewFolderIcon::_GetFullPidl(LPITEMIDLIST *ppidl)
  265. {
  266. *ppidl = NULL;
  267. HRESULT hr;
  268. if (m_pidl)
  269. {
  270. hr = SHILClone(m_pidl, ppidl); // dupe our copy
  271. }
  272. else
  273. {
  274. // This used to be an EVAL, but it can legitimately fail if the script did not
  275. // specify a valid path
  276. // This will fail if we are hosted in a web page instead of the HTML WebView frame in DefView.
  277. IUnknown *punk;
  278. hr = IUnknown_QueryService(m_spClientSite, SID_SFolderView, IID_PPV_ARG(IUnknown, &punk));
  279. if (SUCCEEDED(hr))
  280. {
  281. if (S_OK == SHGetIDListFromUnk(punk, ppidl))
  282. {
  283. Pidl_Set(&m_pidl, *ppidl); // cache a copy of this
  284. }
  285. punk->Release();
  286. }
  287. }
  288. return hr;
  289. }
  290. HRESULT _GetPidlAndShellFolderFromPidl(LPITEMIDLIST pidl, LPITEMIDLIST *ppidlLast, IShellFolder** ppsfParent)
  291. {
  292. LPCITEMIDLIST pidlLast;
  293. HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, ppsfParent), &pidlLast);
  294. if (SUCCEEDED(hr))
  295. {
  296. *ppidlLast = ILClone(pidlLast);
  297. }
  298. return hr;
  299. }
  300. // RETURN VALUES:
  301. // SUCCEEDED() means *ppidlLast and/or *ppsfParent can be NULL.
  302. // FAILED() means a *ppidlLast *ppsfParent are going to be returned NULL.
  303. HRESULT CWebViewFolderIcon::_GetPidlAndShellFolder(LPITEMIDLIST *ppidlLast, IShellFolder** ppsfParent)
  304. {
  305. LPITEMIDLIST pidl;
  306. HRESULT hr = _GetFullPidl(&pidl);
  307. if (hr == S_OK)
  308. {
  309. hr = _GetPidlAndShellFolderFromPidl(pidl, ppidlLast, ppsfParent);
  310. ILFree(pidl);
  311. }
  312. else
  313. {
  314. *ppidlLast = NULL;
  315. *ppsfParent = NULL;
  316. }
  317. return hr;
  318. }
  319. // Get Trident's HWND
  320. HRESULT CWebViewFolderIcon::_GetHwnd(HWND* phwnd)
  321. {
  322. HRESULT hr;
  323. if (m_spInPlaceSite)
  324. {
  325. hr = m_spInPlaceSite->GetWindow(phwnd);
  326. }
  327. else
  328. {
  329. IOleInPlaceSiteWindowless * poipsw;
  330. hr = m_spClientSite->QueryInterface(IID_PPV_ARG(IOleInPlaceSiteWindowless, &poipsw));
  331. if (EVAL(SUCCEEDED(hr)))
  332. {
  333. hr = poipsw->GetWindow(phwnd);
  334. poipsw->Release();
  335. }
  336. }
  337. return hr;
  338. }
  339. HRESULT CWebViewFolderIcon::_GetChildUIObjectOf(REFIID riid, void **ppvObj)
  340. {
  341. LPITEMIDLIST pidlLast;
  342. IShellFolder *psfParent;
  343. HRESULT hr = _GetPidlAndShellFolder(&pidlLast, &psfParent);
  344. if (hr == S_OK)
  345. {
  346. HWND hwnd;
  347. _GetHwnd(&hwnd);
  348. hr = psfParent->GetUIObjectOf(hwnd, 1, (LPCITEMIDLIST *)&pidlLast, riid, NULL, ppvObj);
  349. psfParent->Release();
  350. ILFree(pidlLast);
  351. }
  352. else
  353. hr = E_FAIL;
  354. return hr;
  355. }
  356. // Center point of focus rectangle
  357. HRESULT CWebViewFolderIcon::_GetCenterPoint(POINT *pt)
  358. {
  359. pt->y = ((m_rcPos.top + m_rcPos.bottom)/2);
  360. pt->x = ((m_rcPos.left + m_rcPos.right)/2);
  361. return S_OK;
  362. }
  363. HRESULT CWebViewFolderIcon::_ZoneCheck(DWORD dwFlags)
  364. {
  365. HRESULT hr = E_ACCESSDENIED;
  366. CComPtr<IDefViewSafety> spDefViewSafety;
  367. if (SUCCEEDED(IUnknown_QueryService(m_spClientSite, SID_SFolderView,
  368. IID_PPV_ARG(IDefViewSafety, &spDefViewSafety))))
  369. {
  370. hr = spDefViewSafety->IsSafePage();
  371. }
  372. return hr;
  373. }
  374. BOOL CWebViewFolderIcon::IsSafeToDefaultVerb(void)
  375. {
  376. return S_OK == _ZoneCheck(PUAF_WARN_IF_DENIED);
  377. }
  378. // If the focus rectangle is not in the specified RectState (on or off) change it and reset m_bHasRect
  379. void CWebViewFolderIcon::_FlipFocusRect(BOOL RectState)
  380. {
  381. if (m_bHasRect != RectState) // needs flipping
  382. {
  383. m_bHasRect = RectState;
  384. ForceRedraw();
  385. }
  386. return;
  387. }
  388. // Extract a ULONGLONG from two VARIANT's
  389. ULONGLONG CWebViewFolderIcon::GetUllMemFromVars(VARIANT *pvarHi, VARIANT *pvarLo)
  390. {
  391. ULARGE_INTEGER uli;
  392. uli.HighPart = pvarHi->ulVal;
  393. uli.LowPart = pvarLo->ulVal;
  394. return uli.QuadPart;
  395. }
  396. // Returns the integer percent from the string percent. Returns -1 if the string is invalid;
  397. int CWebViewFolderIcon::GetPercentFromStrW(LPCWSTR pwzPercent)
  398. {
  399. int percent = -1;
  400. int numchar = lstrlenW(pwzPercent);
  401. if (pwzPercent[numchar-1] == '%')
  402. {
  403. LPWSTR pwzTempPct = SysAllocString(pwzPercent);
  404. if (pwzTempPct)
  405. {
  406. pwzTempPct[numchar-1] = '\0';
  407. for (int i=0 ; i < (numchar-2) ; i++)
  408. {
  409. if (!((pwzTempPct[i] >= '0') && (pwzTempPct[i] <= '9')))
  410. {
  411. percent = 100; // 100% is the default to use in error conditions
  412. break;
  413. }
  414. }
  415. if ((-1 == percent) && !StrToIntExW(pwzTempPct, STIF_DEFAULT, &percent))
  416. {
  417. percent = -1;
  418. }
  419. SysFreeString(pwzTempPct);
  420. }
  421. }
  422. return percent;
  423. }
  424. BOOL CWebViewFolderIcon::_WebViewOpen(void)
  425. {
  426. BOOL Processed = FALSE;
  427. if (IsSafeToDefaultVerb())
  428. {
  429. Processed = TRUE;
  430. //
  431. // if the context menu option does not work, we try a shell execute on the pidl
  432. //
  433. if (FAILED(_DoContextMenuCmd(TRUE, 0, 0)))
  434. {
  435. if (m_pidl)
  436. {
  437. SHELLEXECUTEINFO sei = { 0 };
  438. sei.cbSize = sizeof(sei);
  439. sei.fMask = SEE_MASK_INVOKEIDLIST;
  440. sei.nShow = SW_SHOWNORMAL;
  441. sei.lpIDList = m_pidl;
  442. if (!ShellExecuteEx(&sei))
  443. {
  444. Processed = FALSE;
  445. }
  446. }
  447. }
  448. }
  449. return Processed;
  450. }
  451. void CWebViewFolderIcon::_ClearLabel(void)
  452. {
  453. if (m_pszDisplayName)
  454. {
  455. CoTaskMemFree(m_pszDisplayName);
  456. m_pszDisplayName = NULL;
  457. m_sizLabel.cx = m_sizLabel.cy = 0;
  458. }
  459. }
  460. void CWebViewFolderIcon::_GetLabel(IShellFolder *psf, LPCITEMIDLIST pidlItem)
  461. {
  462. if ((m_ViewUser & VIEW_WITHLABEL) && psf)
  463. {
  464. STRRET str;
  465. if (SUCCEEDED(psf->GetDisplayNameOf(pidlItem, SHGDN_INFOLDER, &str)))
  466. {
  467. AssertMsg(m_pszDisplayName == NULL, TEXT("CWebViewFolderIcon::_GetLabel - leaking m_pszDisplayName!"));
  468. StrRetToStr(&str, pidlItem, &m_pszDisplayName);
  469. }
  470. }
  471. }
  472. void CWebViewFolderIcon::_ClearAmbientFont(void)
  473. {
  474. if (m_pfont) // Font came from container
  475. {
  476. if (m_hfAmbient)
  477. m_pfont->ReleaseHfont(m_hfAmbient);
  478. m_pfont->Release();
  479. m_pfont = NULL;
  480. }
  481. else // Font was created by us
  482. {
  483. if (m_hfAmbient)
  484. DeleteObject(m_hfAmbient);
  485. }
  486. m_hfAmbient = NULL;
  487. }
  488. void CWebViewFolderIcon::_GetAmbientFont(void)
  489. {
  490. if (!m_hfAmbient)
  491. {
  492. // Try to get the ambient font from our container
  493. if (SUCCEEDED(GetAmbientFont(&m_pfont)))
  494. {
  495. if (SUCCEEDED(m_pfont->get_hFont(&m_hfAmbient)))
  496. {
  497. // Yay, everybody is happy
  498. m_pfont->AddRefHfont(m_hfAmbient);
  499. }
  500. else
  501. {
  502. // Darn, couldn't get the font from container
  503. // Clean up and use the fallback
  504. _ClearAmbientFont();
  505. goto fallback;
  506. }
  507. }
  508. else
  509. {
  510. fallback:
  511. // No ambient font -- use the icon title font
  512. LOGFONT lf;
  513. SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE);
  514. m_hfAmbient = CreateFontIndirect(&lf);
  515. }
  516. }
  517. }
  518. HRESULT CWebViewFolderIcon::InitImage(void)
  519. {
  520. HRESULT hr = E_FAIL;
  521. // Cancel pending bitmap request if you had a functioning IThumbnail
  522. // but didn't receive the bitmap
  523. if (m_pthumb && (m_hbm == NULL))
  524. {
  525. m_pthumb->GetBitmap(NULL, 0, 0, 0);
  526. }
  527. m_dwThumbnailID++;
  528. // Initialize the image
  529. switch (_ViewType(m_ViewUser))
  530. {
  531. case VIEW_THUMBVIEW:
  532. hr = InitThumbnail();
  533. if (hr != S_OK)
  534. { // Default to icon view, but return the previous hr
  535. InitIcon();
  536. }
  537. break;
  538. case VIEW_PIECHART:
  539. hr = InitPieGraph();
  540. if (hr != S_OK)
  541. { // Default to icon view, but return the previous hr
  542. InitIcon();
  543. }
  544. break;
  545. default:
  546. hr = InitIcon();
  547. break;
  548. }
  549. if (SUCCEEDED(hr)) // Force a Redraw
  550. UpdateSize();
  551. return hr;
  552. }
  553. HRESULT CWebViewFolderIcon::_GetPathW(LPWSTR psz)
  554. {
  555. *psz = 0;
  556. HRESULT hr = E_FAIL;
  557. LPITEMIDLIST pidl;
  558. if (S_OK == _GetFullPidl(&pidl))
  559. {
  560. if (SHGetPathFromIDListW(pidl, psz))
  561. hr = S_OK;
  562. ILFree(pidl);
  563. }
  564. return hr;
  565. }
  566. HRESULT CWebViewFolderIcon::InitPieGraph(void)
  567. {
  568. HRESULT hr = S_FALSE;
  569. WCHAR wzPath[MAX_PATH];
  570. if (SUCCEEDED(_GetPathW(wzPath)))
  571. {
  572. // Check to see if it is a root
  573. if (PathIsRootW(wzPath))
  574. {
  575. if (SUCCEEDED(ComputeFreeSpace(wzPath)))
  576. {
  577. m_ViewCurrent = VIEW_PIECHART;
  578. m_lImageHeight = PIEVIEW_DEFAULT;
  579. m_lImageWidth = PIEVIEW_DEFAULT;
  580. hr = S_OK;
  581. }
  582. }
  583. else // not the root, change view to large icon
  584. m_ViewCurrent = VIEW_LARGEICON;
  585. }
  586. return hr;
  587. }
  588. HRESULT CWebViewFolderIcon::InitThumbnail(void)
  589. {
  590. m_lImageHeight = THUMBVIEW_DEFAULT;
  591. m_lImageWidth = THUMBVIEW_DEFAULT;
  592. // Get thumbnail bitmap from the path
  593. HRESULT hr = S_FALSE;
  594. LPITEMIDLIST pidl;
  595. if (S_OK == _GetFullPidl(&pidl))
  596. {
  597. hr = SetupIThumbnail();
  598. if (SUCCEEDED(hr))
  599. {
  600. LONG lWidth = _GetScaledImageWidth();
  601. LONG lHeight = _GetScaledImageHeight();
  602. // Sends the WM_HTML_BITMAP message
  603. hr = m_pthumb->GetBitmapFromIDList(pidl, m_dwThumbnailID, lWidth, lHeight);
  604. if (SUCCEEDED(hr))
  605. m_ViewCurrent = VIEW_THUMBVIEW;
  606. else
  607. hr = S_FALSE;
  608. }
  609. ILFree(pidl);
  610. }
  611. return hr;
  612. }
  613. HRESULT CWebViewFolderIcon::_MakeRoomForLabel()
  614. {
  615. /*
  616. * If we got a label, then make room for it.
  617. */
  618. if (m_pszDisplayName)
  619. {
  620. GETDCSTATE dcs;
  621. HDC hdc = IUnknown_GetDC(m_spClientSite, &m_rcPos, &dcs);
  622. _GetAmbientFont();
  623. HFONT hfPrev = SelectFont(hdc, m_hfAmbient);
  624. m_sizLabel.cx = m_sizLabel.cy = 0;
  625. GetTextExtentPoint(hdc, m_pszDisplayName, lstrlen(m_pszDisplayName), &m_sizLabel);
  626. SelectFont(hdc, hfPrev);
  627. IUnknown_ReleaseDC(hdc, &dcs);
  628. }
  629. return S_OK;
  630. }
  631. HRESULT CWebViewFolderIcon::InitIcon(void)
  632. {
  633. LPITEMIDLIST pidlLast;
  634. CComPtr<IShellFolder> spsfParent;
  635. INT iIconIndex = II_DESKTOP;
  636. _ClearLabel();
  637. // Get icon index
  638. HRESULT hr = _GetPidlAndShellFolder(&pidlLast, &spsfParent);
  639. if (SUCCEEDED(hr))
  640. {
  641. if (m_ViewUser & VIEW_WITHLABEL)
  642. {
  643. _GetLabel(spsfParent, pidlLast);
  644. }
  645. // _GetPidlAndShellFolder() may succeed and spsfParent and pidlLast can be NULL.
  646. // In this case the icon will default to II_FOLDER
  647. // Is it the default folder case?
  648. if (hr == S_FALSE)
  649. {
  650. // Yes, so just use the default folder icon.
  651. iIconIndex = II_FOLDER;
  652. }
  653. else if (spsfParent && pidlLast)
  654. {
  655. iIconIndex = SHMapPIDLToSystemImageListIndex(spsfParent, pidlLast, NULL);
  656. if (iIconIndex <= 0)
  657. {
  658. iIconIndex = II_FOLDER;
  659. }
  660. }
  661. // else it defaults to the desktop
  662. // Extract icon
  663. hr = E_FAIL; // We haven't gotten it yet
  664. if (m_hIcon)
  665. {
  666. // If the indexes match, we can use the previous value as a cache, otherwise,
  667. // we need to free it. We also need to free the bitmap in this case.
  668. if (iIconIndex != m_iIconIndex)
  669. {
  670. DestroyIcon(m_hIcon);
  671. m_hIcon = 0;
  672. }
  673. else
  674. {
  675. hr = S_OK; // Use the one we have already
  676. }
  677. }
  678. // We also need to check and free the bitmap
  679. if (m_hbm)
  680. {
  681. DeleteObject(m_hbm);
  682. m_hbm = 0;
  683. }
  684. if (FAILED(hr)) // Different icon
  685. {
  686. HIMAGELIST himlSysLarge;
  687. HIMAGELIST himlSysSmall;
  688. if ((iIconIndex > 0) && Shell_GetImageLists(&himlSysLarge, &himlSysSmall))
  689. {
  690. switch (_ViewType(m_ViewUser))
  691. {
  692. case VIEW_SMALLICON:
  693. m_hIcon = ImageList_GetIcon(himlSysSmall, iIconIndex, 0);
  694. m_ViewCurrent = m_ViewUser;
  695. break;
  696. case VIEW_LARGEICON:
  697. m_hIcon = ImageList_GetIcon(himlSysLarge, iIconIndex, 0);
  698. m_ViewCurrent = m_ViewUser;
  699. break;
  700. default: // Falls here for large icon and default
  701. m_hIcon = ImageList_GetIcon(himlSysLarge, iIconIndex, 0);
  702. m_ViewCurrent = VIEW_LARGEICON;
  703. break;
  704. } // switch
  705. if (m_hIcon)
  706. {
  707. ICONINFO iconinfo;
  708. // Get icon size
  709. if (GetIconInfo(m_hIcon, &iconinfo))
  710. {
  711. BITMAP bm;
  712. if (GetObject(iconinfo.hbmColor, sizeof(bm), &bm))
  713. {
  714. m_lImageWidth = bm.bmWidth;
  715. m_lImageHeight = bm.bmHeight;
  716. // Hold on to the color hbm for use as a drag image.
  717. m_hbm = iconinfo.hbmColor;
  718. hr = S_OK;
  719. }
  720. else
  721. {
  722. DeleteObject(iconinfo.hbmColor);
  723. }
  724. DeleteObject(iconinfo.hbmMask);
  725. }
  726. }
  727. }
  728. }
  729. ILFree(pidlLast);
  730. _MakeRoomForLabel();
  731. }
  732. if (FAILED(hr))
  733. {
  734. // Couldn't get the icon so set the size to something resonable so that the rest
  735. // of the page looks normal
  736. m_lImageWidth = LARGE_ICON_DEFAULT;
  737. m_lImageHeight = LARGE_ICON_DEFAULT;
  738. UpdateSize(); // Force an update
  739. }
  740. return hr;
  741. }
  742. HRESULT CWebViewFolderIcon::UpdateSize(void)
  743. {
  744. HRESULT hr = E_FAIL;
  745. // Get the IHtmlStyle
  746. if (m_spClientSite)
  747. {
  748. CComPtr<IOleControlSite> spControlSite;
  749. hr = m_spClientSite->QueryInterface(IID_PPV_ARG(IOleControlSite, &spControlSite));
  750. if (EVAL(SUCCEEDED(hr)))
  751. {
  752. CComPtr<IDispatch> spdisp;
  753. hr = spControlSite->GetExtendedControl(&spdisp);
  754. if (EVAL(SUCCEEDED(hr)))
  755. {
  756. CComPtr<IHTMLElement> spElement;
  757. hr = spdisp->QueryInterface(IID_PPV_ARG(IHTMLElement, &spElement));
  758. if (EVAL(SUCCEEDED(hr)))
  759. {
  760. CComPtr<IHTMLStyle> spStyle;
  761. hr = spElement->get_style(&spStyle);
  762. if (EVAL(SUCCEEDED(hr)))
  763. {
  764. CComVariant vWidth(_GetControlWidth(), VT_I4);
  765. CComVariant vHeight(_GetControlHeight(), VT_I4);
  766. // Set the height and width
  767. spStyle->put_width(vWidth);
  768. spStyle->put_height(vHeight);
  769. }
  770. }
  771. }
  772. }
  773. }
  774. return hr;
  775. }
  776. HRESULT CWebViewFolderIcon::ForceRedraw(void)
  777. {
  778. IOleInPlaceSiteEx *pins;
  779. // Get the IHtmlStyle
  780. if (m_spClientSite)
  781. {
  782. if (SUCCEEDED(m_spClientSite->QueryInterface(IID_PPV_ARG(IOleInPlaceSiteEx, &pins))))
  783. {
  784. HWND hwnd;
  785. if (SUCCEEDED(pins->GetWindow(&hwnd)))
  786. {
  787. ::InvalidateRgn(hwnd, NULL, TRUE);
  788. }
  789. pins->Release();
  790. }
  791. }
  792. return S_OK;
  793. }
  794. /////////////////////////////////////////////////////////////////////////////
  795. // IOleInPlaceObject
  796. STDMETHODIMP CWebViewFolderIcon::UIDeactivate(void)
  797. {
  798. if (m_bAdvPropsOn)
  799. _FlipFocusRect(FALSE);
  800. return IOleInPlaceObject_UIDeactivate();
  801. }
  802. // *** IOleInPlaceActiveObject ***
  803. HRESULT CWebViewFolderIcon::TranslateAccelerator(LPMSG pMsg)
  804. {
  805. HRESULT hr = S_OK;
  806. if (!m_fTabRecieved)
  807. {
  808. hr = IOleInPlaceActiveObjectImpl<CWebViewFolderIcon>::TranslateAccelerator(pMsg);
  809. // If we did not handle this and if it is a tab (and we are not getting it in a cycle), forward it to trident, if present.
  810. if (hr != S_OK && pMsg && (pMsg->wParam == VK_TAB || pMsg->wParam == VK_F6) && m_spClientSite)
  811. {
  812. HWND hwnd;
  813. if (SUCCEEDED(_GetHwnd(&hwnd)) && (GetFocus() != hwnd))
  814. {
  815. ::SetFocus(hwnd);
  816. hr = S_OK;
  817. }
  818. else
  819. {
  820. IOleControlSite* pocs = NULL;
  821. if (SUCCEEDED(m_spClientSite->QueryInterface(IID_PPV_ARG(IOleControlSite, &pocs))))
  822. {
  823. DWORD grfModifiers = 0;
  824. if (GetKeyState(VK_SHIFT) & 0x8000)
  825. {
  826. grfModifiers |= 0x1; //KEYMOD_SHIFT
  827. }
  828. if (GetKeyState(VK_CONTROL) & 0x8000)
  829. {
  830. grfModifiers |= 0x2; //KEYMOD_CONTROL;
  831. }
  832. if (GetKeyState(VK_MENU) & 0x8000)
  833. {
  834. grfModifiers |= 0x4; //KEYMOD_ALT;
  835. }
  836. m_fTabRecieved = TRUE;
  837. hr = pocs->TranslateAccelerator(pMsg, grfModifiers);
  838. m_fTabRecieved = FALSE;
  839. }
  840. }
  841. }
  842. }
  843. return hr;
  844. }
  845. /////////////////////////////////////////////////////////////////////////////
  846. // ATL
  847. HRESULT CWebViewFolderIcon::DoVerbUIActivate(LPCRECT prcPosRect, HWND hwndParent)
  848. {
  849. if (m_bAdvPropsOn)
  850. _FlipFocusRect(TRUE);
  851. return IOleObjectImpl<CWebViewFolderIcon>::DoVerbUIActivate(prcPosRect, hwndParent);
  852. }
  853. /////////////////////////////////////////////////////////////////////////////
  854. // IDispatch
  855. STDMETHODIMP CWebViewFolderIcon::Invoke(DISPID dispidMember, REFIID riid, LCID lcid,
  856. WORD wFlags, DISPPARAMS *pDispParams,
  857. VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
  858. UINT *puArgErr)
  859. {
  860. HRESULT hr;
  861. //
  862. // We are overloading this dispatch implementation to be an html window event
  863. // sink and implement the scale property. This is safe since the dispid ranges
  864. // don't overlap.
  865. // Likewise we overload now for notifications that come from the browser object...
  866. //
  867. if (dispidMember == DISPID_HTMLWINDOWEVENTS_ONLOAD)
  868. {
  869. hr = OnWindowLoad();
  870. }
  871. else if (dispidMember == DISPID_HTMLWINDOWEVENTS_ONUNLOAD)
  872. {
  873. hr = OnWindowUnLoad();
  874. }
  875. else
  876. {
  877. hr = IDispatchImpl<IWebViewFolderIcon3, &IID_IWebViewFolderIcon3, &LIBID_WEBVWLib>::Invoke(
  878. dispidMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
  879. }
  880. return hr;
  881. }
  882. /////////////////////////////////////////////////////////////////////////////
  883. // IViewObjectEx
  884. STDMETHODIMP CWebViewFolderIcon::GetViewStatus(DWORD* pdwStatus)
  885. {
  886. *pdwStatus = VIEWSTATUS_DVASPECTTRANSPARENT;
  887. return S_OK;
  888. }
  889. /////////////////////////////////////////////////////////////////////////////
  890. // IPointerInactive
  891. STDMETHODIMP CWebViewFolderIcon::GetActivationPolicy(DWORD* pdwPolicy)
  892. {
  893. if (!m_bAdvPropsOn)
  894. return S_OK;
  895. *pdwPolicy = POINTERINACTIVE_ACTIVATEONDRAG;
  896. return S_OK;
  897. }
  898. /////////////////////////////////////////////////////////////////////////////
  899. // IOleInPlaceObjectWindowless
  900. // To implement Windowless DropTarget
  901. STDMETHODIMP CWebViewFolderIcon::GetDropTarget(IDropTarget **ppDropTarget)
  902. {
  903. HRESULT hr = S_OK;
  904. if (ppDropTarget)
  905. *ppDropTarget = NULL;
  906. if (m_bAdvPropsOn)
  907. {
  908. // Do we need to populate m_pDropTargetCache?
  909. if (!m_pDropTargetCache)
  910. {
  911. // Yes, so try to get it now.
  912. hr = _GetChildUIObjectOf(IID_PPV_ARG(IDropTarget, &m_pDropTargetCache));
  913. }
  914. if (m_pDropTargetCache)
  915. hr = m_pDropTargetCache->QueryInterface(IID_PPV_ARG(IDropTarget, ppDropTarget));
  916. else
  917. hr = E_FAIL;
  918. }
  919. return hr;
  920. }
  921. /////////////////////////////////////////////////////////////////////////////
  922. // IOleObject
  923. STDMETHODIMP CWebViewFolderIcon::SetClientSite(IOleClientSite *pClientSite)
  924. {
  925. HRESULT hr;
  926. // Deal with the old client site
  927. if (pClientSite == NULL && m_spClientSite)
  928. {
  929. // We need to unadvise from the defview object now...
  930. if (m_pccpDV)
  931. {
  932. m_pccpDV->Unadvise(m_dwCookieDV);
  933. m_pccpDV->Release();
  934. m_pccpDV = NULL;
  935. }
  936. DisconnectHtmlEvents(m_pdispWindow, m_dwHtmlWindowAdviseCookie);
  937. m_dwHtmlWindowAdviseCookie = 0;
  938. }
  939. hr = IOleObjectImpl<CWebViewFolderIcon>::SetClientSite(pClientSite);
  940. if ((pClientSite != NULL) && SUCCEEDED(hr))
  941. {
  942. ConnectHtmlEvents(this, m_spClientSite, &m_pdispWindow, &m_dwHtmlWindowAdviseCookie);
  943. // OK now lets register ourself with the Defview to get any events that they may generate...
  944. IServiceProvider *pspTLB;
  945. hr = IUnknown_QueryService(m_spClientSite, SID_STopLevelBrowser, IID_PPV_ARG(IServiceProvider, &pspTLB));
  946. if (SUCCEEDED(hr))
  947. {
  948. IExpDispSupport *peds;
  949. hr = pspTLB->QueryService(IID_IExpDispSupport, IID_PPV_ARG(IExpDispSupport, &peds));
  950. if (SUCCEEDED(hr))
  951. {
  952. hr = peds->FindCIE4ConnectionPoint(DIID_DWebBrowserEvents2, &m_pccpDV);
  953. if (SUCCEEDED(hr))
  954. {
  955. hr = m_pccpDV->Advise(SAFECAST(this, IDispatch*), &m_dwCookieDV);
  956. }
  957. peds->Release();
  958. }
  959. pspTLB->Release();
  960. }
  961. }
  962. return hr;
  963. }
  964. UINT g_cfPreferedEffect = 0;
  965. HRESULT _SetPreferedDropEffect(IDataObject *pdtobj, DWORD dwEffect)
  966. {
  967. if (g_cfPreferedEffect == 0)
  968. g_cfPreferedEffect = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
  969. HRESULT hr = E_OUTOFMEMORY;
  970. DWORD *pdw = (DWORD *)GlobalAlloc(GPTR, sizeof(DWORD));
  971. if (pdw)
  972. {
  973. STGMEDIUM medium;
  974. FORMATETC fmte = {(CLIPFORMAT)g_cfPreferedEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  975. *pdw = dwEffect;
  976. medium.tymed = TYMED_HGLOBAL;
  977. medium.hGlobal = pdw;
  978. medium.pUnkForRelease = NULL;
  979. hr = pdtobj->SetData(&fmte, &medium, TRUE);
  980. if (FAILED(hr))
  981. GlobalFree((HGLOBAL)pdw);
  982. }
  983. return hr;
  984. }
  985. /////////////////////////////////////////////////////////////////////////////
  986. // Event Handlers
  987. HRESULT CWebViewFolderIcon::DragDrop(int iClickXPos, int iClickYPos)
  988. {
  989. if (!m_bAdvPropsOn)
  990. return S_OK;
  991. LPITEMIDLIST pidlLast;
  992. IShellFolder *psfParent;
  993. HRESULT hr = _GetPidlAndShellFolder(&pidlLast, &psfParent);
  994. if (hr == S_OK)
  995. {
  996. IDataObject *pdtobj;
  997. hr = psfParent->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*) &pidlLast,
  998. IID_PPV_ARG_NULL(IDataObject, &pdtobj));
  999. if (SUCCEEDED(hr))
  1000. {
  1001. DWORD dwEffect = DROPEFFECT_MOVE | DROPEFFECT_COPY | DROPEFFECT_LINK;
  1002. psfParent->GetAttributesOf(1, (LPCITEMIDLIST*) &pidlLast, &dwEffect);
  1003. dwEffect &= DROPEFFECT_MOVE | DROPEFFECT_COPY | DROPEFFECT_LINK;
  1004. if (dwEffect)
  1005. {
  1006. HRESULT hrOleInit = SHCoInitialize();
  1007. HWND hwnd;
  1008. hr = _GetHwnd(&hwnd);
  1009. if (SUCCEEDED(hr))
  1010. {
  1011. DWORD dwEffectOut;
  1012. _SetPreferedDropEffect(pdtobj, DROPEFFECT_LINK);
  1013. // Set the drag image and effect; we don't care if
  1014. // it fails, we'll just use the default.
  1015. _SetDragImage(iClickXPos, iClickYPos, pdtobj);
  1016. hr = SHDoDragDrop(hwnd, pdtobj, NULL, dwEffect, &dwEffectOut);
  1017. }
  1018. SHCoUninitialize(hrOleInit);
  1019. }
  1020. pdtobj->Release();
  1021. }
  1022. psfParent->Release();
  1023. ILFree(pidlLast);
  1024. }
  1025. return hr;
  1026. }
  1027. // SetDragImage
  1028. //
  1029. // Sets the drag image to be identical to the icon
  1030. HRESULT CWebViewFolderIcon::_SetDragImage(int iClickXPos, int iClickYPos, IDataObject *pdtobj)
  1031. {
  1032. // Check things that need to be valid for us to work
  1033. AssertMsg(m_hdc != NULL , TEXT("CWebViewFolderIcon:_SetDragImage() m_hdc is null"));
  1034. AssertMsg(m_hbmDrag != NULL, TEXT("CWebViewFolderIcon:_SetDragImage m_hbmDrag is null"));
  1035. // If the image is a pie chart, it isn't loaded into m_hbm, so we need
  1036. // to do that first
  1037. if (m_ViewCurrent == VIEW_PIECHART)
  1038. {
  1039. _GetPieChartIntoBitmap();
  1040. }
  1041. // Get a dragdrop helper to set our image
  1042. IDragSourceHelper *pdsh;
  1043. HRESULT hr = CoCreateInstance(CLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER,
  1044. IID_PPV_ARG(IDragSourceHelper, &pdsh));
  1045. if (SUCCEEDED(hr))
  1046. {
  1047. BITMAPINFOHEADER bmi = {0};
  1048. BITMAP bm = {0};
  1049. UINT uBufferOffset = 0;
  1050. // This is a screwy procedure to use GetDIBits.
  1051. // See knowledge base Q80080
  1052. GetObject(m_hbm, sizeof(BITMAP), &bm);
  1053. bmi.biSize = sizeof(BITMAPINFOHEADER);
  1054. bmi.biWidth = bm.bmWidth;
  1055. bmi.biHeight = bm.bmHeight;
  1056. bmi.biPlanes = 1;
  1057. bmi.biBitCount = bm.bmPlanes * bm.bmBitsPixel;
  1058. // This needs to be one of these 4 values
  1059. if (bmi.biBitCount <= 1)
  1060. bmi.biBitCount = 1;
  1061. else if (bmi.biBitCount <= 4)
  1062. bmi.biBitCount = 4;
  1063. else if (bmi.biBitCount <= 8)
  1064. bmi.biBitCount = 8;
  1065. else
  1066. bmi.biBitCount = 24;
  1067. bmi.biCompression = BI_RGB;
  1068. // Total size of buffer for info struct and color table
  1069. uBufferOffset = sizeof(BITMAPINFOHEADER) +
  1070. ((bmi.biBitCount == 24) ? 0 : ((1 << bmi.biBitCount) * sizeof(RGBQUAD)));
  1071. // Buffer for bitmap bits, so we can copy them.
  1072. BYTE * psBits = (BYTE *) SHAlloc(uBufferOffset);
  1073. if (psBits)
  1074. {
  1075. // Put bmi into the memory block
  1076. CopyMemory(psBits, &bmi, sizeof(BITMAPINFOHEADER));
  1077. // Get the size of the buffer needed for bitmap bits
  1078. if (GetDIBits(m_hdc, m_hbm, 0, 0, NULL, (BITMAPINFO *) psBits, DIB_RGB_COLORS))
  1079. {
  1080. // Realloc our buffer to be big enough
  1081. psBits = (BYTE *) SHRealloc(psBits, uBufferOffset + ((BITMAPINFOHEADER *) psBits)->biSizeImage);
  1082. if (psBits)
  1083. {
  1084. // Fill the buffer
  1085. if (GetDIBits(m_hdc, m_hbm, 0, bmi.biHeight,
  1086. (void *)(psBits + uBufferOffset), (BITMAPINFO *)psBits,
  1087. DIB_RGB_COLORS))
  1088. {
  1089. SHDRAGIMAGE shdi; // Drag images struct
  1090. shdi.hbmpDragImage = CreateBitmapIndirect(&bm);
  1091. if (shdi.hbmpDragImage)
  1092. {
  1093. // Set the drag image bitmap
  1094. if (SetDIBits(m_hdc, shdi.hbmpDragImage, 0, m_lImageHeight,
  1095. (void *)(psBits + uBufferOffset), (BITMAPINFO *)psBits,
  1096. DIB_RGB_COLORS))
  1097. {
  1098. // Populate the drag image structure
  1099. shdi.sizeDragImage.cx = m_lImageWidth;
  1100. shdi.sizeDragImage.cy = m_lImageHeight;
  1101. shdi.ptOffset.x = iClickXPos - m_rcPos.left;
  1102. shdi.ptOffset.y = iClickYPos - m_rcPos.top;
  1103. shdi.crColorKey = 0;
  1104. // Set the drag image
  1105. hr = pdsh->InitializeFromBitmap(&shdi, pdtobj);
  1106. }
  1107. else
  1108. {
  1109. hr = E_FAIL; // Can't SetDIBits
  1110. }
  1111. }
  1112. else
  1113. {
  1114. hr = E_OUTOFMEMORY; // Can't alloc hbmpDragImage
  1115. }
  1116. }
  1117. else
  1118. {
  1119. hr = E_FAIL; // Can't fill psBits
  1120. }
  1121. // Free psBits below...
  1122. }
  1123. else
  1124. {
  1125. hr = E_OUTOFMEMORY; // Can't realloc psBits
  1126. // Free psbits here; it still has the old contents
  1127. SHFree(psBits);
  1128. psBits = NULL;
  1129. }
  1130. }
  1131. else
  1132. {
  1133. hr = E_FAIL; // Can't get image size
  1134. }
  1135. if (psBits)
  1136. SHFree(psBits);
  1137. }
  1138. else
  1139. {
  1140. hr = E_OUTOFMEMORY; // Can't alloc psBits
  1141. }
  1142. pdsh->Release();
  1143. }
  1144. return hr;
  1145. }
  1146. HRESULT CWebViewFolderIcon::_GetPieChartIntoBitmap()
  1147. {
  1148. BITMAP bm;
  1149. // It is possible for m_hbm to be alloced, so check for it.
  1150. if (m_hbm)
  1151. {
  1152. DeleteObject(m_hbm);
  1153. }
  1154. // Notice that because we want to draw into a new DC starting
  1155. // from the origin, but our rect contains the coords for the
  1156. // original DC, it is neccessary to adjust the coords so that
  1157. // the rect starts at 0, 0 but still has the same proportions.
  1158. // Since OnDraw() resets the rect each time, we don't have to
  1159. // preserve it and do have to do this each time. Finally, since
  1160. // Draw3dPie adjusts the rect dimensions for itself, we only want
  1161. // to fix this once.
  1162. if (!m_fRectAdjusted)
  1163. {
  1164. m_rect.right -= m_rect.left;
  1165. m_rect.left = 0;
  1166. m_rect.bottom -= m_rect.top;
  1167. m_rect.top = 0;
  1168. m_fRectAdjusted = 1;
  1169. }
  1170. // Get the bitmap
  1171. GetObject(m_hbmDrag, sizeof(BITMAP), &bm);
  1172. m_hbm = CreateBitmapIndirect(&bm);
  1173. if (m_hbm)
  1174. {
  1175. // Select into the new DC, and draw our pie
  1176. HBITMAP hbmOld = (HBITMAP) SelectObject(m_hdc, m_hbm);
  1177. DWORD dwPercent1000 = 0;
  1178. if (EVAL((m_ullTotalSpace > 0) && (m_ullFreeSpace <= m_ullTotalSpace)))
  1179. {
  1180. ComputeSlicePct(m_ullUsedSpace, &dwPercent1000);
  1181. }
  1182. Draw3dPie(m_hdc, &m_rect, dwPercent1000, m_ChartColors);
  1183. SelectObject(m_hdc, hbmOld);
  1184. }
  1185. return S_OK;
  1186. }
  1187. LRESULT CWebViewFolderIcon::OnInitPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
  1188. {
  1189. if (m_pcm3)
  1190. m_pcm3->HandleMenuMsg(uMsg, wParam, lParam);
  1191. return 0;
  1192. }
  1193. LRESULT CWebViewFolderIcon::OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
  1194. {
  1195. if (!m_bAdvPropsOn)
  1196. return TRUE;
  1197. if ((int)wParam != VK_RETURN && (int) wParam != VK_SPACE)
  1198. {
  1199. return FALSE;
  1200. }
  1201. else
  1202. return _WebViewOpen();
  1203. }
  1204. LRESULT CWebViewFolderIcon::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
  1205. {
  1206. if (m_bAdvPropsOn)
  1207. {
  1208. _DisplayContextMenu(-1, -1);
  1209. }
  1210. return TRUE;
  1211. }
  1212. // NOTE: our drag drop code captures the mouse and has to do funky stuff to
  1213. // make sure we get this button up message. if you have problems with this check
  1214. // the code in CheckForDragBegin()
  1215. LRESULT CWebViewFolderIcon::OnButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
  1216. {
  1217. BOOL Processed = FALSE;
  1218. if (!m_bAdvPropsOn)
  1219. return TRUE;
  1220. HWND hwnd;
  1221. if (EVAL(SUCCEEDED(_GetHwnd(&hwnd))))
  1222. {
  1223. if (CheckForDragBegin(hwnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)))
  1224. {
  1225. IUnknown *punk;
  1226. if (EVAL(SUCCEEDED(IUnknown_QueryService(m_spClientSite, SID_STopLevelBrowser, IID_PPV_ARG(IUnknown, &punk)))))
  1227. {
  1228. if (SUCCEEDED(DragDrop(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))))
  1229. {
  1230. Processed = TRUE;
  1231. }
  1232. }
  1233. }
  1234. }
  1235. /*
  1236. * In single-click mode, open on single left click.
  1237. */
  1238. if (!Processed && uMsg == WM_LBUTTONDOWN && m_clickStyle == 1)
  1239. return _WebViewOpen();
  1240. return Processed;
  1241. }
  1242. // Only valid for the HTML window case
  1243. LRESULT CWebViewFolderIcon::OnLButtonDoubleClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
  1244. {
  1245. if (!m_bAdvPropsOn || m_clickStyle != 2)
  1246. return TRUE;
  1247. return _WebViewOpen();
  1248. }
  1249. LRESULT CWebViewFolderIcon::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
  1250. {
  1251. if (!m_bAdvPropsOn)
  1252. return TRUE;
  1253. //
  1254. // the first time we get a WM_MOUSEMOVE event, we set m_bHilite to be TRUE and ignore
  1255. // subsequent WM_MOUSEMOVEs. OnMouseLeave() sets m_bHilite to FALSE in response to
  1256. // a WM_MOUSELEAVE msg.
  1257. //
  1258. if (!m_bHilite)
  1259. {
  1260. m_bHilite = TRUE;
  1261. return SUCCEEDED(ForceRedraw());
  1262. }
  1263. else
  1264. {
  1265. return TRUE;
  1266. }
  1267. }
  1268. LRESULT CWebViewFolderIcon::OnMouseLeave(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
  1269. {
  1270. if (!m_bAdvPropsOn)
  1271. return TRUE;
  1272. m_bHilite = FALSE;
  1273. return SUCCEEDED(ForceRedraw());
  1274. }
  1275. // The Right Mouse button came up so we want to
  1276. LRESULT CWebViewFolderIcon::OnRButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
  1277. {
  1278. LRESULT lResult = FALSE;
  1279. if (!m_bAdvPropsOn)
  1280. return TRUE;
  1281. HRESULT hr = LocalZoneCheck(m_spClientSite);
  1282. if (S_OK == hr)
  1283. {
  1284. hr = _DisplayContextMenu(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
  1285. if (SUCCEEDED(hr))
  1286. {
  1287. lResult = TRUE;
  1288. }
  1289. }
  1290. return lResult;
  1291. }
  1292. BOOL CWebViewFolderIcon::_IsHostWebView(void)
  1293. {
  1294. if (UNINITIALIZE_BOOL == m_fIsHostWebView)
  1295. {
  1296. CComPtr<IDefViewID> spDefView;
  1297. m_fIsHostWebView = FALSE;
  1298. // This will fail if we are hosted in a web page instead of the HTML WebView frame in DefView.
  1299. if (SUCCEEDED(IUnknown_QueryService(m_spClientSite, SID_SFolderView, IID_PPV_ARG(IDefViewID, &spDefView))))
  1300. {
  1301. m_fIsHostWebView = TRUE;
  1302. }
  1303. }
  1304. return m_fIsHostWebView;
  1305. }
  1306. BOOL CWebViewFolderIcon::_IsPubWizHosted(void)
  1307. {
  1308. IPropertyBag *ppb;
  1309. HRESULT hr = IUnknown_QueryService(m_spClientSite, SID_WebWizardHost, IID_PPV_ARG(IPropertyBag, &ppb));
  1310. if (SUCCEEDED(hr))
  1311. {
  1312. ppb->Release();
  1313. }
  1314. return SUCCEEDED(hr);
  1315. }
  1316. /****************************************************\
  1317. DESCRIPTION:
  1318. We need a little special
  1319. work on the Context Menu since it points to the
  1320. same folder we are in. So the "Send To" menu
  1321. needs massaging and the "Open" verb needs to
  1322. be removed.
  1323. TODO: I think we should also do this:
  1324. case WM_MENUCHAR:
  1325. _pcm->HandleMenuMsg2(uMsg, wParam, lParam, &lres);
  1326. break;
  1327. case WM_DRAWITEM:
  1328. case WM_MEASUREITEM:
  1329. _pcm->HandleMenuMsg(uMsg, wParam, lParam);
  1330. break;
  1331. case WM_INITMENUPOPUP:
  1332. _pcm->HandleMenuMsg(WM_INITMENUPOPUP, (WPARAM)hmenuPopup, (LPARAM)MAKELONG(nIndex, fSystemMenu)
  1333. break;
  1334. \****************************************************/
  1335. HRESULT CWebViewFolderIcon::_DisplayContextMenu(long nXCord, long nYCord)
  1336. {
  1337. if (!m_bAdvPropsOn)
  1338. {
  1339. return S_OK;
  1340. }
  1341. // respect system policies
  1342. if (SHRestricted(REST_NOVIEWCONTEXTMENU))
  1343. {
  1344. return E_FAIL;
  1345. }
  1346. return _DoContextMenuCmd(FALSE, nXCord, nYCord);
  1347. }
  1348. //
  1349. // bDefault == TRUE > Function executes the default context menu verb, ignores the coords
  1350. // bDefault == FALSE > Function pops up a menu at the given coords and executes the desired verb
  1351. //
  1352. HRESULT CWebViewFolderIcon::_DoContextMenuCmd(BOOL bDefault, long nXCord, long nYCord)
  1353. {
  1354. IContextMenu *pcm;
  1355. HRESULT hr = _GetChildUIObjectOf(IID_PPV_ARG(IContextMenu, &pcm));
  1356. if (SUCCEEDED(hr))
  1357. {
  1358. HMENU hpopup = CreatePopupMenu();
  1359. if (hpopup)
  1360. {
  1361. // SetSite required if you want in place navigation
  1362. IUnknown_SetSite(pcm, m_spClientSite);
  1363. hr = pcm->QueryContextMenu(hpopup, 0, ID_FIRST, ID_LAST, CMF_NORMAL);
  1364. if (SUCCEEDED(hr))
  1365. {
  1366. HWND hwnd;
  1367. hr = _GetHwnd(&hwnd);
  1368. if (SUCCEEDED(hr))
  1369. {
  1370. UINT idCmd = -1;
  1371. if (bDefault) // invoke the default verb
  1372. {
  1373. idCmd = GetMenuDefaultItem(hpopup, FALSE, GMDI_GOINTOPOPUPS);
  1374. }
  1375. else
  1376. {
  1377. //
  1378. // popup the menu and get the command to be executed
  1379. //
  1380. POINT point = {nXCord, nYCord};
  1381. // NTRAID#106655 05-02-2000 arisha
  1382. // We need to add support to be able to modify the context menu from script.
  1383. // Below, we make sure we do not remove the "open" verb from the context
  1384. // menu if we are displaying it in the VIEW_LARGEICONLABEL mode.
  1385. if (_IsHostWebView() && (m_ViewCurrent != VIEW_LARGEICONLABEL))
  1386. {
  1387. hr = ContextMenu_DeleteCommandByName(pcm, hpopup, ID_FIRST, TEXT("open"));
  1388. }
  1389. if ((point.x == -1) && (point.y == -1))
  1390. {
  1391. _GetCenterPoint(&point);
  1392. }
  1393. ::ClientToScreen(hwnd, &point);
  1394. pcm->QueryInterface(IID_PPV_ARG(IContextMenu3, &m_pcm3));
  1395. if (SUCCEEDED(_SetupWindow()))
  1396. {
  1397. idCmd = TrackPopupMenu(hpopup, TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTALIGN,
  1398. (int)point.x, (int)point.y,
  1399. 0, m_msgHwnd, NULL);
  1400. }
  1401. if (!IsSafeToDefaultVerb() || 0 == idCmd) // 0 implies user cancelled selection
  1402. {
  1403. idCmd = -1;
  1404. }
  1405. ATOMICRELEASE(m_pcm3);
  1406. }
  1407. if (idCmd != -1)
  1408. {
  1409. CMINVOKECOMMANDINFO cmdInfo =
  1410. {
  1411. sizeof(cmdInfo),
  1412. 0,
  1413. hwnd,
  1414. (LPSTR)MAKEINTRESOURCE(idCmd),
  1415. NULL,
  1416. NULL,
  1417. SW_NORMAL
  1418. };
  1419. hr = pcm->InvokeCommand(&cmdInfo);
  1420. }
  1421. }
  1422. }
  1423. IUnknown_SetSite(pcm, NULL);
  1424. DestroyMenu(hpopup);
  1425. }
  1426. pcm->Release();
  1427. }
  1428. return hr;
  1429. }
  1430. HRESULT CWebViewFolderIcon::OnAmbientPropertyChange(DISPID dispid)
  1431. {
  1432. switch (dispid)
  1433. {
  1434. case DISPID_UNKNOWN:
  1435. case DISPID_AMBIENT_FONT:
  1436. // changing the font means we need to recompute our label
  1437. if (m_pszDisplayName)
  1438. {
  1439. CComPtr<IFont> spFont;
  1440. if (SUCCEEDED(GetAmbientFont(&spFont)))
  1441. {
  1442. if (spFont->IsEqual(m_pfont) != S_OK)
  1443. {
  1444. _ClearAmbientFont();
  1445. _MakeRoomForLabel();
  1446. }
  1447. }
  1448. }
  1449. // FALL THROUGH
  1450. case DISPID_AMBIENT_BACKCOLOR:
  1451. case DISPID_AMBIENT_FORECOLOR:
  1452. ForceRedraw();
  1453. break;
  1454. }
  1455. return S_OK;
  1456. }
  1457. COLORREF _TranslateColor(OLE_COLOR oclr)
  1458. {
  1459. COLORREF clr;
  1460. if (FAILED(OleTranslateColor(oclr, NULL, &clr)))
  1461. clr = oclr;
  1462. return clr;
  1463. }
  1464. HRESULT CWebViewFolderIcon::OnDraw(ATL_DRAWINFO& di)
  1465. {
  1466. RECT& rc = *(RECT*)di.prcBounds;
  1467. LONG lImageWidth = _GetScaledImageWidth();
  1468. LONG lImageHeight = _GetScaledImageHeight();
  1469. // Grab our hdc and rect to be used in _SetDragImage
  1470. if (m_hdc)
  1471. {
  1472. DeleteDC(m_hdc);
  1473. }
  1474. m_hdc = CreateCompatibleDC(di.hdcDraw);
  1475. if (m_hbmDrag)
  1476. {
  1477. DeleteObject(m_hbmDrag);
  1478. }
  1479. m_hbmDrag = CreateCompatibleBitmap(di.hdcDraw, m_lImageWidth, m_lImageHeight);
  1480. m_rect = rc;
  1481. m_fRectAdjusted = 0;
  1482. //
  1483. // Draw the folder icon
  1484. //
  1485. if ((m_ViewCurrent == VIEW_THUMBVIEW) || (m_ViewCurrent == VIEW_PIECHART))
  1486. {
  1487. HDC hdc = di.hdcDraw;
  1488. HDC hdcBitmap;
  1489. BITMAP bm;
  1490. HPALETTE hpal = NULL;
  1491. ASSERT(hdc);
  1492. // Create pallete appropriate for this HDC
  1493. if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
  1494. {
  1495. hpal = SHCreateShellPalette(hdc);
  1496. HPALETTE hpalOld = SelectPalette(hdc, hpal, TRUE);
  1497. RealizePalette(hdc);
  1498. // Old one needs to be selected back in
  1499. SelectPalette(hdc, hpalOld, TRUE);
  1500. }
  1501. hdcBitmap = CreateCompatibleDC(hdc);
  1502. if (hdcBitmap)
  1503. {
  1504. // Draw pie chart
  1505. if (m_ViewCurrent == VIEW_PIECHART)
  1506. {
  1507. DWORD dwPercent1000 = 0;
  1508. if (1) // m_fUseSystemColors. When do we want this off?
  1509. {
  1510. // system colors can change!
  1511. m_ChartColors[PIE_USEDCOLOR] = GetSysColor(COLOR_3DFACE);
  1512. m_ChartColors[PIE_FREECOLOR] = GetSysColor(COLOR_3DHILIGHT);
  1513. m_ChartColors[PIE_USEDSHADOW] = GetSysColor(COLOR_3DSHADOW);
  1514. m_ChartColors[PIE_FREESHADOW] = GetSysColor(COLOR_3DFACE);
  1515. }
  1516. else if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
  1517. {
  1518. // Call GetNearestColor on the colors to make sure they're on the palette
  1519. // Of course, system colors ARE on the palette (I think)
  1520. DWORD dw = 0; // index
  1521. for (dw = 0; dw < PIE_NUM; dw++)
  1522. {
  1523. m_ChartColors[dw] = GetNearestColor(hdc, m_ChartColors[dw]);
  1524. }
  1525. }
  1526. if (EVAL((m_ullTotalSpace > 0) && (m_ullFreeSpace <= m_ullTotalSpace)))
  1527. {
  1528. ComputeSlicePct(m_ullUsedSpace, &dwPercent1000);
  1529. }
  1530. Draw3dPie(hdc, &rc, dwPercent1000, m_ChartColors);
  1531. }
  1532. else // Draw the Bitmap
  1533. {
  1534. SelectObject(hdcBitmap, m_hbm);
  1535. GetObject(m_hbm, sizeof(bm), &bm);
  1536. // Bitmap exactly fits the rectangle
  1537. if (bm.bmWidth == rc.right - rc.left && bm.bmHeight == rc.bottom - rc.top)
  1538. {
  1539. BitBlt(hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hdcBitmap, 0, 0, SRCCOPY);
  1540. }
  1541. // Stretch Bitmap to fit the rectangle
  1542. else
  1543. {
  1544. SetStretchBltMode(hdc, COLORONCOLOR);
  1545. StretchBlt(hdc, rc.left, rc.top, lImageWidth, lImageHeight, hdcBitmap, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
  1546. }
  1547. }
  1548. DeleteDC(hdcBitmap);
  1549. }
  1550. }
  1551. else if (m_hIcon)
  1552. {
  1553. DrawIconEx(di.hdcDraw, rc.left, rc.top, m_hIcon, lImageWidth, lImageHeight, 0, 0, DI_NORMAL);
  1554. }
  1555. // Draw the label (if any)
  1556. if (m_pszDisplayName)
  1557. {
  1558. TEXTMETRIC tm;
  1559. TCHAR szFace[32];
  1560. HFONT hFontHilite = NULL;
  1561. //
  1562. // first get the current font properties, there seems to be no straightforward way
  1563. // to just obtain the LOGFONT structure from an HFONT object, so we have to select it
  1564. // to a DC, then obtain the text metrics and use them to create a new font with or
  1565. // without the underline based on m_bHilite value.
  1566. //
  1567. HFONT hfPrev = SelectFont(di.hdcDraw, m_hfAmbient);
  1568. GetTextFace(di.hdcDraw,ARRAYSIZE(szFace), szFace);
  1569. if (szFace[0] && GetTextMetrics(di.hdcDraw,&tm))
  1570. {
  1571. hFontHilite = CreateFont(tm.tmHeight,
  1572. tm.tmAveCharWidth,
  1573. 0, //Escapement,
  1574. 0, //Orientation,
  1575. tm.tmWeight,
  1576. (DWORD) tm.tmItalic,
  1577. (DWORD) m_bHilite, // Hilite is by underlining
  1578. tm.tmStruckOut,
  1579. tm.tmCharSet,
  1580. OUT_DEFAULT_PRECIS,
  1581. CLIP_DEFAULT_PRECIS,
  1582. DEFAULT_QUALITY,
  1583. tm.tmPitchAndFamily,
  1584. szFace);
  1585. if (hFontHilite)
  1586. {
  1587. SelectFont(di.hdcDraw, hFontHilite);
  1588. }
  1589. }
  1590. OLE_COLOR oclrTxt, oclrBk;
  1591. COLORREF clrTxtPrev, clrBkPrev;
  1592. HRESULT hrTxt, hrBk;
  1593. hrTxt = GetAmbientForeColor(oclrTxt);
  1594. if (SUCCEEDED(hrTxt))
  1595. clrTxtPrev = SetTextColor(di.hdcDraw, _TranslateColor(oclrTxt));
  1596. hrBk = GetAmbientBackColor(oclrBk);
  1597. if (SUCCEEDED(hrBk))
  1598. clrBkPrev = SetBkColor(di.hdcDraw, _TranslateColor(oclrBk));
  1599. TextOut(di.hdcDraw, rc.left + lImageWidth + m_cxLabelGap, rc.top + lImageHeight/2 - m_sizLabel.cy/2,
  1600. m_pszDisplayName, lstrlen(m_pszDisplayName));
  1601. if (m_bHasRect)
  1602. {
  1603. RECT rcFocus;
  1604. rcFocus.top = rc.top + lImageHeight/2 - m_sizLabel.cy/2;
  1605. rcFocus.bottom = rcFocus.top + m_sizLabel.cy;
  1606. rcFocus.left = rc.left + lImageWidth + m_cxLabelGap - 1;
  1607. rcFocus.right = rcFocus.left + m_sizLabel.cx + 1;
  1608. DrawFocusRect(di.hdcDraw, &rcFocus);
  1609. }
  1610. if (SUCCEEDED(hrTxt))
  1611. SetTextColor(di.hdcDraw, clrTxtPrev);
  1612. if (SUCCEEDED(hrBk))
  1613. SetBkColor(di.hdcDraw, clrBkPrev);
  1614. SelectFont(di.hdcDraw, hfPrev);
  1615. if (hFontHilite)
  1616. {
  1617. DeleteObject(hFontHilite);
  1618. hFontHilite = NULL;
  1619. }
  1620. }
  1621. return S_OK;
  1622. }
  1623. HRESULT CWebViewFolderIcon::OnWindowLoad()
  1624. {
  1625. return InitImage();
  1626. }
  1627. HRESULT CWebViewFolderIcon::OnImageChanged()
  1628. {
  1629. HRESULT hr = InitImage();
  1630. if (SUCCEEDED(hr))
  1631. ForceRedraw();
  1632. return hr;
  1633. }
  1634. HRESULT CWebViewFolderIcon::OnWindowUnLoad()
  1635. {
  1636. // nothing here now...
  1637. return S_OK;
  1638. }
  1639. STDMETHODIMP CWebViewFolderIcon::get_scale(BSTR *pbstrScale)
  1640. {
  1641. WCHAR wzScale[MAX_SCALE_STR];
  1642. wnsprintfW(wzScale, ARRAYSIZE(wzScale), L"%d", m_percentScale);
  1643. *pbstrScale = SysAllocString(wzScale);
  1644. return S_OK;
  1645. }
  1646. STDMETHODIMP CWebViewFolderIcon::put_scale(BSTR bstrScale)
  1647. {
  1648. int numchar = lstrlenW(bstrScale);
  1649. int tempScale = 0;
  1650. if (numchar && bstrScale[numchar-1] == '%')
  1651. {
  1652. tempScale = GetPercentFromStrW(bstrScale);
  1653. }
  1654. else
  1655. {
  1656. // valid number
  1657. for (int i=0 ; i < (numchar-2) ; i++)
  1658. {
  1659. if (!((bstrScale[i] >= '0') && (bstrScale[i] <= '9')))
  1660. {
  1661. tempScale = -1;
  1662. break;
  1663. }
  1664. }
  1665. if ((tempScale != -1) && !StrToIntExW(bstrScale, STIF_DEFAULT, &tempScale))
  1666. {
  1667. tempScale = -1;
  1668. }
  1669. }
  1670. if (tempScale > 0)
  1671. {
  1672. if (m_percentScale != tempScale)
  1673. {
  1674. m_percentScale = tempScale;
  1675. return UpdateSize();
  1676. }
  1677. else
  1678. return S_OK;
  1679. }
  1680. return S_FALSE;
  1681. }
  1682. STDMETHODIMP CWebViewFolderIcon::get_advproperty(VARIANT_BOOL *pvarbAdvProp)
  1683. {
  1684. *pvarbAdvProp = (VARIANT_BOOL)m_bAdvPropsOn;
  1685. return S_OK;
  1686. }
  1687. STDMETHODIMP CWebViewFolderIcon::put_advproperty(VARIANT_BOOL varbAdvProp)
  1688. {
  1689. if (varbAdvProp != m_bAdvPropsOn)
  1690. {
  1691. m_bAdvPropsOn = varbAdvProp;
  1692. return OnImageChanged();
  1693. }
  1694. return S_OK;
  1695. }
  1696. STDMETHODIMP CWebViewFolderIcon::get_view(BSTR *pbstrView)
  1697. {
  1698. HRESULT hr = S_FALSE;
  1699. LPCWSTR pwzTempView;
  1700. switch (m_ViewCurrent)
  1701. {
  1702. case VIEW_THUMBVIEW:
  1703. {
  1704. pwzTempView = SZ_THUMB_VIEW;
  1705. break;
  1706. }
  1707. case VIEW_PIECHART:
  1708. {
  1709. pwzTempView = SZ_PIE_VIEW;
  1710. break;
  1711. }
  1712. case VIEW_SMALLICON:
  1713. {
  1714. pwzTempView = SZ_SMALL_ICON;
  1715. break;
  1716. }
  1717. case VIEW_SMALLICONLABEL:
  1718. {
  1719. pwzTempView = SZ_SMALL_ICON_LABEL;
  1720. break;
  1721. }
  1722. case VIEW_LARGEICONLABEL:
  1723. {
  1724. pwzTempView = SZ_LARGE_ICON_LABEL;
  1725. break;
  1726. }
  1727. default: // default and large icon
  1728. {
  1729. pwzTempView = SZ_LARGE_ICON;
  1730. break;
  1731. }
  1732. }
  1733. *pbstrView = SysAllocString(pwzTempView);
  1734. if (*pbstrView)
  1735. hr = S_OK;
  1736. return hr;
  1737. }
  1738. STDMETHODIMP CWebViewFolderIcon::put_view(BSTR bstrView)
  1739. {
  1740. HRESULT hr = S_OK;
  1741. VIEWS View = VIEW_LARGEICON;
  1742. if (StrCmpIW(bstrView, SZ_LARGE_ICON) == 0)
  1743. {
  1744. View = VIEW_LARGEICON;
  1745. }
  1746. else if (StrCmpIW(bstrView, SZ_SMALL_ICON) == 0)
  1747. {
  1748. View = VIEW_SMALLICON;
  1749. }
  1750. else if (StrCmpIW(bstrView, SZ_SMALL_ICON_LABEL) == 0)
  1751. {
  1752. View = VIEW_SMALLICONLABEL;
  1753. }
  1754. else if (StrCmpIW(bstrView, SZ_LARGE_ICON_LABEL) == 0)
  1755. {
  1756. View = VIEW_LARGEICONLABEL;
  1757. }
  1758. else if (StrCmpIW(bstrView, SZ_THUMB_VIEW) == 0)
  1759. {
  1760. View = VIEW_THUMBVIEW;
  1761. }
  1762. else if (StrCmpIW(bstrView, SZ_PIE_VIEW) == 0)
  1763. {
  1764. View = VIEW_PIECHART;
  1765. }
  1766. else
  1767. hr = S_FALSE;
  1768. if ((S_OK == hr) && (m_ViewUser != View))
  1769. {
  1770. m_ViewUser = View;
  1771. hr = OnImageChanged();
  1772. }
  1773. return hr;
  1774. }
  1775. /**************************************************************\
  1776. DESCRIPTION:
  1777. The caller is getting the path of our control.
  1778. SECURITY:
  1779. We only trust callers from the LocalZone. This method
  1780. secifically worries about untrusted callers using us to
  1781. find out what paths on the file system exists or don't exist.
  1782. \**************************************************************/
  1783. STDMETHODIMP CWebViewFolderIcon::get_path(BSTR *pbstrPath)
  1784. {
  1785. AssertMsg((NULL != m_spClientSite.p), TEXT("CWebViewFolderIcon::get_path() We need m_spClientSite for our security test and it's NULL. BAD, BAD, BAD!"));
  1786. HRESULT hr = LocalZoneCheck(m_spClientSite);
  1787. if ((S_OK != hr) && !_IsPubWizHosted())
  1788. {
  1789. // We don't trust this host, so we are going to not carry
  1790. // out the action. We are going to return E_ACCESSDENIED so they can't
  1791. // determine if the path exists or not.
  1792. hr = E_ACCESSDENIED;
  1793. }
  1794. else
  1795. {
  1796. LPITEMIDLIST pidlFull;
  1797. hr = S_FALSE;
  1798. *pbstrPath = NULL;
  1799. if (S_OK == _GetFullPidl(&pidlFull))
  1800. {
  1801. WCHAR wzPath[INTERNET_MAX_URL_LENGTH];
  1802. if (S_OK == SHGetNameAndFlagsW(pidlFull, SHGDN_FORPARSING, wzPath, ARRAYSIZE(wzPath), NULL))
  1803. {
  1804. *pbstrPath = SysAllocString(wzPath);
  1805. if (*pbstrPath)
  1806. hr = S_OK;
  1807. }
  1808. ILFree(pidlFull);
  1809. }
  1810. }
  1811. return hr;
  1812. }
  1813. /**************************************************************\
  1814. DESCRIPTION:
  1815. The caller is setting the path of our control. Our
  1816. control will render a view of this item, which is often and
  1817. icon.
  1818. SECURITY:
  1819. We only trust callers from the LocalZone. This method
  1820. secifically worries about untrusted callers using us to
  1821. find out what paths on the file system exists or don't exist.
  1822. \**************************************************************/
  1823. STDMETHODIMP CWebViewFolderIcon::put_path(BSTR bstrPath)
  1824. {
  1825. AssertMsg((NULL != m_spClientSite.p), TEXT("CWebViewFolderIcon::put_path() We need m_spClientSite for our security test and it's NULL. BAD, BAD, BAD!"));
  1826. HRESULT hr = LocalZoneCheck(m_spClientSite);
  1827. if ((S_OK != hr) && !_IsPubWizHosted())
  1828. {
  1829. // We don't trust this host, so we are going to not carry
  1830. // out the action. We are going to return E_ACCESSDENIED so they can't
  1831. // determine if the path exists or not.
  1832. hr = E_ACCESSDENIED;
  1833. }
  1834. else
  1835. {
  1836. hr = S_FALSE;
  1837. LPITEMIDLIST pidlNew;
  1838. hr = IEParseDisplayNameW(CP_ACP, bstrPath, &pidlNew);
  1839. if (SUCCEEDED(hr))
  1840. {
  1841. ATOMICRELEASE(m_pDropTargetCache); // We will want another IDropTarget for this new pidl.
  1842. ILFree(m_pidl);
  1843. m_pidl = pidlNew;
  1844. hr = OnImageChanged();
  1845. AssertMsg(SUCCEEDED(hr), TEXT("CWebViewFolderIcon::put_path() failed to create the image so the image will be incorrect. Please find out why."));
  1846. hr = S_OK;
  1847. }
  1848. }
  1849. return hr;
  1850. }
  1851. // Automation methods to get/put FolderItem objects from FolderIcon
  1852. STDMETHODIMP CWebViewFolderIcon::get_item(FolderItem ** ppFolderItem)
  1853. {
  1854. HRESULT hr = LocalZoneCheck(m_spClientSite);
  1855. if (S_OK != hr)
  1856. {
  1857. // We don't trust this host, so we are going to not carry
  1858. // out the action. We are going to return E_ACCESSDENIED so they can't
  1859. // determine if the path exists or not.
  1860. hr = E_ACCESSDENIED;
  1861. }
  1862. else
  1863. {
  1864. LPITEMIDLIST pidlFull;
  1865. *ppFolderItem = NULL;
  1866. hr = _GetFullPidl(&pidlFull);
  1867. if ((hr == S_OK) && pidlFull)
  1868. {
  1869. IShellDispatch * psd;
  1870. hr = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellDispatch, &psd));
  1871. if (SUCCEEDED(hr))
  1872. {
  1873. IObjectSafety * pos;
  1874. hr = psd->QueryInterface(IID_PPV_ARG(IObjectSafety, &pos));
  1875. if (SUCCEEDED(hr))
  1876. {
  1877. // Simulate what trident does.
  1878. hr = pos->SetInterfaceSafetyOptions(IID_IDispatch, INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER);
  1879. if (SUCCEEDED(hr))
  1880. {
  1881. VARIANT varDir;
  1882. hr = InitVariantFromIDList(&varDir, pidlFull);
  1883. if (SUCCEEDED(hr))
  1884. {
  1885. IObjectWithSite * pows;
  1886. hr = psd->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pows));
  1887. if (SUCCEEDED(hr))
  1888. {
  1889. Folder *psdf;
  1890. // If we call ::SetSite(), they will display UI to ask the user if they want to allow this.
  1891. // This is annoying because Trident will always call our get_item() when they load our object
  1892. // tag.
  1893. pows->SetSite(m_spClientSite);
  1894. hr = psd->NameSpace(varDir, &psdf);
  1895. if (S_OK == hr)
  1896. {
  1897. Folder2 *psdf2;
  1898. hr = psdf->QueryInterface(IID_PPV_ARG(Folder2, &psdf2));
  1899. if (S_OK == hr)
  1900. {
  1901. hr = psdf2->get_Self(ppFolderItem);
  1902. psdf2->Release();
  1903. }
  1904. psdf->Release();
  1905. }
  1906. pows->SetSite(NULL);
  1907. pows->Release();
  1908. }
  1909. VariantClear(&varDir);
  1910. }
  1911. }
  1912. pos->Release();
  1913. }
  1914. psd->Release();
  1915. }
  1916. ILFree(pidlFull);
  1917. }
  1918. // Automation method can't fail or hard script error. We do want a hard
  1919. // script error on access denied, however.
  1920. if (FAILED(hr) && (hr != E_ACCESSDENIED))
  1921. {
  1922. hr = S_FALSE;
  1923. }
  1924. }
  1925. return hr;
  1926. }
  1927. STDMETHODIMP CWebViewFolderIcon::put_item(FolderItem * pFolderItem)
  1928. {
  1929. HRESULT hr = LocalZoneCheck(m_spClientSite);
  1930. if ((S_OK != hr) && !_IsPubWizHosted())
  1931. {
  1932. // We don't trust this host, so we are going to not carry
  1933. // out the action. We are going to return E_ACCESSDENIED so they can't
  1934. // determine if the path exists or not.
  1935. hr = E_ACCESSDENIED;
  1936. }
  1937. else
  1938. {
  1939. hr = S_FALSE;
  1940. LPITEMIDLIST pidlNew;
  1941. if (S_OK == SHGetIDListFromUnk(pFolderItem, &pidlNew))
  1942. {
  1943. ATOMICRELEASE(m_pDropTargetCache); // We will want another IDropTarget for this new pidl.
  1944. ILFree(m_pidl);
  1945. m_pidl = pidlNew;
  1946. hr = OnImageChanged();
  1947. if (FAILED(hr))
  1948. {
  1949. hr = S_FALSE;
  1950. }
  1951. }
  1952. }
  1953. return hr;
  1954. }
  1955. STDMETHODIMP CWebViewFolderIcon::get_clickStyle(LONG *plClickStyle)
  1956. {
  1957. *plClickStyle = m_clickStyle;
  1958. return S_OK;
  1959. }
  1960. STDMETHODIMP CWebViewFolderIcon::put_clickStyle(LONG lClickStyle)
  1961. {
  1962. switch (lClickStyle)
  1963. {
  1964. case 1: /* oneclick - weblike */
  1965. case 2: /* twoclick - explorer-like */
  1966. m_clickStyle = lClickStyle;
  1967. break;
  1968. default: /* Ignore invalid arguments to keep script happy */
  1969. break;
  1970. }
  1971. return S_OK;
  1972. }
  1973. STDMETHODIMP CWebViewFolderIcon::get_labelGap(LONG *plLabelGap)
  1974. {
  1975. *plLabelGap = m_cxLabelGap;
  1976. return S_OK;
  1977. }
  1978. STDMETHODIMP CWebViewFolderIcon::put_labelGap(LONG lLabelGap)
  1979. {
  1980. if (m_cxLabelGap != lLabelGap)
  1981. {
  1982. m_cxLabelGap = lLabelGap;
  1983. UpdateSize();
  1984. }
  1985. return S_OK;
  1986. }
  1987. STDMETHODIMP CWebViewFolderIcon::setSlice(int index, VARIANT varHiBytes, VARIANT varLoBytes, VARIANT varColorref)
  1988. {
  1989. HRESULT hr = S_FALSE;
  1990. PieSlice_S pieSlice;
  1991. if ((varHiBytes.vt == VT_I4) && (varLoBytes.vt == VT_I4))
  1992. pieSlice.MemSize = GetUllMemFromVars(&varHiBytes, &varLoBytes);
  1993. // Passed a COLORREF
  1994. if (varColorref.vt == VT_I4)
  1995. {
  1996. pieSlice.Color = (COLORREF)varColorref.lVal;
  1997. }
  1998. // Passed a string
  1999. else if (varColorref.vt == VT_BSTR)
  2000. pieSlice.Color = ColorRefFromHTMLColorStrW(varColorref.bstrVal);
  2001. else
  2002. return hr;
  2003. if (DSA_SetItem(m_hdsaSlices, index, &pieSlice))
  2004. {
  2005. if (index > (m_highestIndexSlice - 1))
  2006. m_highestIndexSlice = (index + 1);
  2007. hr = OnImageChanged();
  2008. }
  2009. return hr;
  2010. }
  2011. /////////////////////////////////////////////////////////////////////////////
  2012. // IObjectSafetyImpl overrides
  2013. STDMETHODIMP CWebViewFolderIcon::SetInterfaceSafetyOptions(REFIID riid,
  2014. DWORD dwOptionSetMask,
  2015. DWORD dwEnabledOptions)
  2016. {
  2017. // If we're being asked to set our safe for scripting option then oblige
  2018. if (riid == IID_IDispatch || riid == IID_IPersistPropertyBag)
  2019. {
  2020. // Store our current safety level to return in GetInterfaceSafetyOptions
  2021. m_dwCurrentSafety = dwEnabledOptions & dwOptionSetMask;
  2022. return S_OK;
  2023. }
  2024. return E_NOINTERFACE;
  2025. }
  2026. // Handle Window messages for the thumbnail bitmap
  2027. LRESULT CALLBACK CWebViewFolderIcon::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2028. {
  2029. CWebViewFolderIcon *ptc = (CWebViewFolderIcon *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  2030. switch(uMsg)
  2031. {
  2032. case WM_CREATE:
  2033. {
  2034. ptc = (CWebViewFolderIcon *)((CREATESTRUCT *)lParam)->lpCreateParams;
  2035. ::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)ptc);
  2036. }
  2037. break;
  2038. // NOTE: do not need to check to see that the bitmap coming through is the one you want since each control has its own
  2039. // message wnd.
  2040. case WM_HTML_BITMAP:
  2041. // check that ptc is still alive and that you have an HBITMAP
  2042. if (ptc && (ptc->m_dwThumbnailID == wParam))
  2043. {
  2044. if (ptc->m_hbm != NULL)
  2045. {
  2046. DeleteObject(ptc->m_hbm);
  2047. }
  2048. ptc->m_hbm = (HBITMAP)lParam;
  2049. ptc->_InvokeOnThumbnailReady();
  2050. ptc->ForceRedraw();
  2051. }
  2052. else if (lParam)
  2053. {
  2054. DeleteObject((HBITMAP)lParam);
  2055. }
  2056. break;
  2057. case WM_MEASUREITEM:
  2058. case WM_DRAWITEM:
  2059. case WM_INITMENUPOPUP:
  2060. if (ptc && ptc->m_pcm3)
  2061. ptc->m_pcm3->HandleMenuMsg(uMsg, wParam, lParam);
  2062. break;
  2063. case WM_DESTROY:
  2064. // ignore late messages
  2065. if (ptc)
  2066. {
  2067. MSG msg;
  2068. while(PeekMessage(&msg, hwnd, WM_HTML_BITMAP, WM_HTML_BITMAP, PM_REMOVE))
  2069. {
  2070. if (msg.lParam)
  2071. {
  2072. DeleteObject((HBITMAP)msg.lParam);
  2073. }
  2074. }
  2075. ::SetWindowLongPtr(hwnd, GWLP_USERDATA, NULL);
  2076. }
  2077. break;
  2078. default:
  2079. return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
  2080. }
  2081. return 0;
  2082. }
  2083. // Pie chart functions
  2084. HRESULT CWebViewFolderIcon::ComputeFreeSpace(LPCWSTR pszFileName)
  2085. {
  2086. return _ComputeFreeSpace(pszFileName, m_ullFreeSpace,
  2087. m_ullUsedSpace, m_ullTotalSpace);
  2088. }
  2089. // Draw3dPie draws the pie chart with the used slice and the additional slices in m_hdsaSlices
  2090. // Look in drawpie.c for the majority of the code (including member functions called within this one)
  2091. HRESULT CWebViewFolderIcon::Draw3dPie(HDC hdc, LPRECT lprc, DWORD dwPercent1000, const COLORREF *pColors)
  2092. {
  2093. LONG ShadowDepth;
  2094. ASSERT(lprc != NULL && pColors != NULL);
  2095. const LONG c_ShadowScale = 6; // ratio of shadow depth to height
  2096. const LONG c_AspectRatio = 2; // ratio of width : height of ellipse
  2097. ScalePieRect(c_ShadowScale, c_AspectRatio, lprc);
  2098. // Compute a shadow depth based on height of the image
  2099. ShadowDepth = (lprc->bottom - lprc->top) / c_ShadowScale;
  2100. // Check dwPercent1000 to ensure within bounds. Shouldn't be but check anyway.
  2101. // dwPercent1000 is the percentage of used space based out of 1000.
  2102. if (dwPercent1000 > 1000)
  2103. dwPercent1000 = 1000;
  2104. // Now the drawing portion
  2105. RECT rcItem;
  2106. int cx, cy; // Center of the pie
  2107. int rx, ry; // Center of the rectangle
  2108. int x, y; // Radial intersection of the slices
  2109. int FirstQuadPercent1000;
  2110. // Set up the pie rectangle
  2111. rcItem = *lprc;
  2112. rcItem.left = lprc->left;
  2113. rcItem.top = lprc->top;
  2114. rcItem.right = lprc->right - rcItem.left;
  2115. rcItem.bottom = lprc->bottom - rcItem.top - ShadowDepth;
  2116. SetUpPiePts(&cx, &cy, &rx, &ry, rcItem);
  2117. if ((rx <= 10) || (ry <= 10))
  2118. {
  2119. return S_FALSE;
  2120. }
  2121. // Make the rectangle a little more accurate
  2122. rcItem.right = (2 * rx) + rcItem.left;
  2123. rcItem.bottom = (2 * ry) + rcItem.top;
  2124. // Translate the used percentage to first quadrant
  2125. FirstQuadPercent1000 = (dwPercent1000 % 500) - 250;
  2126. if (FirstQuadPercent1000 < 0)
  2127. {
  2128. FirstQuadPercent1000 = -FirstQuadPercent1000;
  2129. }
  2130. // Find the slice intersection for the used slice
  2131. CalcSlicePoint(&x, &y, rx, ry, cx, cy, FirstQuadPercent1000, dwPercent1000);
  2132. DrawEllipse(hdc, rcItem, x, y, cx, cy, dwPercent1000, pColors);
  2133. // Used pie slice.
  2134. DrawSlice(hdc, rcItem, dwPercent1000, rx, ry, cx, cy, pColors[COLOR_UP]);
  2135. // Iterate through and draw the slices in m_hdsaSlices.
  2136. PieSlice_S pieSlice;
  2137. ULONGLONG ullMemTotal = 0; // Keep track of memory in the m_hdsaSlices slices
  2138. DWORD dwPercentTotal; // 1000 Percentage of memory in slices
  2139. for (int i=0; i < m_highestIndexSlice; i++)
  2140. {
  2141. if (DSA_GetItemPtr(m_hdsaSlices, i) != NULL)
  2142. {
  2143. DSA_GetItem(m_hdsaSlices, i, &pieSlice);
  2144. ullMemTotal += pieSlice.MemSize;
  2145. }
  2146. }
  2147. ComputeSlicePct(ullMemTotal, &dwPercentTotal);
  2148. if (m_highestIndexSlice)
  2149. {
  2150. for (i = (m_highestIndexSlice - 1); i >= 0; i--)
  2151. {
  2152. if (DSA_GetItemPtr(m_hdsaSlices, i))
  2153. {
  2154. DSA_GetItem(m_hdsaSlices, i, &pieSlice);
  2155. DrawSlice(hdc, rcItem, dwPercentTotal, rx, ry, cx, cy, pieSlice.Color);
  2156. ullMemTotal -= pieSlice.MemSize;
  2157. ComputeSlicePct(ullMemTotal, &dwPercentTotal);
  2158. }
  2159. }
  2160. }
  2161. DrawShadowRegions(hdc, rcItem, lprc, x, cy, ShadowDepth, dwPercent1000, pColors);
  2162. DrawPieDepth(hdc, rcItem, x, y, cy, dwPercent1000, ShadowDepth);
  2163. // Redraw the bottom line of the pie because it has been painted over
  2164. Arc(hdc, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom,
  2165. rcItem.left, cy, rcItem.right, cy);
  2166. return S_OK; // Everything worked fine
  2167. }
  2168. void CWebViewFolderIcon::ScalePieRect(LONG ShadowScale, LONG AspectRatio, LPRECT lprc)
  2169. {
  2170. LONG rectHeight;
  2171. LONG rectWidth;
  2172. LONG TargetHeight;
  2173. LONG TargetWidth;
  2174. // We make sure that the aspect ratio of the pie-chart is always preserved
  2175. // regardless of the shape of the given rectangle
  2176. // Stabilize the aspect ratio
  2177. rectHeight = lprc->bottom - lprc->top;
  2178. rectWidth = lprc->right - lprc->left;
  2179. if ((rectHeight * AspectRatio) <= rectWidth)
  2180. TargetHeight = rectHeight;
  2181. else
  2182. TargetHeight = rectWidth / AspectRatio;
  2183. TargetWidth = TargetHeight * AspectRatio;
  2184. // Shrink the rectangle to the correct size
  2185. lprc->top += (rectHeight - TargetHeight) / 2;
  2186. lprc->bottom = lprc->top + TargetHeight;
  2187. lprc->left += (rectWidth - TargetWidth) / 2;
  2188. lprc->right = lprc->left + TargetWidth;
  2189. }
  2190. // Calculate center of rectangle and center of pie points
  2191. void CWebViewFolderIcon::SetUpPiePts(int *pcx, int *pcy, int *prx, int *pry, RECT rect)
  2192. {
  2193. *prx = rect.right / 2;
  2194. *pcx = rect.left + *prx - 1;
  2195. *pry = rect.bottom / 2;
  2196. *pcy = rect.top + *pry - 1;
  2197. }
  2198. void CWebViewFolderIcon::DrawShadowRegions(HDC hdc, RECT rect, LPRECT lprc, int UsedArc_x, int center_y,
  2199. LONG ShadowDepth, DWORD dwPercent1000, const COLORREF *pColors)
  2200. {
  2201. HBRUSH hBrush;
  2202. HRGN hEllipticRgn = CreateEllipticRgnIndirect(&rect);
  2203. HRGN hEllRect = CreateRectRgn(rect.left, center_y, rect.right, center_y + ShadowDepth);
  2204. HRGN hRectRgn = CreateRectRgn(0, 0, 0, 0);
  2205. // Move the ellipse up so it doesn't run into the shadow
  2206. OffsetRgn(hEllipticRgn, 0, ShadowDepth);
  2207. // Union the Ellipse and the Ellipse rect together into hRectRegn
  2208. CombineRgn(hRectRgn, hEllipticRgn, hEllRect, RGN_OR);
  2209. OffsetRgn(hEllipticRgn, 0, -(int)ShadowDepth);
  2210. CombineRgn(hEllRect, hRectRgn, hEllipticRgn, RGN_DIFF);
  2211. // Always draw the whole area in the free shadow
  2212. hBrush = CreateSolidBrush(pColors[COLOR_DNSHADOW]);
  2213. if (hBrush)
  2214. {
  2215. FillRgn(hdc, hEllRect, hBrush);
  2216. DeleteObject(hBrush);
  2217. }
  2218. // Draw a shadow for the used section only if the disk is at least half used
  2219. hBrush = CreateSolidBrush(pColors[COLOR_UPSHADOW]);
  2220. if ((dwPercent1000 > 500) && hBrush)
  2221. {
  2222. DeleteObject(hRectRgn);
  2223. hRectRgn = CreateRectRgn(UsedArc_x, center_y, rect.right, lprc->bottom);
  2224. CombineRgn(hEllipticRgn, hEllRect, hRectRgn, RGN_AND);
  2225. FillRgn(hdc, hEllipticRgn, hBrush);
  2226. DeleteObject(hBrush);
  2227. }
  2228. DeleteObject(hRectRgn);
  2229. DeleteObject(hEllipticRgn);
  2230. DeleteObject(hEllRect);
  2231. }
  2232. void CWebViewFolderIcon::CalcSlicePoint(int *x, int *y, int rx, int ry, int cx, int cy, int FirstQuadPercent1000, DWORD dwPercent1000)
  2233. {
  2234. // Use a triangle area approximation based on the ellipse's rect to calculate the point since
  2235. // an exact calculation of the area of the slice and percentage of the pie would be costly and
  2236. // a hassle.
  2237. // The approximation is better this way if FirstQuadPercent1000 is in the first half of the quadrant. Use 120 as the
  2238. // halfway point (instead of 125) because it looks better that way on an ellipse.
  2239. if (FirstQuadPercent1000 < 120)
  2240. {
  2241. *x = IntSqrt(((DWORD)rx*(DWORD)rx*(DWORD)FirstQuadPercent1000*(DWORD)FirstQuadPercent1000)
  2242. /((DWORD)FirstQuadPercent1000*(DWORD)FirstQuadPercent1000+(250L-(DWORD)FirstQuadPercent1000)
  2243. *(250L-(DWORD)FirstQuadPercent1000)));
  2244. *y = IntSqrt(((DWORD)rx*(DWORD)rx-(DWORD)(*x)*(DWORD)(*x))*(DWORD)ry*(DWORD)ry/((DWORD)rx*(DWORD)rx));
  2245. }
  2246. else
  2247. {
  2248. *y = IntSqrt((DWORD)ry*(DWORD)ry*(250L-(DWORD)FirstQuadPercent1000)*(250L-(DWORD)FirstQuadPercent1000)
  2249. /((DWORD)FirstQuadPercent1000*(DWORD)FirstQuadPercent1000+(250L-(DWORD)FirstQuadPercent1000)
  2250. *(250L-(DWORD)FirstQuadPercent1000)));
  2251. *x = IntSqrt(((DWORD)ry*(DWORD)ry-(DWORD)(*y)*(DWORD)(*y))*(DWORD)rx*(DWORD)rx/((DWORD)ry*(DWORD)ry));
  2252. }
  2253. // Adjust for the actual quadrant (These aren't quadrants like in the real Cartesian coordinate system.
  2254. switch (dwPercent1000 / 250)
  2255. {
  2256. case 1: // First Quadrant
  2257. *y = -(*y);
  2258. break;
  2259. case 2: // Second Quadrant
  2260. break;
  2261. case 3: // Third Quadrant
  2262. *x = -(*x);
  2263. break;
  2264. default: // Fourth Quadrant
  2265. *x = -(*x);
  2266. *y = -(*y);
  2267. break;
  2268. }
  2269. // Now adjust for the center.
  2270. *x += cx;
  2271. *y += cy;
  2272. }
  2273. void CWebViewFolderIcon::ComputeSlicePct(ULONGLONG ullMemSize, DWORD *pdwPercent1000)
  2274. {
  2275. // some special cases require interesting treatment
  2276. if ((ullMemSize == 0) || (m_ullFreeSpace == m_ullTotalSpace))
  2277. {
  2278. *pdwPercent1000 = 0;
  2279. }
  2280. else if (ullMemSize == 0)
  2281. {
  2282. *pdwPercent1000 = 1000;
  2283. }
  2284. else
  2285. {
  2286. // not completely full or empty
  2287. *pdwPercent1000 = (DWORD)(ullMemSize * 1000 / m_ullTotalSpace);
  2288. // if pdwPercent1000 is especially big or small and rounds incorrectly, you still want
  2289. // to see a little slice.
  2290. if (*pdwPercent1000 == 0)
  2291. {
  2292. *pdwPercent1000 = 1;
  2293. }
  2294. else if (*pdwPercent1000 == 1000)
  2295. {
  2296. *pdwPercent1000 = 999;
  2297. }
  2298. }
  2299. }
  2300. void CWebViewFolderIcon::DrawPieDepth(HDC hdc, RECT rect, int x, int y, int cy, DWORD dwPercent1000, LONG ShadowDepth)
  2301. {
  2302. HPEN hPen, hOldPen;
  2303. hPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME));
  2304. hOldPen = (HPEN__*) SelectObject(hdc, hPen);
  2305. Arc(hdc, rect.left, rect.top + ShadowDepth, rect.right, rect.bottom + ShadowDepth,
  2306. rect.left, cy + ShadowDepth, rect.right, cy + ShadowDepth - 1);
  2307. MoveToEx(hdc, rect.left, cy, NULL);
  2308. LineTo(hdc, rect.left, cy + ShadowDepth);
  2309. MoveToEx(hdc, rect.right - 1, cy, NULL);
  2310. LineTo(hdc, rect.right - 1, cy + ShadowDepth);
  2311. if ((dwPercent1000 > 500) && (dwPercent1000 < 1000))
  2312. {
  2313. MoveToEx(hdc, x, y, NULL);
  2314. LineTo(hdc, x, y + ShadowDepth);
  2315. }
  2316. SelectObject(hdc, hOldPen);
  2317. DeleteObject(hPen);
  2318. }
  2319. // Draw a pie slice. One side is always from the middle of the pie horizontally to the left. The other
  2320. // slice is defined by x and y.
  2321. void CWebViewFolderIcon::DrawSlice(HDC hdc, RECT rect, DWORD dwPercent1000, int rx, int ry, int cx, int cy, /*int *px, int *py,*/
  2322. COLORREF Color)
  2323. {
  2324. HBRUSH hBrush, hOldBrush;
  2325. HPEN hPen, hOldPen;
  2326. int FirstQuadPercent1000; // slice percentage based out of 1000 in the first quadrant
  2327. int x, y; // intersection with the ellipse
  2328. // Translate to first quadrant
  2329. FirstQuadPercent1000 = (dwPercent1000 % 500) - 250;
  2330. if (FirstQuadPercent1000 < 0)
  2331. {
  2332. FirstQuadPercent1000 = -FirstQuadPercent1000;
  2333. }
  2334. CalcSlicePoint(&x, &y, rx, ry, cx, cy, FirstQuadPercent1000, dwPercent1000);
  2335. hPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME));
  2336. hOldPen = (HPEN__*) SelectObject(hdc, hPen);
  2337. if ((dwPercent1000 != 0) && (dwPercent1000 != 1000))
  2338. {
  2339. // display small sub-section of ellipse for smaller part
  2340. hBrush = CreateSolidBrush(Color);
  2341. hOldBrush = (HBRUSH__*) SelectObject(hdc, hBrush);
  2342. // Make sure it colors correctly
  2343. if (cy == y)
  2344. {
  2345. if (dwPercent1000 < 500)
  2346. y--;
  2347. else
  2348. y++;
  2349. }
  2350. Pie(hdc, rect.left, rect.top, rect.right, rect.bottom,
  2351. x, y, rect.left, cy);
  2352. SelectObject(hdc, hOldBrush);
  2353. DeleteObject(hBrush);
  2354. }
  2355. SelectObject(hdc, hOldPen);
  2356. DeleteObject(hPen);
  2357. }
  2358. void CWebViewFolderIcon::DrawEllipse(HDC hdc, RECT rect, int x, int y, int cx, int cy, DWORD dwPercent1000, const COLORREF *pColors)
  2359. {
  2360. HBRUSH hBrush, hOldBrush;
  2361. HPEN hPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME));
  2362. HPEN hOldPen = (HPEN__*) SelectObject(hdc, hPen);
  2363. // In this case the slice is miniscule
  2364. if ((dwPercent1000 < 500) && (y == cy) && (x < cx))
  2365. {
  2366. hBrush = CreateSolidBrush(pColors[COLOR_UP]);
  2367. }
  2368. else
  2369. {
  2370. hBrush = CreateSolidBrush(pColors[COLOR_DN]);
  2371. }
  2372. hOldBrush = (HBRUSH__*) SelectObject(hdc, hBrush);
  2373. Ellipse(hdc, rect.left, rect.top, rect.right, rect.bottom);
  2374. SelectObject(hdc, hOldBrush);
  2375. DeleteObject(hBrush);
  2376. SelectObject(hdc, hOldPen);
  2377. DeleteObject(hPen);
  2378. }