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

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