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.

2134 lines
61 KiB

  1. #include "priv.h"
  2. #include <iehelpid.h>
  3. #include <pstore.h>
  4. #include "hlframe.h"
  5. #include "shldisp.h"
  6. #include "opsprof.h"
  7. #include "resource.h"
  8. #include <mluisupp.h>
  9. #include "htmlstr.h"
  10. #include "mypics.h"
  11. #include "mshtmcid.h"
  12. #include "util.h"
  13. #include "winuser.h"
  14. //////////////////////////////////////////////////////////////////////////////////
  15. //
  16. // filename: mypics.cpp
  17. //
  18. // description: implements the my pictures exposure hoverbar thingie
  19. //
  20. // notes: lots of stuff is stolen from iforms.cpp and iformsp.h
  21. //
  22. // history: 06.15.2000 created by t-jdavis
  23. //
  24. //////////////////////////////////////////////////////////////////////////////////
  25. extern HINSTANCE g_hinst;
  26. #define TF_MYPICS TF_CUSTOM2
  27. // we don't actually use all of these, but we COULD, you know, if we wanted too.
  28. CMyPicsEventSinkCallback::EventSinkEntry CMyPicsEventSinkCallback::EventsToSink[] =
  29. {
  30. { EVENT_MOUSEOVER, L"onmouseover", L"mouseover" },
  31. { EVENT_MOUSEOUT, L"onmouseout", L"mouseout" },
  32. { EVENT_SCROLL, L"onscroll", L"scroll" },
  33. { EVENT_RESIZE, L"onresize", L"resize" }
  34. };
  35. // image toolbar states
  36. enum
  37. {
  38. HOVERSTATE_HIDING = 0,
  39. HOVERSTATE_SHOWING,
  40. HOVERSTATE_LOCKED,
  41. HOVERSTATE_SCROLLING,
  42. HOVERSTATE_WAITINGTOSHOW
  43. };
  44. //
  45. // CMyPics
  46. //
  47. // set some stuff
  48. CMyPics::CMyPics()
  49. {
  50. TraceMsg(TF_MYPICS, "+CMyPics::CMyPics");
  51. m_Hwnd = NULL;
  52. m_hWndMyPicsToolBar = NULL;
  53. m_hWndHover = NULL;
  54. m_wndprocOld = NULL;
  55. m_pEleCurr = NULL;
  56. m_pSink = NULL;
  57. m_bIsOffForSession = FALSE;
  58. m_cRef = 1;
  59. m_bGalleryMeta = TRUE;
  60. TraceMsg(TF_MYPICS, "-CMyPics::CMyPics");
  61. }
  62. // destroy whatever needs destroying....
  63. CMyPics::~CMyPics()
  64. {
  65. TraceMsg(TF_MYPICS, "+CMyPics::~CMyPics");
  66. DestroyHover();
  67. ATOMICRELEASE(m_pEleCurr);
  68. if (m_hWndMyPicsToolBar)
  69. DestroyWindow(m_hWndMyPicsToolBar);
  70. if (m_hWndHover)
  71. {
  72. if (m_wndprocOld)
  73. {
  74. SetWindowLongPtr(m_hWndHover, GWLP_WNDPROC, (LONG_PTR)m_wndprocOld);
  75. }
  76. SetWindowPtr(m_hWndHover, GWLP_USERDATA, NULL);
  77. DestroyWindow(m_hWndHover);
  78. }
  79. TraceMsg(TF_MYPICS, "-CMyPics::~CMyPics");
  80. }
  81. // did the user turn this feature off?
  82. BOOL CMyPics::IsOff()
  83. {
  84. return (m_bIsOffForSession);
  85. }
  86. void CMyPics::IsGalleryMeta(BOOL bFlag)
  87. {
  88. m_bGalleryMeta = bFlag;
  89. }
  90. HRESULT CMyPics::Init(IHTMLDocument2 *pDoc2)
  91. {
  92. HRESULT hr = S_OK;
  93. TraceMsg(TF_MYPICS, "+CMyPics::Init");
  94. ASSERT(pDoc2);
  95. //sink things
  96. IHTMLElement2 *pEle2 = NULL;
  97. IHTMLElementCollection *pCollect = NULL;
  98. IHTMLElementCollection *pSubCollect = NULL;
  99. IDispatch *pDisp = NULL;
  100. VARIANT TagName;
  101. ULONG ulCount = 0;
  102. VARIANTARG va1;
  103. VARIANTARG va2;
  104. IHTMLWindow3 *pWin3 = NULL;
  105. // ...remember this...
  106. m_pDoc2 = pDoc2;
  107. pDoc2->AddRef();
  108. // setup variant for finding all the IMG tags...
  109. TagName.vt = VT_BSTR;
  110. TagName.bstrVal = (BSTR)c_bstr_IMG;
  111. //get all tags
  112. hr = pDoc2->get_all(&pCollect);
  113. if (FAILED(hr))
  114. goto Cleanup;
  115. //get all IMG tags
  116. hr = pCollect->tags(TagName, &pDisp);
  117. if (FAILED(hr))
  118. goto Cleanup;
  119. if (pDisp)
  120. {
  121. hr = pDisp->QueryInterface(IID_IHTMLElementCollection,(void **)&pSubCollect);
  122. ATOMICRELEASE(pDisp);
  123. }
  124. if (FAILED(hr))
  125. goto Cleanup;
  126. //get IMG tag count
  127. hr = pSubCollect->get_length((LONG *)&ulCount);
  128. if (FAILED(hr))
  129. goto Cleanup;
  130. va1.vt = VT_I4;
  131. va2.vt = VT_EMPTY;
  132. //iterate through tags sinking events to elements
  133. for (int i=0; i<(LONG)ulCount; i++)
  134. {
  135. pDisp = NULL;
  136. va1.lVal = (LONG)i;
  137. pSubCollect->item(va1, va2, &pDisp);
  138. // only create a new CEventSink once
  139. if (!m_pSink && pDisp)
  140. m_pSink = new CEventSink(this);
  141. if (pDisp)
  142. {
  143. hr = pDisp->QueryInterface(IID_IHTMLElement2, (void **)&pEle2);
  144. if (FAILED(hr))
  145. goto Cleanup;
  146. ASSERT(m_pSink);
  147. if (m_pSink && pEle2)
  148. {
  149. EVENTS events[] = { EVENT_MOUSEOVER, EVENT_MOUSEOUT, EVENT_RESIZE };
  150. m_pSink->SinkEvents(pEle2, ARRAYSIZE(events), events);
  151. }
  152. ATOMICRELEASE(pEle2);
  153. ATOMICRELEASE(pDisp);
  154. }
  155. }
  156. // sink scroll event from the window, because it doesn't come from elements.
  157. if (m_pSink)
  158. {
  159. Win3FromDoc2(m_pDoc2, &pWin3);
  160. if (pWin3)
  161. {
  162. m_pWin3 = pWin3;
  163. m_pWin3->AddRef();
  164. EVENTS eventScroll[] = { EVENT_SCROLL };
  165. m_pSink->SinkEvents(pWin3, ARRAYSIZE(eventScroll), eventScroll);
  166. }
  167. }
  168. //end sinking things
  169. Cleanup:
  170. ATOMICRELEASE(pCollect);
  171. ATOMICRELEASE(pSubCollect);
  172. ATOMICRELEASE(pWin3);
  173. ATOMICRELEASE(pDisp);
  174. ATOMICRELEASE(pEle2);
  175. TraceMsg(TF_MYPICS, "-CMyPics::Init");
  176. return hr;
  177. }
  178. HRESULT CMyPics::UnInit()
  179. {
  180. // Unhook regular event sink
  181. TraceMsg(TF_MYPICS, "+CMyPics::UnInit");
  182. if (m_pSink)
  183. {
  184. if (m_pWin3)
  185. {
  186. EVENTS events[] = { EVENT_SCROLL };
  187. m_pSink->UnSinkEvents(m_pWin3, ARRAYSIZE(events), events);
  188. SAFERELEASE(m_pWin3);
  189. }
  190. m_pSink->SetParent(NULL);
  191. ATOMICRELEASE(m_pSink);
  192. }
  193. SAFERELEASE(m_pEleCurr);
  194. SAFERELEASE(m_pDoc2);
  195. TraceMsg(TF_MYPICS, "-CMyPics::UnInit");
  196. return S_OK;
  197. }
  198. STDMETHODIMP CMyPics::QueryInterface(REFIID riid, void **ppv)
  199. {
  200. *ppv = NULL;
  201. if ((IID_IPropertyNotifySink == riid) || (IID_IUnknown == riid))
  202. {
  203. *ppv = (IPropertyNotifySink *)this;
  204. }
  205. if (*ppv)
  206. {
  207. ((IUnknown *)*ppv)->AddRef();
  208. return S_OK;
  209. }
  210. return E_NOINTERFACE;
  211. }
  212. STDMETHODIMP_(ULONG) CMyPics::AddRef(void)
  213. {
  214. return ++m_cRef;
  215. }
  216. STDMETHODIMP_(ULONG) CMyPics::Release(void)
  217. {
  218. if (--m_cRef == 0)
  219. {
  220. delete this;
  221. return 0;
  222. }
  223. return m_cRef;
  224. }
  225. // has this been disabled by some administrator or something via IEAK?
  226. BOOL MP_IsEnabledInIEAK()
  227. {
  228. DWORD dwType = REG_DWORD;
  229. DWORD dwSize;
  230. DWORD dwEnabled;
  231. DWORD dwRet;
  232. const TCHAR c_szSPMIEPS[] = TEXT("Software\\Policies\\Microsoft\\Internet Explorer\\PhotoSupport");
  233. const TCHAR c_szVal[] = TEXT("MyPics_Hoverbar");
  234. dwSize = sizeof(dwEnabled);
  235. dwRet = SHGetValue(HKEY_CURRENT_USER, c_szSPMIEPS, c_szVal, &dwType, &dwEnabled, &dwSize);
  236. if ((dwType == REG_DWORD) && (dwRet == ERROR_SUCCESS))
  237. {
  238. if (dwEnabled!=1)
  239. return TRUE; // enabled
  240. else
  241. return FALSE; // disabled
  242. }
  243. // value not found...
  244. return TRUE;
  245. }
  246. // has the user explicitly disabled this feature for now and all time via intern control panel?
  247. BOOL MP_IsEnabledInRegistry()
  248. {
  249. DWORD dwType = REG_SZ;
  250. DWORD dwSize;
  251. TCHAR szEnabled[16];
  252. DWORD dwRet;
  253. const TCHAR c_szSMIEM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
  254. const TCHAR c_szVal[] = TEXT("Enable_MyPics_Hoverbar");
  255. dwSize = sizeof(szEnabled);
  256. dwRet = SHGetValue(HKEY_CURRENT_USER, c_szSMIEM, c_szVal, &dwType, szEnabled, &dwSize);
  257. if (dwRet == ERROR_INSUFFICIENT_BUFFER)
  258. {
  259. ASSERT(dwRet == ERROR_SUCCESS); // this is wacky...
  260. return FALSE;
  261. }
  262. if ((dwType == REG_SZ) && (dwRet == ERROR_SUCCESS))
  263. {
  264. if (!StrCmp(szEnabled, TEXT("yes")))
  265. return TRUE; // enabled
  266. else
  267. return FALSE; // disabled
  268. }
  269. // value not found...
  270. return TRUE;
  271. }
  272. // what should the default behavior be if an error occurs? hmm...
  273. // check status of the Show Pictures option in the inetcpl
  274. BOOL MP_ShowPicsIsOn()
  275. {
  276. DWORD dwType = REG_SZ;
  277. DWORD dwSize;
  278. TCHAR szEnabled[16];
  279. DWORD dwRet;
  280. const TCHAR c_szSMIEM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
  281. const TCHAR c_szVal[] = TEXT("Display Inline Images");
  282. dwSize = sizeof(szEnabled);
  283. dwRet = SHGetValue(HKEY_CURRENT_USER, c_szSMIEM, c_szVal, &dwType, szEnabled, &dwSize);
  284. if (dwRet == ERROR_INSUFFICIENT_BUFFER)
  285. {
  286. ASSERT(dwRet == ERROR_SUCCESS);
  287. return FALSE;
  288. }
  289. if ((dwType == REG_SZ) && (dwRet == ERROR_SUCCESS))
  290. {
  291. if (!StrCmp(szEnabled, TEXT("yes")))
  292. return TRUE; // enabled
  293. else
  294. return FALSE; // disabled
  295. }
  296. // value not found...
  297. return TRUE;
  298. }
  299. DWORD MP_GetFilterInfoFromRegistry()
  300. {
  301. const TCHAR c_szSMIEAOMM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
  302. const TCHAR c_szVal[] = TEXT("Image_Filter");
  303. DWORD dwType, dwSize, dwFilter, dwRet;
  304. dwSize = sizeof(dwFilter);
  305. dwRet = SHGetValue(HKEY_CURRENT_USER, c_szSMIEAOMM, c_szVal, &dwType, &dwFilter, &dwSize);
  306. if ((dwRet != ERROR_SUCCESS) || (dwType != REG_DWORD))
  307. {
  308. dwFilter = MP_MIN_SIZE;
  309. }
  310. return dwFilter;
  311. }
  312. DWORD MP_GetOffsetInfoFromRegistry()
  313. {
  314. const TCHAR c_szSMIEAOMM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
  315. const TCHAR c_szVal[] = TEXT("Offset");
  316. DWORD dwType, dwSize, dwOffset, dwRet;
  317. dwSize = sizeof(dwOffset);
  318. dwRet = SHGetValue(HKEY_CURRENT_USER, c_szSMIEAOMM, c_szVal, &dwType, &dwOffset, &dwSize);
  319. if ((dwRet != ERROR_SUCCESS) || (dwType != REG_DWORD))
  320. {
  321. dwOffset = MP_HOVER_OFFSET;
  322. }
  323. return dwOffset;
  324. }
  325. BOOL_PTR CALLBACK DisableMPDialogProc(HWND hDlg, UINT uMsg, WPARAM wparam, LPARAM lparam)
  326. {
  327. BOOL bMsgHandled = FALSE;
  328. switch (uMsg)
  329. {
  330. case WM_INITDIALOG:
  331. {
  332. // center dialog... yay msdn...
  333. RECT rc;
  334. GetWindowRect(hDlg, &rc);
  335. SetWindowPos(hDlg, HWND_TOP,
  336. ((GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2),
  337. ((GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 2),
  338. 0, 0, SWP_NOSIZE);
  339. }
  340. break;
  341. case WM_COMMAND:
  342. switch (LOWORD(wparam))
  343. {
  344. case IDC_MP_ALWAYS:
  345. EndDialog(hDlg, IDC_MP_ALWAYS);
  346. break;
  347. case IDC_MP_THISSESSION:
  348. EndDialog(hDlg, IDC_MP_THISSESSION);
  349. break;
  350. case IDC_MP_CANCEL:
  351. EndDialog(hDlg, IDC_MP_CANCEL);
  352. break;
  353. }
  354. break;
  355. case WM_CLOSE:
  356. EndDialog(hDlg, IDC_MP_CANCEL);
  357. break;
  358. default:
  359. break;
  360. }
  361. return(bMsgHandled);
  362. }
  363. LRESULT CALLBACK CMyPics::s_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  364. {
  365. CMyPics* pThis = (CMyPics*)GetWindowPtr(hWnd, GWLP_USERDATA);
  366. TraceMsg(TF_MYPICS, "+CMyPics::s_WndProc hWnd=%x, pThis=%p", hWnd, pThis);
  367. HRESULT hr = S_OK;
  368. IOleCommandTarget *pOleCommandTarget = NULL;
  369. switch (uMsg)
  370. {
  371. case WM_SIZE:
  372. if (!pThis)
  373. break;
  374. SetWindowPos(pThis->m_hWndMyPicsToolBar, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
  375. break;
  376. case WM_ERASEBKGND:
  377. if (!pThis)
  378. break;
  379. {
  380. RECT rc;
  381. HBRUSH hb = GetSysColorBrush(COLOR_3DFACE);
  382. GetClientRect(pThis->m_hWndMyPicsToolBar, &rc);
  383. FillRect((HDC)wParam, &rc, hb);
  384. return TRUE;
  385. }
  386. case WM_COMMAND:
  387. if (!pThis)
  388. break;
  389. switch(LOWORD(wParam))
  390. {
  391. case IDM_MYPICS_SAVE: //Save As... dialogue
  392. ASSERT(pThis->m_pEleCurr);
  393. // the evil QI call...
  394. hr = pThis->m_pEleCurr->QueryInterface(IID_IOleCommandTarget, (void **)&pOleCommandTarget);
  395. if (FAILED(hr))
  396. return(hr);
  397. // hide the hoverthing so it doesn't cause us any nasty problems
  398. pThis->HideHover();
  399. // launch the Save As dialogue thingie...
  400. pOleCommandTarget->Exec(&CGID_MSHTML, IDM_SAVEPICTURE, 0, 0, NULL);
  401. ATOMICRELEASE(pOleCommandTarget);
  402. break;
  403. case IDM_MYPICS_PRINT:
  404. {
  405. // get the cmd target
  406. hr = pThis->m_pEleCurr->QueryInterface(IID_IOleCommandTarget, (void **)&pOleCommandTarget);
  407. if (FAILED(hr))
  408. return(hr);
  409. pThis->HideHover();
  410. //pThis->m_hoverState = HOVERSTATE_SHOWING; // kludge to keep hover from appearing under print dialogue
  411. pOleCommandTarget->Exec(&CGID_MSHTML, IDM_MP_PRINTPICTURE, 0, 0, NULL);
  412. ATOMICRELEASE(pOleCommandTarget);
  413. //pThis->m_hoverState = HOVERSTATE_HIDING;
  414. }
  415. break;
  416. case IDM_MYPICS_EMAIL:
  417. {
  418. // get the cmd target...
  419. hr = pThis->m_pEleCurr->QueryInterface(IID_IOleCommandTarget, (void **)&pOleCommandTarget);
  420. if (FAILED(hr))
  421. return(hr);
  422. // ... and then hide the hover bar...
  423. pThis->HideHover();
  424. //pThis->m_hoverState = HOVERSTATE_SHOWING; // kludge to keep hover from appearing under print dialogue
  425. // ... and pray this works...
  426. pOleCommandTarget->Exec(&CGID_MSHTML, IDM_MP_EMAILPICTURE, 0, 0, NULL);
  427. ATOMICRELEASE(pOleCommandTarget);
  428. // ... and cleanup
  429. //pThis->m_hoverState = HOVERSTATE_HIDING;
  430. }
  431. break;
  432. case IDM_MYPICS_MYPICS: // Open My Pictures folder
  433. // get the cmd target
  434. hr = pThis->m_pEleCurr->QueryInterface(IID_IOleCommandTarget, (void **)&pOleCommandTarget);
  435. if (FAILED(hr))
  436. return(hr);
  437. pOleCommandTarget->Exec(&CGID_MSHTML, IDM_MP_MYPICS, 0, 0, NULL);
  438. ATOMICRELEASE(pOleCommandTarget);
  439. hr = S_OK;
  440. pThis->HideHover();
  441. break;
  442. default:
  443. break;
  444. }
  445. break;
  446. case WM_NOTIFY: // tooltips...
  447. if (!pThis)
  448. break;
  449. switch (((LPNMHDR)lParam)->code)
  450. {
  451. case TTN_NEEDTEXT:
  452. {
  453. LPTOOLTIPTEXT lpToolTipText;
  454. TCHAR szBuf[MAX_PATH];
  455. lpToolTipText = (LPTOOLTIPTEXT)lParam;
  456. hr = MLLoadString((UINT)lpToolTipText->hdr.idFrom,
  457. szBuf,
  458. ARRAYSIZE(szBuf));
  459. lpToolTipText->lpszText = szBuf;
  460. break;
  461. }
  462. }
  463. break;
  464. case WM_SETTINGCHANGE:
  465. if (!pThis)
  466. break;
  467. {
  468. pThis->DestroyHover(); // to stop wierd window distortion
  469. break;
  470. }
  471. case WM_CONTEXTMENU:
  472. if (!pThis)
  473. break;
  474. {
  475. // load the menu
  476. HMENU hMenu0 = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(IDR_MYPICS_CONTEXT_MENU));
  477. HMENU hMenu1 = GetSubMenu(hMenu0, 0);
  478. if(!hMenu1)
  479. break;
  480. POINT point;
  481. point.x = (LONG)GET_X_LPARAM(lParam);
  482. point.y = (LONG)GET_Y_LPARAM(lParam);
  483. ASSERT(pThis->m_hoverState=HOVERSTATE_SHOWING);
  484. // lock against mouseouts
  485. pThis->m_hoverState = HOVERSTATE_LOCKED;
  486. // display it, get choice (if any)
  487. int iPick = TrackPopupMenu(hMenu1,
  488. TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
  489. point.x,
  490. point.y,
  491. 0,
  492. hWnd,
  493. (RECT *)NULL);
  494. DestroyMenu(hMenu0);
  495. DestroyMenu(hMenu1);
  496. pThis->m_hoverState = HOVERSTATE_SHOWING;
  497. if (iPick)
  498. {
  499. switch(iPick)
  500. {
  501. case IDM_DISABLE_MYPICS:
  502. {
  503. pThis->HideHover();
  504. // create dialog to ask user if they want to turn this stuff off...
  505. // (explicit cast to make Win64 builds happy)
  506. int iResult = (int)DialogBoxParam(MLGetHinst(),
  507. MAKEINTRESOURCE(DLG_DISABLE_MYPICS),
  508. pThis->m_Hwnd,
  509. DisableMPDialogProc,
  510. NULL);
  511. // deal with their choice...
  512. if (iResult)
  513. {
  514. switch (iResult)
  515. {
  516. case IDC_MP_ALWAYS:
  517. {
  518. pThis->m_bIsOffForSession = TRUE;
  519. DWORD dwType = REG_SZ;
  520. DWORD dwSize;
  521. TCHAR szEnabled[16] = TEXT("no");
  522. DWORD dwRet;
  523. const TCHAR c_szSMIEM[] =
  524. TEXT("Software\\Microsoft\\Internet Explorer\\Main");
  525. const TCHAR c_szVal[] = TEXT("Enable_MyPics_Hoverbar");
  526. dwSize = sizeof(szEnabled);
  527. dwRet = SHSetValue(HKEY_CURRENT_USER,
  528. c_szSMIEM,
  529. c_szVal,
  530. dwType,
  531. szEnabled,
  532. dwSize);
  533. }
  534. break;
  535. case IDC_MP_THISSESSION:
  536. // twiddle member var flag
  537. // this is propagated back up to COmWindow via ReleaseMyPics() function.
  538. pThis->m_bIsOffForSession = TRUE;
  539. break;
  540. default:
  541. break;
  542. }
  543. }
  544. }
  545. break;
  546. case IDM_HELP_MYPICS:
  547. pThis->HideHover();
  548. SHHtmlHelpOnDemandWrap(hWnd, TEXT("iexplore.chm > iedefault"), 0, (DWORD_PTR) TEXT("pic_tb_ovr.htm"), ML_CROSSCODEPAGE);
  549. break;
  550. default:
  551. // um, do nothing
  552. break;
  553. }
  554. }
  555. }
  556. break;
  557. default:
  558. return (DefWindowProc(hWnd, uMsg, wParam, lParam));
  559. }
  560. TraceMsg(TF_MYPICS, "-CMyPics::s_WndProc hWnd=%x, pThis=%p", hWnd, pThis);
  561. return (hr);
  562. }
  563. VOID CALLBACK CMyPics::s_TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
  564. {
  565. TraceMsg(TF_MYPICS, "+CMyPics::TimerProc");
  566. CMyPics* pThis = (CMyPics*)GetWindowPtr(hwnd, GWLP_USERDATA);
  567. switch (uMsg)
  568. {
  569. case WM_TIMER:
  570. KillTimer(hwnd, IDT_MP_TIMER);
  571. if (pThis && (pThis->m_hoverState == HOVERSTATE_WAITINGTOSHOW))
  572. {
  573. // Our hover bar is waiting to be shown.
  574. if (pThis->m_pEleCurr)
  575. {
  576. // We still have an element. Show it.
  577. pThis->m_hoverState = HOVERSTATE_SHOWING;
  578. pThis->ShowHover();
  579. }
  580. else
  581. {
  582. // Our timer popped, but we don't have an element.
  583. pThis->HideHover();
  584. }
  585. }
  586. break;
  587. default:
  588. break;
  589. }
  590. TraceMsg(TF_MYPICS, "-CMyPics::TimerProc");
  591. }
  592. BOOL CMyPics::ShouldAppearOnThisElement(IHTMLElement *pEle)
  593. {
  594. BOOL bRet = TRUE; // appear by default
  595. VARIANT varVal = {0};
  596. BSTR bstrAttribute = NULL; // to check img tags for expando
  597. IHTMLRect *pRect = NULL; // to get screen coords
  598. IHTMLElement2 *pEle2 = NULL;
  599. IHTMLElement3 *pEle3 = NULL; // to check for contenteditable mode
  600. VARIANT_BOOL bEdit = FALSE;// becomes true if contenteditable mode is true
  601. LONG lLeft; // these are the screen coords
  602. LONG lRight; // we get right and bottom to det size of image
  603. LONG lTop;
  604. LONG lBottom;
  605. DWORD dwFilter;
  606. IOleCommandTarget *pOleCommandTarget = NULL;
  607. TraceMsg(TF_MYPICS, "+CMyPics::ShouldAppearOnThisElement");
  608. // don't create it if it already exists. thats bad.
  609. if ((HOVERSTATE_SHOWING == m_hoverState) || (HOVERSTATE_LOCKED == m_hoverState))
  610. {
  611. bRet = FALSE;
  612. goto Cleanup;
  613. }
  614. m_bGalleryImg = FALSE;
  615. if (!pEle)
  616. {
  617. bRet = FALSE;
  618. goto Cleanup;
  619. }
  620. // find out if the image didn't load or is unrenderable
  621. if (SUCCEEDED(pEle->QueryInterface(IID_IOleCommandTarget, (void **)&pOleCommandTarget)))
  622. {
  623. OLECMD rgCmd;
  624. rgCmd.cmdID = IDM_SAVEPICTURE; // this is the same check the context menu uses
  625. rgCmd.cmdf = 0;
  626. pOleCommandTarget->QueryStatus(&CGID_MSHTML, 1, &rgCmd, NULL);
  627. if (!(OLECMDF_ENABLED & rgCmd.cmdf))
  628. {
  629. bRet = FALSE;
  630. goto Cleanup;
  631. }
  632. }
  633. // check for explicit enable/disable attribute in img tag...
  634. bstrAttribute=SysAllocString(L"galleryimg");
  635. if (!bstrAttribute)
  636. goto Cleanup;
  637. if (SUCCEEDED(pEle->getAttribute(bstrAttribute, 0, &varVal)))
  638. {
  639. if (varVal.vt == VT_BSTR)
  640. {
  641. if (StrCmpIW(varVal.bstrVal, L"true") == 0
  642. || StrCmpIW(varVal.bstrVal, L"on") == 0
  643. || StrCmpIW(varVal.bstrVal, L"yes") == 0
  644. )
  645. {
  646. // Explicitly turned on. Honor it and leave.
  647. bRet = TRUE;
  648. m_bGalleryImg = TRUE;
  649. goto Cleanup;
  650. }
  651. if (StrCmpIW(varVal.bstrVal, L"false") == 0
  652. || StrCmpIW(varVal.bstrVal, L"off") == 0
  653. || StrCmpIW(varVal.bstrVal, L"no") == 0
  654. )
  655. {
  656. // Explicitly turned off. Honor it and leave.
  657. bRet = FALSE;
  658. goto Cleanup;
  659. }
  660. }
  661. else if (varVal.vt == VT_BOOL)
  662. {
  663. if (varVal.boolVal == VARIANT_TRUE)
  664. {
  665. bRet = TRUE;
  666. m_bGalleryImg = TRUE;
  667. goto Cleanup;
  668. }
  669. else
  670. {
  671. bRet = FALSE;
  672. goto Cleanup;
  673. }
  674. }
  675. }
  676. VariantClear(&varVal);
  677. SysFreeString(bstrAttribute);
  678. // After checking "galleryimg" tag, check to see if turned off by the META tag
  679. if (m_bGalleryMeta == FALSE)
  680. return FALSE;
  681. // check for mappings on the image...
  682. bstrAttribute=SysAllocString(L"usemap");
  683. if (!bstrAttribute)
  684. return (bRet);
  685. if (SUCCEEDED(pEle->getAttribute(bstrAttribute, 0, &varVal)))
  686. {
  687. if (varVal.vt == VT_BSTR)
  688. {
  689. // What do we do here?
  690. bRet = (varVal.bstrVal == NULL);
  691. if (!bRet)
  692. goto Cleanup;
  693. }
  694. }
  695. VariantClear(&varVal);
  696. SysFreeString(bstrAttribute);
  697. // check for mappings on the image...
  698. bstrAttribute=SysAllocString(L"ismap");
  699. if (!bstrAttribute)
  700. return (bRet);
  701. if (SUCCEEDED(pEle->getAttribute(bstrAttribute, 0, &varVal)))
  702. {
  703. // If the attribute exists, then we need to return FALSE *unless* we see a value of FALSE
  704. bRet = FALSE;
  705. if (varVal.vt == VT_BOOL
  706. && varVal.boolVal == VARIANT_FALSE)
  707. {
  708. // "ismap" is false, so we can show the hover bar over this image.
  709. bRet = TRUE;
  710. }
  711. }
  712. if (!bRet)
  713. goto Cleanup;
  714. bRet = FALSE; // If any of the calls below fail, we'll exit with "FALSE".
  715. // Now check to see if we pass the size filter.
  716. // get an IHTMLElement2 from the IHTMLElement passed in...
  717. if (FAILED(pEle->QueryInterface(IID_IHTMLElement2, (void **)&pEle2) ))
  718. goto Cleanup;
  719. // get coords...
  720. if (FAILED(pEle2->getBoundingClientRect(&pRect) ))
  721. goto Cleanup;
  722. if (FAILED(pRect->get_left(&lLeft) ))
  723. goto Cleanup;
  724. if (FAILED(pRect->get_right(&lRight) ))
  725. goto Cleanup;
  726. if (FAILED(pRect->get_top(&lTop) ))
  727. goto Cleanup;
  728. if (FAILED(pRect->get_bottom(&lBottom) ))
  729. goto Cleanup;
  730. dwFilter = MP_GetFilterInfoFromRegistry();
  731. // see if this picture is big enough to qualify as a "Photo"...
  732. // TODO: decide if we like checking aspect ratio or not
  733. if ( (lRight - lLeft >= (LONG)dwFilter && lBottom - lTop >= (LONG)dwFilter)
  734. /*&& !(2*(min(lRight-lLeft,lBottom-lTop)) < max(lRight-lLeft,lBottom-lTop)) */)
  735. bRet = TRUE;
  736. if (FAILED(pEle2->QueryInterface(IID_IHTMLElement3, (void **)&pEle3) ))
  737. goto Cleanup;
  738. if (FAILED(pEle3->get_isContentEditable(&bEdit) ))
  739. goto Cleanup;
  740. if (bEdit)
  741. bRet = FALSE;
  742. Cleanup:
  743. VariantClear(&varVal);
  744. if (bstrAttribute)
  745. SysFreeString(bstrAttribute);
  746. SAFERELEASE(pOleCommandTarget);
  747. SAFERELEASE(pEle3);
  748. SAFERELEASE(pRect);
  749. SAFERELEASE(pEle2);
  750. TraceMsg(TF_MYPICS, "-CMyPics::ShouldAppearOnThisElement");
  751. return bRet;
  752. }
  753. HRESULT CMyPics::CreateHover()
  754. {
  755. HRESULT hr = S_OK;
  756. SIZE size = {0,0};
  757. WORD wImage;
  758. HBITMAP hbmp = NULL;
  759. HBITMAP hbmpHot = NULL;
  760. TraceMsg(TF_MYPICS, "+CMyPics::CreateHover, this=%p, m_hoverState=%d", this, m_hoverState);
  761. InitCommonControls();
  762. WNDCLASS wc = {0};
  763. wc.style = CS_HREDRAW | CS_VREDRAW;
  764. wc.lpszClassName = TEXT("MyPicturesHost");
  765. wc.lpfnWndProc = s_WndProc;
  766. wc.hInstance = g_hinst;
  767. wc.hbrBackground = HBRUSH(COLOR_BTNFACE);
  768. RegisterClass(&wc);
  769. // create the rebar to hold the toolbar...
  770. if (!m_hWndHover)
  771. {
  772. m_hWndHover = CreateWindow(TEXT("MyPicturesHost"), TEXT(""), WS_DLGFRAME | WS_VISIBLE | WS_CHILD,
  773. 0, 0, 0, 0, m_Hwnd, NULL, g_hinst, NULL);
  774. if (!m_hWndHover)
  775. {
  776. TraceMsg(TF_MYPICS | TF_WARNING, "CMyPics::CreateHover, unable to create m_hWndHover");
  777. hr = E_FAIL;
  778. goto Cleanup;
  779. }
  780. ASSERT(GetWindowPtr(m_hWndHover, GWLP_USERDATA) == NULL);
  781. SetWindowPtr(m_hWndHover, GWLP_USERDATA, this);
  782. // set cc version
  783. SendMessage(m_hWndHover, CCM_SETVERSION, COMCTL32_VERSION, 0);
  784. }
  785. // create the toolbar...
  786. if (!m_hWndMyPicsToolBar)
  787. {
  788. m_hWndMyPicsToolBar = CreateWindow(TOOLBARCLASSNAME, TEXT(""), TBSTYLE_TOOLTIPS | CCS_NODIVIDER | TBSTYLE_FLAT | WS_VISIBLE | WS_CHILD,
  789. 0,0,0,0, m_hWndHover, NULL, g_hinst, NULL);
  790. if (!m_hWndMyPicsToolBar)
  791. {
  792. TraceMsg(TF_MYPICS | TF_WARNING, "CMyPics::CreateHover, unable to create m_hWndMyPicsToolBar");
  793. hr = E_FAIL;
  794. goto Cleanup;
  795. }
  796. SetWindowPtr(m_hWndMyPicsToolBar, GWLP_USERDATA, this); // for the timer proc
  797. // set cc version for this too, and the sizeof tbbutton struct...
  798. SendMessage(m_hWndMyPicsToolBar, CCM_SETVERSION, COMCTL32_VERSION, 0);
  799. SendMessage(m_hWndMyPicsToolBar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
  800. }
  801. // create image lists...
  802. wImage = ((IsOS(OS_WHISTLERORGREATER)) ? IDB_MYPICS_TOOLBARGW : IDB_MYPICS_TOOLBARG);
  803. if (!m_himlHover)
  804. {
  805. m_himlHover = ImageList_LoadImage(HINST_THISDLL, MAKEINTRESOURCE(wImage), 16, 0, CLR_DEFAULT, IMAGE_BITMAP, LR_CREATEDIBSECTION);
  806. if (!m_himlHover)
  807. {
  808. TraceMsg(TF_MYPICS | TF_WARNING, "CMyPics::CreateHover, unable to create m_himlHover");
  809. }
  810. }
  811. wImage = ((IsOS(OS_WHISTLERORGREATER)) ? IDB_MYPICS_TOOLBARW : IDB_MYPICS_TOOLBAR);
  812. if (!m_himlHoverHot)
  813. {
  814. m_himlHoverHot = ImageList_LoadImage(HINST_THISDLL, MAKEINTRESOURCE(wImage) , 16, 0, CLR_DEFAULT, IMAGE_BITMAP, LR_CREATEDIBSECTION);
  815. if (!m_himlHoverHot)
  816. {
  817. TraceMsg(TF_MYPICS | TF_WARNING, "CMyPics::CreateHover, unable to create m_himlHoverHot");
  818. }
  819. }
  820. // set image list and hot image list
  821. SendMessage(m_hWndMyPicsToolBar, TB_SETIMAGELIST, 0, (LPARAM)m_himlHover );
  822. SendMessage(m_hWndMyPicsToolBar, TB_SETHOTIMAGELIST, 0, (LPARAM)m_himlHoverHot);
  823. TBBUTTON tbButton;
  824. // set bitmap indexes in tbbutton structure (this may not be necessary)
  825. for (int i=0;i<MP_NUM_TBBITMAPS;i++)
  826. {
  827. tbButton.iBitmap = MAKELONG(i,0);
  828. tbButton.fsState = TBSTATE_ENABLED;
  829. tbButton.fsStyle = TBSTYLE_BUTTON;
  830. tbButton.dwData = 0;
  831. tbButton.iString = 0;
  832. switch(i)
  833. {
  834. case 0: tbButton.idCommand = IDM_MYPICS_SAVE; break;
  835. case 1: tbButton.idCommand = IDM_MYPICS_PRINT; break;
  836. case 2: tbButton.idCommand = IDM_MYPICS_EMAIL; break;
  837. case 3: tbButton.idCommand = IDM_MYPICS_MYPICS; break;
  838. }
  839. SendMessage(m_hWndMyPicsToolBar, TB_INSERTBUTTON, i, (LPARAM)&tbButton);
  840. }
  841. Cleanup:
  842. TraceMsg(TF_MYPICS, "-CMyPics::CreateHover, this=%p, m_hoverState=%d", this, m_hoverState);
  843. return hr;
  844. }
  845. HRESULT CMyPics::DestroyHover()
  846. {
  847. HRESULT hr = S_OK;
  848. TraceMsg(TF_MYPICS, "+CMyPics::DestroyHover, this=%p, m_hoverState=%d", this, m_hoverState);
  849. // If we have a MyPicsToolBar...
  850. if (m_hWndMyPicsToolBar)
  851. {
  852. // first destroy the toolbar
  853. if (!DestroyWindow(m_hWndMyPicsToolBar))
  854. {
  855. TraceMsg(TF_MYPICS, "In CMyPics::DestroyHover, DestroyWindow(m_hWndMyPicsToolBar) failed");
  856. hr = E_FAIL;
  857. }
  858. m_hWndMyPicsToolBar=NULL;
  859. }
  860. // If we have a hover window...
  861. if (m_hWndHover)
  862. {
  863. if (m_wndprocOld)
  864. {
  865. // Unsubclass the window
  866. SetWindowLongPtr(m_hWndHover, GWLP_WNDPROC, (LONG_PTR)m_wndprocOld);
  867. m_wndprocOld = NULL;
  868. }
  869. // Clear the window word
  870. SetWindowPtr(m_hWndHover, GWLP_USERDATA, NULL);
  871. // then destroy the rebar
  872. if (!DestroyWindow(m_hWndHover))
  873. {
  874. hr = E_FAIL;
  875. goto Cleanup;
  876. }
  877. m_hWndHover = NULL;
  878. }
  879. // and destroy the image lists...
  880. if (m_himlHover)
  881. {
  882. ImageList_Destroy(m_himlHover);
  883. m_himlHover = NULL;
  884. }
  885. if (m_himlHoverHot)
  886. {
  887. ImageList_Destroy(m_himlHoverHot);
  888. m_himlHoverHot = NULL;
  889. }
  890. Cleanup:
  891. TraceMsg(TF_MYPICS, "-CMyPics::DestroyHover, this=%p, hr=%x", this, hr);
  892. return hr;
  893. }
  894. HRESULT CMyPics::HideHover()
  895. {
  896. HRESULT hr = S_OK;
  897. TraceMsg(TF_MYPICS, "+CMyPics::HideHover, this=%p, m_hoverState=%d", this, m_hoverState);
  898. if (m_hWndHover)
  899. {
  900. ShowWindow(m_hWndHover, SW_HIDE);
  901. m_hoverState = HOVERSTATE_HIDING;
  902. }
  903. else
  904. hr = E_FAIL;
  905. TraceMsg(TF_MYPICS, "-CMyPics::HideHover, this=%p, m_hoverState=%d", this, m_hoverState);
  906. return hr;
  907. }
  908. IHTMLElement *CMyPics::GetIMGFromArea(IHTMLElement *pEleIn, POINT ptEvent)
  909. {
  910. // someone got an IHTMLElement and decided it was an area tag
  911. // so find the img tag associated and return it as an IHTMLElement
  912. BSTR bstrName = NULL;
  913. BSTR bstrUseMap = NULL;
  914. IHTMLElement *pEleParent = NULL;
  915. IHTMLElement *pEleMisc = NULL;
  916. IHTMLElement2 *pEle2Misc = NULL;
  917. IHTMLElement *pEleMiscPar = NULL;
  918. IHTMLMapElement *pEleMap = NULL;
  919. IHTMLImgElement *pEleImg = NULL;
  920. IHTMLElement *pEleOut = NULL;
  921. IHTMLElementCollection *pCollect = NULL;
  922. IHTMLElementCollection *pSubCollect = NULL;
  923. IDispatch *pDisp = NULL;
  924. VARIANT TagName;
  925. ULONG ulCount = 0;
  926. VARIANTARG va1;
  927. VARIANTARG va2;
  928. HRESULT hr;
  929. POINT ptMouse,
  930. ptScr;
  931. LONG xInIMG = 0,
  932. yInIMG = 0,
  933. lOffset = 0,
  934. lOffsetLeft = 0,
  935. lOffsetTop = 0,
  936. lScrollLeft = 0,
  937. lScrollTop = 0,
  938. lOffsetW = 0,
  939. lOffsetH = 0;
  940. TagName.vt = VT_BSTR;
  941. TagName.bstrVal = (BSTR)c_bstr_IMG;
  942. // first get the map element
  943. if (SUCCEEDED(pEleIn->get_offsetParent(&pEleParent)))
  944. {
  945. // get the map element
  946. hr=pEleParent->QueryInterface(IID_IHTMLMapElement, (void **)&pEleMap);
  947. if (FAILED(hr))
  948. goto Cleanup;
  949. // next get the name of the map
  950. if (SUCCEEDED(pEleMap->get_name(&bstrName)))
  951. {
  952. //next get all tags
  953. hr = m_pDoc2->get_all(&pCollect);
  954. if (FAILED(hr))
  955. goto Cleanup;
  956. //get all IMG tags
  957. hr = pCollect->tags(TagName, &pDisp);
  958. if (FAILED(hr))
  959. goto Cleanup;
  960. if (pDisp)
  961. {
  962. hr = pDisp->QueryInterface(IID_IHTMLElementCollection,(void **)&pSubCollect);
  963. ATOMICRELEASE(pDisp);
  964. }
  965. if (FAILED(hr))
  966. goto Cleanup;
  967. //get IMG tag count
  968. hr = pSubCollect->get_length((LONG *)&ulCount);
  969. if (FAILED(hr))
  970. goto Cleanup;
  971. va1.vt = VT_I4;
  972. va2.vt = VT_EMPTY;
  973. ASSERT(pDisp==NULL);
  974. //iterate through tags looking for images that have the right usemap set
  975. for (int i=0; i<(LONG)ulCount; i++)
  976. {
  977. ATOMICRELEASE(pEleImg);
  978. ATOMICRELEASE(pDisp);
  979. pDisp = NULL;
  980. bstrUseMap = NULL;
  981. xInIMG = 0;
  982. yInIMG = 0;
  983. lOffset = 0;
  984. lOffsetLeft = 0;
  985. lOffsetTop = 0;
  986. lScrollLeft = 0;
  987. lScrollTop = 0;
  988. lOffsetW = 0;
  989. lOffsetH = 0;
  990. va1.lVal = (LONG)i;
  991. pSubCollect->item(va1, va2, &pDisp);
  992. if (pDisp)
  993. {
  994. hr = pDisp->QueryInterface(IID_IHTMLImgElement, (void **)&pEleImg);
  995. if (FAILED(hr))
  996. goto Cleanup;
  997. hr = pEleImg->get_useMap(&bstrUseMap);
  998. if (FAILED(hr))
  999. goto Cleanup;
  1000. // this will be non-null if set for this IMG element...
  1001. if (bstrUseMap){
  1002. // get rid of the prepended '#'...
  1003. bstrUseMap++;
  1004. // see if this is what we're looking for...
  1005. if (StrCmp(bstrUseMap, bstrName) == 0)
  1006. {
  1007. m_pWin3->get_screenLeft(&ptScr.x);
  1008. m_pWin3->get_screenTop (&ptScr.y);
  1009. //Ok, we found a candidate. See if the mouse is here...
  1010. ptMouse.x = ptEvent.x - ptScr.x;
  1011. ptMouse.y = ptEvent.y - ptScr.y;
  1012. hr = pDisp->QueryInterface(IID_IHTMLElement, (void **)&pEleMisc);
  1013. if (FAILED(hr))
  1014. goto Cleanup;
  1015. while (pEleMisc)
  1016. {
  1017. hr = pEleMisc->QueryInterface(IID_IHTMLElement2, (void **)&pEle2Misc);
  1018. if (FAILED(hr))
  1019. goto Cleanup;
  1020. pEleMisc->get_offsetLeft(&lOffsetLeft);
  1021. pEle2Misc->get_scrollLeft(&lScrollLeft);
  1022. lOffset += lOffsetLeft - lScrollLeft;
  1023. pEleMisc->get_offsetParent(&pEleMiscPar);
  1024. ATOMICRELEASE(pEleMisc);
  1025. ATOMICRELEASE(pEle2Misc);
  1026. pEleMisc=pEleMiscPar;
  1027. }
  1028. ATOMICRELEASE(pEleMiscPar);
  1029. hr = pDisp->QueryInterface(IID_IHTMLElement, (void **)&pEleMisc);
  1030. if (FAILED(hr))
  1031. goto Cleanup;
  1032. xInIMG = ptMouse.x - lOffset;
  1033. pEleMisc->get_offsetWidth(&lOffsetW);
  1034. if ((xInIMG < 0) || (xInIMG > lOffsetW))
  1035. continue;
  1036. lOffset = 0;
  1037. while (pEleMisc)
  1038. {
  1039. hr = pEleMisc->QueryInterface(IID_IHTMLElement2, (void **)&pEle2Misc);
  1040. if (FAILED(hr))
  1041. goto Cleanup;
  1042. pEleMisc->get_offsetTop(&lOffsetTop);
  1043. pEle2Misc->get_scrollTop(&lScrollTop);
  1044. lOffset += lOffsetTop - lScrollTop;
  1045. pEleMisc->get_offsetParent(&pEleMiscPar);
  1046. ATOMICRELEASE(pEleMisc);
  1047. ATOMICRELEASE(pEle2Misc);
  1048. pEleMisc=pEleMiscPar;
  1049. }
  1050. ATOMICRELEASE(pEleMiscPar);
  1051. hr = pDisp->QueryInterface(IID_IHTMLElement, (void **)&pEleMisc);
  1052. if (FAILED(hr))
  1053. goto Cleanup;
  1054. yInIMG = ptMouse.y - lOffset;
  1055. pEleMisc->get_offsetHeight(&lOffsetH);
  1056. ATOMICRELEASE(pEleMisc);
  1057. if ((yInIMG < 0) || (yInIMG > lOffsetH))
  1058. continue;
  1059. // if we get to this point we found our IMG element so...
  1060. // ...do the QI...
  1061. pEleImg->QueryInterface(IID_IHTMLElement, (void **)&pEleOut);
  1062. // ...and we're done.
  1063. break;
  1064. }
  1065. }
  1066. }
  1067. }
  1068. }
  1069. }
  1070. Cleanup:
  1071. ATOMICRELEASE(pCollect);
  1072. ATOMICRELEASE(pSubCollect);
  1073. ATOMICRELEASE(pEleMap);
  1074. ATOMICRELEASE(pEleParent);
  1075. ATOMICRELEASE(pDisp);
  1076. ATOMICRELEASE(pEleImg);
  1077. ATOMICRELEASE(pEleMisc);
  1078. ATOMICRELEASE(pEle2Misc);
  1079. ATOMICRELEASE(pEleMiscPar);
  1080. return (pEleOut);
  1081. }
  1082. // sometimes coordinates are relative to a parent object, like in frames, etc. so this gets their real position relative
  1083. // to the browser window...
  1084. HRESULT CMyPics::GetRealCoords(IHTMLElement2 *pEle2, HWND hwnd, LONG *plLeft, LONG *plTop, LONG *plRight, LONG *plBottom)
  1085. {
  1086. LONG lScreenLeft = 0,
  1087. lScreenTop = 0;
  1088. HRESULT hr = E_FAIL;
  1089. IHTMLRect *pRect = NULL;
  1090. *plLeft = *plTop = *plRight = *plBottom = 0;
  1091. if (!pEle2)
  1092. return hr;
  1093. if (SUCCEEDED(pEle2->getBoundingClientRect(&pRect)) && pRect)
  1094. {
  1095. LONG lLeft, lRight, lTop, lBottom;
  1096. pRect->get_left(&lLeft);
  1097. pRect->get_right(&lRight);
  1098. pRect->get_top(&lTop);
  1099. pRect->get_bottom(&lBottom);
  1100. // if its an iframe and it scrolls past the top of the frame, we should correct a bit.
  1101. if (lTop <= 0)
  1102. lTop = 0;
  1103. // dito for left side
  1104. if (lLeft <= 0)
  1105. lLeft = 0;
  1106. POINT pointTL, pointBR; // TL=Top,Left BR=Bottom,Right
  1107. ASSERT(m_pWin3);
  1108. m_pWin3->get_screenLeft(&lScreenLeft);
  1109. m_pWin3->get_screenTop(&lScreenTop);
  1110. // convert coords relative to the frame window to screen coords
  1111. pointTL.x = lScreenLeft + lLeft;
  1112. pointTL.y = lScreenTop + lTop;
  1113. pointBR.x = lScreenLeft + lRight;
  1114. pointBR.y = lScreenTop + lBottom;
  1115. // now convert from screen coords to client coords and assign...
  1116. if (ScreenToClient(hwnd, &pointTL) && ScreenToClient(hwnd, &pointBR))
  1117. {
  1118. *plLeft = pointTL.x;
  1119. *plRight = pointBR.x;
  1120. *plTop = pointTL.y;
  1121. *plBottom = pointBR.y;
  1122. hr = S_OK;
  1123. }
  1124. pRect->Release();
  1125. }
  1126. return hr;
  1127. }
  1128. HRESULT CMyPics::ShowHover()
  1129. {
  1130. HRESULT hr = S_OK;
  1131. IHTMLElement2 *pEle2 = NULL; // cause we need an ele2 to get screen coords
  1132. IHTMLRect *pRect = NULL; // to get screen coords
  1133. LONG lLeft; // these are the screen coords
  1134. LONG lRight; // we get right and bottom to det size of image
  1135. LONG lTop;
  1136. LONG lBottom;
  1137. DWORD dwOffset;
  1138. DWORD dw;
  1139. SIZE sz;
  1140. RECT rc;
  1141. TraceMsg(TF_MYPICS, "+CMyPics::ShowHover, this=%p, m_hoverState=%d", this, m_hoverState);
  1142. ASSERT(m_pEleCurr);
  1143. ASSERT(m_Hwnd);
  1144. // get an IHTMLElement2 from the IHTMLElement cached...
  1145. hr = m_pEleCurr->QueryInterface(IID_IHTMLElement2, (void **)&pEle2);
  1146. if (FAILED(hr))
  1147. goto Cleanup;
  1148. // get correct coords...
  1149. hr = GetRealCoords(pEle2, m_Hwnd, &lLeft, &lTop, &lRight, &lBottom);
  1150. if (FAILED(hr))
  1151. goto Cleanup;
  1152. // adjust for offset...
  1153. dwOffset = MP_GetOffsetInfoFromRegistry();
  1154. lLeft += dwOffset;
  1155. lTop += dwOffset;
  1156. // need to do some sanity checks to make sure the hover bar appears in a visible location...
  1157. RECT rcBrowserWnd;
  1158. if (GetClientRect(m_Hwnd, &rcBrowserWnd))
  1159. {
  1160. // check to make sure it'll appear somewhere we'll see it...
  1161. if (lLeft < rcBrowserWnd.left)
  1162. lLeft = rcBrowserWnd.left + dwOffset;
  1163. if (lTop < rcBrowserWnd.top)
  1164. lTop = rcBrowserWnd.top + dwOffset;
  1165. // check to make sure the entire hoverbar is over the image (so the user
  1166. // doesn't mouseout trying to get to the buttons!)
  1167. // If "galleryimg" was explicitly turned on, then bypass this code, which ensures that the entire
  1168. // toolbar will fit within the image.
  1169. if (!m_bGalleryImg)
  1170. {
  1171. if (lRight - lLeft < MP_MIN_CX + 10 - (LONG)dwOffset)
  1172. goto Cleanup;
  1173. if (lBottom - lTop < MP_MIN_CY + 10)
  1174. goto Cleanup;
  1175. // now check to make sure there is enough horiz and vert room for it to appear...
  1176. // if there isn't enough room, we just don't display it...
  1177. if ((rcBrowserWnd.right - MP_SCROLLBAR_SIZE) - lLeft < MP_MIN_CX)
  1178. goto Cleanup;
  1179. if ((rcBrowserWnd.bottom - (MP_SCROLLBAR_SIZE+2)) - lTop < MP_MIN_CY)
  1180. goto Cleanup;
  1181. }
  1182. }
  1183. dw = (DWORD)SendMessage(m_hWndMyPicsToolBar, TB_GETBUTTONSIZE, 0, 0);
  1184. sz.cx = LOWORD(dw); sz.cy = HIWORD(dw);
  1185. rc.left = rc.top = 0;
  1186. SendMessage(m_hWndMyPicsToolBar, TB_GETIDEALSIZE, FALSE, (LPARAM)&sz);
  1187. rc.right = sz.cx;
  1188. rc.bottom = sz.cy;
  1189. AdjustWindowRectEx(&rc, GetWindowLong(m_hWndHover, GWL_STYLE), FALSE, GetWindowLong(m_hWndHover, GWL_EXSTYLE));
  1190. if (SetWindowPos(m_hWndHover, NULL, lLeft, lTop, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER | SWP_SHOWWINDOW))
  1191. {
  1192. m_hoverState = HOVERSTATE_SHOWING;
  1193. }
  1194. Cleanup:
  1195. ATOMICRELEASE(pRect);
  1196. ATOMICRELEASE(pEle2);
  1197. TraceMsg(TF_MYPICS, "-CMyPics::ShowHover, this=%p, m_hoverState=%d", this, m_hoverState);
  1198. return hr;
  1199. }
  1200. HRESULT CMyPics::HandleScroll()
  1201. {
  1202. TraceMsg(TF_MYPICS, "+CMyPics::HandleScroll, this=%p, m_hoverState=%d", this, m_hoverState);
  1203. HRESULT hr = S_OK;
  1204. switch(m_hoverState)
  1205. {
  1206. // I don't think we need to do anything in these cases.
  1207. //
  1208. case HOVERSTATE_HIDING:
  1209. case HOVERSTATE_LOCKED:
  1210. case HOVERSTATE_WAITINGTOSHOW:
  1211. break;
  1212. case HOVERSTATE_SHOWING:
  1213. {
  1214. IHTMLElement2 *pEle2=NULL;
  1215. IHTMLRect *pRect=NULL;
  1216. RECT rect;
  1217. ASSERT(m_pEleCurr);
  1218. ASSERT(m_Hwnd);
  1219. ASSERT(m_hWndHover); // Ensure we do have a window
  1220. HideHover();
  1221. ShowHover();
  1222. // Redraw client area to get rid of window droppings scrolling causes.
  1223. // Try to redraw just the part where its likely to need it.
  1224. if (FAILED(m_pEleCurr->QueryInterface(IID_IHTMLElement2, (void **)&pEle2)))
  1225. {
  1226. goto CleanUp;
  1227. }
  1228. if (FAILED(pEle2->getBoundingClientRect(&pRect)))
  1229. {
  1230. goto CleanUp;
  1231. }
  1232. pRect->get_left(&rect.left);
  1233. pRect->get_right(&rect.right);
  1234. pRect->get_top(&rect.top);
  1235. pRect->get_bottom(&rect.bottom);
  1236. rect.top -= 2*MP_MIN_CY;
  1237. if (rect.top < 0)
  1238. rect.top = 0;
  1239. rect.left -= 2*MP_MIN_CX;
  1240. if (rect.left <0)
  1241. rect.left = 0;
  1242. rect.bottom *= 2; rect.right *= 2;
  1243. RedrawWindow(m_Hwnd, &rect, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
  1244. CleanUp:
  1245. SAFERELEASE(pRect);
  1246. SAFERELEASE(pEle2);
  1247. }
  1248. break;
  1249. }
  1250. TraceMsg(TF_MYPICS, "-CMyPics::HandleScroll, this=%p, m_hoverState=%d", this, m_hoverState);
  1251. return hr;
  1252. }
  1253. HRESULT CMyPics::HandleMouseover(IHTMLElement *pEle)
  1254. {
  1255. HRESULT hr = S_OK;
  1256. IOleWindow *pOleWindow;
  1257. TraceMsg(TF_MYPICS, "+CMyPics::HandleMouseover");
  1258. if (m_hoverState != HOVERSTATE_HIDING)
  1259. {
  1260. // Ensure we really have a hover window
  1261. ASSERT(m_hWndHover);
  1262. return (S_OK);
  1263. }
  1264. else
  1265. {
  1266. // No bar. Release current element, if any.
  1267. ATOMICRELEASE(m_pEleCurr);
  1268. if (ShouldAppearOnThisElement(pEle))
  1269. {
  1270. m_pEleCurr = pEle;
  1271. pEle->AddRef();
  1272. // set m_Hwnd once...
  1273. if (!m_Hwnd)
  1274. {
  1275. // Get the Hwnd for the document...
  1276. hr = m_pDoc2->QueryInterface(IID_IOleWindow,(void **)&pOleWindow);
  1277. if (FAILED(hr))
  1278. return hr;
  1279. pOleWindow->GetWindow(&m_Hwnd);
  1280. pOleWindow->Release();
  1281. }
  1282. if (!m_hWndHover)
  1283. {
  1284. // We need a hover window now to conveniently set a timer.
  1285. hr = CreateHover(); // review: do we need to pass member variables as params?
  1286. }
  1287. // We're all set up. Set the state and start the timer.
  1288. m_hoverState=HOVERSTATE_WAITINGTOSHOW;
  1289. SetTimer(m_hWndMyPicsToolBar, IDT_MP_TIMER, MP_TIMER, s_TimerProc);
  1290. }
  1291. }
  1292. TraceMsg(TF_MYPICS, "-CMyPics::HandleMouseover");
  1293. return hr;
  1294. }
  1295. HRESULT CMyPics::HandleMouseout()
  1296. {
  1297. TraceMsg(TF_MYPICS, "+CMyPics::HandleMouseout");
  1298. switch(m_hoverState)
  1299. {
  1300. case HOVERSTATE_HIDING:
  1301. // Nothing to do
  1302. break;
  1303. case HOVERSTATE_SHOWING:
  1304. // Hide it
  1305. HideHover();
  1306. break;
  1307. case HOVERSTATE_LOCKED:
  1308. // Noop
  1309. break;
  1310. case HOVERSTATE_WAITINGTOSHOW:
  1311. m_hoverState = HOVERSTATE_HIDING;
  1312. KillTimer(m_hWndMyPicsToolBar, IDT_MP_TIMER);
  1313. break;
  1314. }
  1315. TraceMsg(TF_MYPICS, "-CMyPics::HandleMouseout");
  1316. return S_OK;
  1317. }
  1318. HRESULT CMyPics::HandleResize()
  1319. {
  1320. HRESULT hr = S_OK;
  1321. if (m_pEleCurr && (HOVERSTATE_SHOWING == m_hoverState))
  1322. {
  1323. HideHover();
  1324. ShowHover();
  1325. }
  1326. return hr;
  1327. }
  1328. HRESULT CMyPics::HandleEvent(IHTMLElement *pEle, EVENTS Event, IHTMLEventObj *pEventObj)
  1329. {
  1330. TraceMsg(TF_MYPICS, "CMyPics::HandleEvent Event=%ws", EventsToSink[Event].pwszEventName);
  1331. HRESULT hr = S_OK;
  1332. BSTR bstrTagName = NULL;
  1333. IHTMLElement *pEleUse = NULL;
  1334. BOOL fWasArea = FALSE;
  1335. // if this is an area tag we need to find the IMG tag that corresponds
  1336. if (pEle && SUCCEEDED(pEle->get_tagName(&bstrTagName)))
  1337. {
  1338. // if its an area tag, we need to find the img tag associated with it...
  1339. if (StrCmpNI(bstrTagName, TEXT("area"), 4)==0)
  1340. {
  1341. POINT ptEvent;
  1342. if (FAILED(pEventObj->get_screenX(&ptEvent.x)) ||
  1343. FAILED(pEventObj->get_screenY(&ptEvent.y)))
  1344. {
  1345. hr = E_FAIL;
  1346. goto Cleanup;
  1347. }
  1348. fWasArea = TRUE;
  1349. pEleUse = GetIMGFromArea(pEle, ptEvent);
  1350. }
  1351. }
  1352. // has the user turned this off?
  1353. if (m_bIsOffForSession)
  1354. goto Cleanup;
  1355. switch(Event)
  1356. {
  1357. case EVENT_SCROLL:
  1358. HandleScroll();
  1359. break;
  1360. case EVENT_MOUSEOVER:
  1361. hr = HandleMouseover(fWasArea ? pEleUse : pEle);
  1362. break;
  1363. case EVENT_MOUSEOUT:
  1364. hr = HandleMouseout();
  1365. break;
  1366. case EVENT_RESIZE:
  1367. hr = HandleResize();
  1368. break;
  1369. default:
  1370. //do nothing?
  1371. break;
  1372. }
  1373. Cleanup:
  1374. if (pEleUse)
  1375. ATOMICRELEASE(pEleUse);
  1376. if (bstrTagName)
  1377. SysFreeString(bstrTagName);
  1378. return (hr);
  1379. }
  1380. ////////////////////////////////////////////////////////////////////////////////////////////////
  1381. ////////////////////////////////////////////////////////////////////////////////////////////////
  1382. // this is stolen from iforms.cpp:
  1383. //=========================================================================
  1384. //
  1385. // Event sinking class
  1386. //
  1387. // We simply implement IDispatch and make a call into our parent when
  1388. // we receive a sinked event.
  1389. //
  1390. //=========================================================================
  1391. CMyPics::CEventSink::CEventSink(CMyPicsEventSinkCallback *pParent)
  1392. {
  1393. TraceMsg(TF_MYPICS, "CMyPics::CEventSink::CEventSink");
  1394. DllAddRef();
  1395. m_cRef = 1;
  1396. m_pParent = pParent;
  1397. }
  1398. CMyPics::CEventSink::~CEventSink()
  1399. {
  1400. TraceMsg(TF_MYPICS, "CMyPics::CEventSink::~CEventSink");
  1401. ASSERT( m_cRef == 0 );
  1402. DllRelease();
  1403. }
  1404. STDMETHODIMP CMyPics::CEventSink::QueryInterface(REFIID riid, void **ppv)
  1405. {
  1406. *ppv = NULL;
  1407. if ((IID_IDispatch == riid) ||
  1408. (IID_IUnknown == riid))
  1409. {
  1410. *ppv = (IDispatch *)this;
  1411. }
  1412. if (NULL != *ppv)
  1413. {
  1414. ((IUnknown *)*ppv)->AddRef();
  1415. return S_OK;
  1416. }
  1417. return E_NOINTERFACE;
  1418. }
  1419. STDMETHODIMP_(ULONG) CMyPics::CEventSink::AddRef(void)
  1420. {
  1421. return ++m_cRef;
  1422. }
  1423. STDMETHODIMP_(ULONG) CMyPics::CEventSink::Release(void)
  1424. {
  1425. if (--m_cRef == 0)
  1426. {
  1427. delete this;
  1428. return 0;
  1429. }
  1430. return m_cRef;
  1431. }
  1432. HRESULT CMyPics::CEventSink::SinkEvents(IHTMLElement2 *pEle2, int iNum, EVENTS *pEvents)
  1433. {
  1434. VARIANT_BOOL bSuccess = VARIANT_TRUE;
  1435. for (int i=0; i<iNum; i++)
  1436. {
  1437. BSTR bstrEvent = SysAllocString(CMyPicsEventSinkCallback::EventsToSink[(int)(pEvents[i])].pwszEventSubscribe);
  1438. if (bstrEvent)
  1439. {
  1440. pEle2->attachEvent(bstrEvent, (IDispatch *)this, &bSuccess);
  1441. SysFreeString(bstrEvent);
  1442. }
  1443. else
  1444. {
  1445. bSuccess = VARIANT_FALSE;
  1446. }
  1447. if (!bSuccess)
  1448. break;
  1449. }
  1450. return (bSuccess) ? S_OK : E_FAIL;
  1451. }
  1452. HRESULT CMyPics::CEventSink::SinkEvents(IHTMLWindow3 *pWin3, int iNum, EVENTS *pEvents)
  1453. {
  1454. VARIANT_BOOL bSuccess = VARIANT_TRUE;
  1455. for (int i=0; i<iNum; i++)
  1456. {
  1457. BSTR bstrEvent = SysAllocString(CMyPicsEventSinkCallback::EventsToSink[(int)(pEvents[i])].pwszEventSubscribe);
  1458. if (bstrEvent)
  1459. {
  1460. pWin3->attachEvent(bstrEvent, (IDispatch *)this, &bSuccess);
  1461. SysFreeString(bstrEvent);
  1462. }
  1463. else
  1464. {
  1465. bSuccess = VARIANT_FALSE;
  1466. }
  1467. if (!bSuccess)
  1468. break;
  1469. }
  1470. return (bSuccess) ? S_OK : E_FAIL;
  1471. }
  1472. HRESULT CMyPics::CEventSink::UnSinkEvents(IHTMLElement2 *pEle2, int iNum, EVENTS *pEvents)
  1473. {
  1474. for (int i=0; i<iNum; i++)
  1475. {
  1476. BSTR bstrEvent = SysAllocString(CMyPicsEventSinkCallback::EventsToSink[(int)(pEvents[i])].pwszEventSubscribe);
  1477. if (bstrEvent)
  1478. {
  1479. pEle2->detachEvent(bstrEvent, (IDispatch *)this);
  1480. SysFreeString(bstrEvent);
  1481. }
  1482. }
  1483. return S_OK;
  1484. }
  1485. HRESULT CMyPics::CEventSink::UnSinkEvents(IHTMLWindow3 *pWin3, int iNum, EVENTS *pEvents)
  1486. {
  1487. for (int i=0; i<iNum; i++)
  1488. {
  1489. BSTR bstrEvent = SysAllocString(CMyPicsEventSinkCallback::EventsToSink[(int)(pEvents[i])].pwszEventSubscribe);
  1490. if (bstrEvent)
  1491. {
  1492. pWin3->detachEvent(bstrEvent, (IDispatch *)this);
  1493. SysFreeString(bstrEvent);
  1494. }
  1495. }
  1496. return S_OK;
  1497. }
  1498. // IDispatch
  1499. STDMETHODIMP CMyPics::CEventSink::GetTypeInfoCount(UINT* /*pctinfo*/)
  1500. {
  1501. return E_NOTIMPL;
  1502. }
  1503. STDMETHODIMP CMyPics::CEventSink::GetTypeInfo(/* [in] */ UINT /*iTInfo*/,
  1504. /* [in] */ LCID /*lcid*/,
  1505. /* [out] */ ITypeInfo** /*ppTInfo*/)
  1506. {
  1507. return E_NOTIMPL;
  1508. }
  1509. STDMETHODIMP CMyPics::CEventSink::GetIDsOfNames(
  1510. REFIID riid,
  1511. OLECHAR** rgszNames,
  1512. UINT cNames,
  1513. LCID lcid,
  1514. DISPID* rgDispId)
  1515. {
  1516. return E_NOTIMPL;
  1517. }
  1518. STDMETHODIMP CMyPics::CEventSink::Invoke(
  1519. DISPID dispIdMember,
  1520. REFIID, LCID,
  1521. WORD wFlags,
  1522. DISPPARAMS* pDispParams,
  1523. VARIANT* pVarResult,
  1524. EXCEPINFO*,
  1525. UINT* puArgErr)
  1526. {
  1527. if (m_pParent && pDispParams && pDispParams->cArgs>=1)
  1528. {
  1529. if (pDispParams->rgvarg[0].vt == VT_DISPATCH)
  1530. {
  1531. IHTMLEventObj *pObj=NULL;
  1532. if (SUCCEEDED(pDispParams->rgvarg[0].pdispVal->QueryInterface(IID_IHTMLEventObj, (void **)&pObj) && pObj))
  1533. {
  1534. EVENTS Event=EVENT_BOGUS;
  1535. BSTR bstrEvent=NULL;
  1536. pObj->get_type(&bstrEvent);
  1537. if (bstrEvent)
  1538. {
  1539. for (int i=0; i<ARRAYSIZE(CMyPicsEventSinkCallback::EventsToSink); i++)
  1540. {
  1541. if (!StrCmpCW(bstrEvent, CMyPicsEventSinkCallback::EventsToSink[i].pwszEventName))
  1542. {
  1543. Event = (EVENTS) i;
  1544. break;
  1545. }
  1546. }
  1547. SysFreeString(bstrEvent);
  1548. }
  1549. if (Event != EVENT_BOGUS)
  1550. {
  1551. IHTMLElement *pEle=NULL;
  1552. pObj->get_srcElement(&pEle);
  1553. // EVENT_SCROLL comes from our window so we won't have an
  1554. // element for it
  1555. if (pEle || (Event == EVENT_SCROLL))
  1556. {
  1557. // Call the event handler here
  1558. m_pParent->HandleEvent(pEle, Event, pObj);
  1559. if (pEle)
  1560. {
  1561. pEle->Release();
  1562. }
  1563. }
  1564. }
  1565. pObj->Release();
  1566. }
  1567. }
  1568. }
  1569. return S_OK;
  1570. }
  1571. //////////////////////////////////////////////////////////////////////////////
  1572. // {9E56BE60-C50F-11CF-9A2C-00A0C90A90CE}
  1573. EXTERN_C const GUID MP_CLSID_MailRecipient = {0x9E56BE60L, 0xC50F, 0x11CF, 0x9A, 0x2C, 0x00, 0xA0, 0xC9, 0x0A, 0x90, 0xCE};
  1574. HRESULT DropPicOnMailRecipient(IDataObject *pdtobj, DWORD grfKeyState)
  1575. {
  1576. IDropTarget *pdrop;
  1577. HRESULT hres = CoCreateInstance(MP_CLSID_MailRecipient,
  1578. NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  1579. IID_PPV_ARG(IDropTarget, &pdrop));
  1580. if (SUCCEEDED(hres))
  1581. {
  1582. hres = SHSimulateDrop(pdrop, pdtobj, grfKeyState, NULL, NULL);
  1583. pdrop->Release();
  1584. }
  1585. return hres;
  1586. }
  1587. //
  1588. // This function cannot return Non -NULL pointers if
  1589. // it returns a FAILED(hr)
  1590. //
  1591. HRESULT CreateShortcutSetSiteAndGetDataObjectIfPIDLIsNetUrl(
  1592. LPCITEMIDLIST pidl,
  1593. IUnknown *pUnkSite,
  1594. IUniformResourceLocator **ppUrlOut,
  1595. IDataObject **ppdtobj
  1596. )
  1597. {
  1598. HRESULT hr;
  1599. TCHAR szUrl[MAX_URL_STRING];
  1600. TCHAR *szTemp = NULL;
  1601. ASSERT(ppUrlOut);
  1602. ASSERT(ppdtobj);
  1603. *ppUrlOut = NULL;
  1604. *ppdtobj = NULL;
  1605. szUrl[0] = TEXT('\0');
  1606. hr = IEGetNameAndFlags(pidl, SHGDN_FORPARSING, szUrl, SIZECHARS(szUrl), NULL);
  1607. if ((S_OK == hr) && (*szUrl))
  1608. {
  1609. BOOL fIsHTML = FALSE;
  1610. BOOL fHitsNet = UrlHitsNetW(szUrl);
  1611. if (!fHitsNet)
  1612. {
  1613. if (URL_SCHEME_FILE == GetUrlScheme(szUrl))
  1614. {
  1615. TCHAR *szExt = PathFindExtension(szUrl);
  1616. if (szExt)
  1617. {
  1618. fIsHTML = ((0 == StrCmpNI(szExt, TEXT(".htm"),4)) ||
  1619. (0 == StrCmpNI(szExt, TEXT(".html"),5)));
  1620. }
  1621. }
  1622. }
  1623. if (fHitsNet || fIsHTML)
  1624. {
  1625. // Create a shortcut object and
  1626. HRESULT hr = CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
  1627. IID_PPV_ARG(IUniformResourceLocator, ppUrlOut));
  1628. if (SUCCEEDED(hr))
  1629. {
  1630. hr = (*ppUrlOut)->SetURL(szUrl, 0);
  1631. if (S_OK == hr)
  1632. {
  1633. // Get the IDataObject and send that back for the Drag Drop
  1634. hr = (*ppUrlOut)->QueryInterface(IID_PPV_ARG(IDataObject, ppdtobj));
  1635. if (SUCCEEDED(hr))
  1636. {
  1637. IUnknown_SetSite(*ppUrlOut, pUnkSite); // Only set the site if we're sure of
  1638. // returning SUCCESS
  1639. }
  1640. }
  1641. }
  1642. }
  1643. else
  1644. {
  1645. hr = E_FAIL;
  1646. }
  1647. }
  1648. if (FAILED(hr))
  1649. {
  1650. SAFERELEASE(*ppUrlOut);
  1651. SAFERELEASE(*ppdtobj);
  1652. }
  1653. return hr;
  1654. }
  1655. HRESULT SendDocToMailRecipient(LPCITEMIDLIST pidl, UINT uiCodePage, DWORD grfKeyState, IUnknown *pUnkSite)
  1656. {
  1657. IDataObject *pdtobj = NULL;
  1658. IUniformResourceLocator *purl = NULL;
  1659. HRESULT hr = CreateShortcutSetSiteAndGetDataObjectIfPIDLIsNetUrl(pidl, pUnkSite, &purl, &pdtobj);
  1660. if (FAILED(hr))
  1661. {
  1662. ASSERT(NULL == pdtobj);
  1663. ASSERT(NULL == purl);
  1664. hr = GetDataObjectForPidl(pidl, &pdtobj);
  1665. }
  1666. if (SUCCEEDED(hr))
  1667. {
  1668. IQueryCodePage * pQcp;
  1669. if (SUCCEEDED(pdtobj->QueryInterface(IID_PPV_ARG(IQueryCodePage, &pQcp))))
  1670. {
  1671. pQcp->SetCodePage(uiCodePage);
  1672. pQcp->Release();
  1673. }
  1674. hr = DropPicOnMailRecipient(pdtobj, grfKeyState);
  1675. pdtobj->Release();
  1676. }
  1677. if (purl)
  1678. {
  1679. IUnknown_SetSite(purl, NULL);
  1680. purl->Release();
  1681. }
  1682. return hr;
  1683. }
  1684. //////////////////////////////////////////////////////////////////////////////
  1685. #undef TF_MYPICS