|
|
#include "priv.h"
#include <iehelpid.h>
#include <pstore.h>
#include "hlframe.h"
#include "shldisp.h"
#include "opsprof.h"
#include "resource.h"
#include <mluisupp.h>
#include "htmlstr.h"
#include "mypics.h"
#include "mshtmcid.h"
#include "util.h"
#include "winuser.h"
//////////////////////////////////////////////////////////////////////////////////
//
// filename: mypics.cpp
//
// description: implements the my pictures exposure hoverbar thingie
//
// notes: lots of stuff is stolen from iforms.cpp and iformsp.h
//
// history: 06.15.2000 created by t-jdavis
//
//////////////////////////////////////////////////////////////////////////////////
extern HINSTANCE g_hinst;
#define TF_MYPICS TF_CUSTOM2
// we don't actually use all of these, but we COULD, you know, if we wanted too.
CMyPicsEventSinkCallback::EventSinkEntry CMyPicsEventSinkCallback::EventsToSink[] = { { EVENT_MOUSEOVER, L"onmouseover", L"mouseover" }, { EVENT_MOUSEOUT, L"onmouseout", L"mouseout" }, { EVENT_SCROLL, L"onscroll", L"scroll" }, { EVENT_RESIZE, L"onresize", L"resize" } };
// image toolbar states
enum { HOVERSTATE_HIDING = 0, HOVERSTATE_SHOWING, HOVERSTATE_LOCKED, HOVERSTATE_SCROLLING, HOVERSTATE_WAITINGTOSHOW };
//
// CMyPics
//
// set some stuff
CMyPics::CMyPics() { TraceMsg(TF_MYPICS, "+CMyPics::CMyPics");
m_Hwnd = NULL; m_hWndMyPicsToolBar = NULL; m_hWndHover = NULL; m_pEleCurr = NULL; m_pSink = NULL; m_bIsOffForSession = FALSE; m_cRef = 1; m_bGalleryMeta = TRUE;
TraceMsg(TF_MYPICS, "-CMyPics::CMyPics"); }
// destroy whatever needs destroying....
CMyPics::~CMyPics() { TraceMsg(TF_MYPICS, "+CMyPics::~CMyPics");
DestroyHover();
ATOMICRELEASE(m_pEleCurr);
if (m_hWndMyPicsToolBar) DestroyWindow(m_hWndMyPicsToolBar);
if (m_hWndHover) { SetWindowPtr(m_hWndHover, GWLP_USERDATA, NULL); DestroyWindow(m_hWndHover); }
TraceMsg(TF_MYPICS, "-CMyPics::~CMyPics"); }
// did the user turn this feature off?
BOOL CMyPics::IsOff() { return (m_bIsOffForSession); }
void CMyPics::IsGalleryMeta(BOOL bFlag) { m_bGalleryMeta = bFlag; }
HRESULT CMyPics::Init(IHTMLDocument2 *pDoc2) { HRESULT hr = S_OK;
TraceMsg(TF_MYPICS, "+CMyPics::Init");
ASSERT(pDoc2);
//sink things
IHTMLElement2 *pEle2 = NULL; IHTMLElementCollection *pCollect = NULL; IHTMLElementCollection *pSubCollect = NULL; IDispatch *pDisp = NULL; VARIANT TagName; ULONG ulCount = 0; VARIANTARG va1; VARIANTARG va2; IHTMLWindow3 *pWin3 = NULL; // ...remember this...
m_pDoc2 = pDoc2; pDoc2->AddRef(); // setup variant for finding all the IMG tags...
TagName.vt = VT_BSTR; TagName.bstrVal = (BSTR)c_bstr_IMG; //get all tags
hr = pDoc2->get_all(&pCollect); if (FAILED(hr)) goto Cleanup;
//get all IMG tags
hr = pCollect->tags(TagName, &pDisp); if (FAILED(hr)) goto Cleanup; if (pDisp) { hr = pDisp->QueryInterface(IID_IHTMLElementCollection,(void **)&pSubCollect); ATOMICRELEASE(pDisp); } if (FAILED(hr)) goto Cleanup;
//get IMG tag count
hr = pSubCollect->get_length((LONG *)&ulCount); if (FAILED(hr)) goto Cleanup;
va1.vt = VT_I4; va2.vt = VT_EMPTY; //iterate through tags sinking events to elements
for (int i=0; i<(LONG)ulCount; i++) { pDisp = NULL; va1.lVal = (LONG)i; pSubCollect->item(va1, va2, &pDisp);
// only create a new CEventSink once
if (!m_pSink && pDisp) m_pSink = new CEventSink(this);
if (pDisp) { hr = pDisp->QueryInterface(IID_IHTMLElement2, (void **)&pEle2); if (FAILED(hr)) goto Cleanup;
ASSERT(m_pSink);
if (m_pSink && pEle2) { EVENTS events[] = { EVENT_MOUSEOVER, EVENT_MOUSEOUT, EVENT_RESIZE }; m_pSink->SinkEvents(pEle2, ARRAYSIZE(events), events); } ATOMICRELEASE(pEle2); ATOMICRELEASE(pDisp); } }
// sink scroll event from the window, because it doesn't come from elements.
if (m_pSink) { Win3FromDoc2(m_pDoc2, &pWin3);
if (pWin3) { m_pWin3 = pWin3; m_pWin3->AddRef();
EVENTS eventScroll[] = { EVENT_SCROLL }; m_pSink->SinkEvents(pWin3, ARRAYSIZE(eventScroll), eventScroll); } } //end sinking things
Cleanup:
ATOMICRELEASE(pCollect); ATOMICRELEASE(pSubCollect); ATOMICRELEASE(pWin3); ATOMICRELEASE(pDisp); ATOMICRELEASE(pEle2);
TraceMsg(TF_MYPICS, "-CMyPics::Init");
return hr; }
HRESULT CMyPics::UnInit() { // Unhook regular event sink
TraceMsg(TF_MYPICS, "+CMyPics::UnInit");
if (m_pSink) { if (m_pWin3) { EVENTS events[] = { EVENT_SCROLL }; m_pSink->UnSinkEvents(m_pWin3, ARRAYSIZE(events), events); SAFERELEASE(m_pWin3); }
m_pSink->SetParent(NULL); ATOMICRELEASE(m_pSink); }
SAFERELEASE(m_pEleCurr); SAFERELEASE(m_pDoc2); TraceMsg(TF_MYPICS, "-CMyPics::UnInit");
return S_OK; }
ULONG CMyPics::AddRef(void) { return ++m_cRef; }
ULONG CMyPics::Release(void) { if (--m_cRef == 0) { delete this; return 0; }
return m_cRef; }
// has this been disabled by some administrator or something via IEAK?
BOOL MP_IsEnabledInIEAK() { DWORD dwType = REG_DWORD; DWORD dwSize; DWORD dwEnabled; // dsheldon - should this var be called dwDisabled since we say (dwEnabled != 1) == enabled?
DWORD dwRet; const TCHAR c_szSPMIEPS[] = TEXT("Software\\Policies\\Microsoft\\Internet Explorer\\PhotoSupport"); const TCHAR c_szVal[] = TEXT("MyPics_Hoverbar");
dwSize = sizeof(dwEnabled);
dwRet = SHGetValue(HKEY_CURRENT_USER, c_szSPMIEPS, c_szVal, &dwType, &dwEnabled, &dwSize);
if ((dwType == REG_DWORD) && (dwRet == ERROR_SUCCESS)) { if (dwEnabled!=1) return TRUE; // enabled
else return FALSE; // disabled
}
// value not found...
return TRUE; }
// has the user explicitly disabled this feature for now and all time via intern control panel?
BOOL MP_IsEnabledInRegistry() { DWORD dwType = REG_SZ; DWORD dwSize; TCHAR szEnabled[16]; DWORD dwRet; const TCHAR c_szSMIEM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main"); const TCHAR c_szVal[] = TEXT("Enable_MyPics_Hoverbar");
dwSize = sizeof(szEnabled);
dwRet = SHGetValue(HKEY_CURRENT_USER, c_szSMIEM, c_szVal, &dwType, szEnabled, &dwSize);
if (dwRet == ERROR_INSUFFICIENT_BUFFER) { ASSERT(dwRet == ERROR_SUCCESS); // this is wacky...
return FALSE; }
if ((dwType == REG_SZ) && (dwRet == ERROR_SUCCESS)) { if (!StrCmp(szEnabled, TEXT("yes"))) return TRUE; // enabled
else return FALSE; // disabled
}
// value not found...
return TRUE; }
DWORD MP_GetFilterInfoFromRegistry() {
const TCHAR c_szSMIEAOMM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main"); const TCHAR c_szVal[] = TEXT("Image_Filter"); DWORD dwType, dwSize, dwFilter, dwRet; dwSize = sizeof(dwFilter);
dwRet = SHGetValue(HKEY_CURRENT_USER, c_szSMIEAOMM, c_szVal, &dwType, &dwFilter, &dwSize);
if ((dwRet != ERROR_SUCCESS) || (dwType != REG_DWORD)) { dwFilter = MP_MIN_SIZE; }
return dwFilter; }
DWORD MP_GetOffsetInfoFromRegistry() {
const TCHAR c_szSMIEAOMM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main"); const TCHAR c_szVal[] = TEXT("Offset"); DWORD dwType, dwSize, dwOffset, dwRet; dwSize = sizeof(dwOffset);
dwRet = SHGetValue(HKEY_CURRENT_USER, c_szSMIEAOMM, c_szVal, &dwType, &dwOffset, &dwSize);
if ((dwRet != ERROR_SUCCESS) || (dwType != REG_DWORD)) { dwOffset = MP_HOVER_OFFSET; }
return dwOffset; }
BOOL_PTR CALLBACK DisableMPDialogProc(HWND hDlg, UINT uMsg, WPARAM wparam, LPARAM lparam) { BOOL bMsgHandled = FALSE;
switch (uMsg) { case WM_INITDIALOG: { // center dialog... yay msdn...
RECT rc; GetWindowRect(hDlg, &rc); SetWindowPos(hDlg, HWND_TOP, ((GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2), ((GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 2), 0, 0, SWP_NOSIZE); } break;
case WM_COMMAND: switch (LOWORD(wparam)) { case IDC_MP_ALWAYS: EndDialog(hDlg, IDC_MP_ALWAYS); break;
case IDC_MP_THISSESSION: EndDialog(hDlg, IDC_MP_THISSESSION); break;
case IDC_MP_CANCEL: EndDialog(hDlg, IDC_MP_CANCEL); break; } break;
case WM_CLOSE: EndDialog(hDlg, IDC_MP_CANCEL); break;
default: break; } return(bMsgHandled); }
LRESULT CALLBACK CMyPics::s_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CMyPics* pThis = (CMyPics*)GetWindowPtr(hWnd, GWLP_USERDATA);
TraceMsg(TF_MYPICS, "+CMyPics::s_WndProc hWnd=%x, pThis=%p", hWnd, pThis);
HRESULT hr = S_OK; IOleCommandTarget *pOleCommandTarget = NULL; switch (uMsg) { case WM_SIZE: if (!pThis) break;
SetWindowPos(pThis->m_hWndMyPicsToolBar, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); break;
case WM_ERASEBKGND:
if (!pThis) break;
{ RECT rc; HBRUSH hb = GetSysColorBrush(COLOR_3DFACE);
GetClientRect(pThis->m_hWndMyPicsToolBar, &rc); FillRect((HDC)wParam, &rc, hb); return TRUE; }
case WM_COMMAND:
if (!pThis) break;
switch(LOWORD(wParam)) { case IDM_MYPICS_SAVE: //Save As... dialogue
ASSERT(pThis->m_pEleCurr);
// the evil QI call...
hr = pThis->m_pEleCurr->QueryInterface(IID_IOleCommandTarget, (void **)&pOleCommandTarget); if (FAILED(hr)) return(hr);
// hide the hoverthing so it doesn't cause us any nasty problems
pThis->HideHover(); // launch the Save As dialogue thingie...
pOleCommandTarget->Exec(&CGID_MSHTML, IDM_SAVEPICTURE, 0, 0, NULL); ATOMICRELEASE(pOleCommandTarget);
break; case IDM_MYPICS_PRINT: { // get the cmd target
hr = pThis->m_pEleCurr->QueryInterface(IID_IOleCommandTarget, (void **)&pOleCommandTarget); if (FAILED(hr)) return(hr); pThis->HideHover(); //pThis->m_hoverState = HOVERSTATE_SHOWING; // kludge to keep hover from appearing under print dialogue
pOleCommandTarget->Exec(&CGID_MSHTML, IDM_MP_PRINTPICTURE, 0, 0, NULL); ATOMICRELEASE(pOleCommandTarget); //pThis->m_hoverState = HOVERSTATE_HIDING;
} break; case IDM_MYPICS_EMAIL: { // get the cmd target...
hr = pThis->m_pEleCurr->QueryInterface(IID_IOleCommandTarget, (void **)&pOleCommandTarget); if (FAILED(hr)) return(hr);
// ... and then hide the hover bar...
pThis->HideHover(); //pThis->m_hoverState = HOVERSTATE_SHOWING; // kludge to keep hover from appearing under print dialogue
// ... and pray this works...
pOleCommandTarget->Exec(&CGID_MSHTML, IDM_MP_EMAILPICTURE, 0, 0, NULL); ATOMICRELEASE(pOleCommandTarget);
// ... and cleanup
//pThis->m_hoverState = HOVERSTATE_HIDING;
} break; case IDM_MYPICS_MYPICS: // Open My Pictures folder
// get the cmd target
hr = pThis->m_pEleCurr->QueryInterface(IID_IOleCommandTarget, (void **)&pOleCommandTarget); if (FAILED(hr)) return(hr); pOleCommandTarget->Exec(&CGID_MSHTML, IDM_MP_MYPICS, 0, 0, NULL); ATOMICRELEASE(pOleCommandTarget);
hr = S_OK; pThis->HideHover();
break;
default: break; } break;
case WM_NOTIFY: // tooltips...
if (!pThis) break; switch (((LPNMHDR)lParam)->code) { case TTN_NEEDTEXT: { LPTOOLTIPTEXT lpToolTipText; TCHAR szBuf[MAX_PATH]; lpToolTipText = (LPTOOLTIPTEXT)lParam; hr = MLLoadString((UINT)lpToolTipText->hdr.idFrom, szBuf, ARRAYSIZE(szBuf)); lpToolTipText->lpszText = szBuf; break; } } break;
case WM_SETTINGCHANGE:
if (!pThis) break;
{ pThis->DestroyHover(); // to stop wierd window distortion
break; }
case WM_CONTEXTMENU:
if (!pThis) break;
{ // load the menu
HMENU hMenu0 = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(IDR_MYPICS_CONTEXT_MENU)); HMENU hMenu1 = GetSubMenu(hMenu0, 0);
if(!hMenu1) break; POINT point;
point.x = (LONG)GET_X_LPARAM(lParam); point.y = (LONG)GET_Y_LPARAM(lParam);
ASSERT(pThis->m_hoverState=HOVERSTATE_SHOWING);
// lock against mouseouts
pThis->m_hoverState = HOVERSTATE_LOCKED;
// display it, get choice (if any)
int iPick = TrackPopupMenu(hMenu1, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, 0, hWnd, (RECT *)NULL);
DestroyMenu(hMenu0); DestroyMenu(hMenu1);
pThis->m_hoverState = HOVERSTATE_SHOWING;
if (iPick) { switch(iPick) { case IDM_DISABLE_MYPICS: { pThis->HideHover(); // create dialog to ask user if they want to turn this stuff off...
// (explicit cast to make Win64 builds happy)
int iResult = (int)DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(DLG_DISABLE_MYPICS), pThis->m_Hwnd, DisableMPDialogProc, NULL); // deal with their choice...
if (iResult) { switch (iResult) { case IDC_MP_ALWAYS: { pThis->m_bIsOffForSession = TRUE; DWORD dwType = REG_SZ; DWORD dwSize; TCHAR szEnabled[16] = TEXT("no"); DWORD dwRet; const TCHAR c_szSMIEM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main"); const TCHAR c_szVal[] = TEXT("Enable_MyPics_Hoverbar");
dwSize = sizeof(szEnabled);
dwRet = SHSetValue(HKEY_CURRENT_USER, c_szSMIEM, c_szVal, dwType, szEnabled, dwSize); } break; case IDC_MP_THISSESSION: // twiddle member var flag
// this is propagated back up to COmWindow via ReleaseMyPics() function.
pThis->m_bIsOffForSession = TRUE; break;
default: break; } } } break; case IDM_HELP_MYPICS: pThis->HideHover(); SHHtmlHelpOnDemandWrap(hWnd, TEXT("iexplore.chm > iedefault"), 0, (DWORD_PTR) TEXT("pic_tb_ovr.htm"), ML_CROSSCODEPAGE); break; default: // um, do nothing
break; } } }
break;
default: return (DefWindowProc(hWnd, uMsg, wParam, lParam)); }
TraceMsg(TF_MYPICS, "-CMyPics::s_WndProc hWnd=%x, pThis=%p", hWnd, pThis);
return (hr); }
VOID CALLBACK CMyPics::s_TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { TraceMsg(TF_MYPICS, "+CMyPics::TimerProc");
CMyPics* pThis = (CMyPics*)GetWindowPtr(hwnd, GWLP_USERDATA);
switch (uMsg) { case WM_TIMER: KillTimer(hwnd, IDT_MP_TIMER); if (pThis && (pThis->m_hoverState == HOVERSTATE_WAITINGTOSHOW)) { // Our hover bar is waiting to be shown.
if (pThis->m_pEleCurr) { // We still have an element. Show it.
pThis->m_hoverState = HOVERSTATE_SHOWING;
pThis->ShowHover(); } else { // Our timer popped, but we don't have an element.
pThis->HideHover(); } } break; default: break; } TraceMsg(TF_MYPICS, "-CMyPics::TimerProc"); }
BOOL CMyPics::ShouldAppearOnThisElement(IHTMLElement *pEle) { BOOL bRet = TRUE; // appear by default
VARIANT varVal = {0}; BSTR bstrAttribute = NULL; // to check img tags for expando
IHTMLRect *pRect = NULL; // to get screen coords
IHTMLElement2 *pEle2 = NULL; IHTMLElement3 *pEle3 = NULL; // to check for contenteditable mode
VARIANT_BOOL bEdit = FALSE;// becomes true if contenteditable mode is true
LONG lLeft; // these are the screen coords
LONG lRight; // we get right and bottom to det size of image
LONG lTop; LONG lBottom; DWORD dwFilter; IOleCommandTarget *pOleCommandTarget = NULL;
TraceMsg(TF_MYPICS, "+CMyPics::ShouldAppearOnThisElement");
// don't create it if it already exists. thats bad.
if ((HOVERSTATE_SHOWING == m_hoverState) || (HOVERSTATE_LOCKED == m_hoverState)) { bRet = FALSE; goto Cleanup; }
m_bGalleryImg = FALSE;
if (!pEle) { bRet = FALSE; goto Cleanup; }
// find out if the image didn't load or is unrenderable
if (SUCCEEDED(pEle->QueryInterface(IID_IOleCommandTarget, (void **)&pOleCommandTarget))) { OLECMD rgCmd;
rgCmd.cmdID = IDM_SAVEPICTURE; // this is the same check the context menu uses
rgCmd.cmdf = 0;
pOleCommandTarget->QueryStatus(&CGID_MSHTML, 1, &rgCmd, NULL);
if (!(OLECMDF_ENABLED & rgCmd.cmdf)) { bRet = FALSE; goto Cleanup; } }
// check for explicit enable/disable attribute in img tag...
bstrAttribute=SysAllocString(L"galleryimg"); if (!bstrAttribute) goto Cleanup;
if (SUCCEEDED(pEle->getAttribute(bstrAttribute, 0, &varVal))) { if (varVal.vt == VT_BSTR) { if (StrCmpIW(varVal.bstrVal, L"true") == 0 || StrCmpIW(varVal.bstrVal, L"on") == 0 || StrCmpIW(varVal.bstrVal, L"yes") == 0 ) { // Explicitly turned on. Honor it and leave.
bRet = TRUE; m_bGalleryImg = TRUE; goto Cleanup; } if (StrCmpIW(varVal.bstrVal, L"false") == 0 || StrCmpIW(varVal.bstrVal, L"off") == 0 || StrCmpIW(varVal.bstrVal, L"no") == 0 ) { // Explicitly turned off. Honor it and leave.
bRet = FALSE; goto Cleanup; } } else if (varVal.vt == VT_BOOL) { if (varVal.boolVal == VARIANT_TRUE) { bRet = TRUE; m_bGalleryImg = TRUE; goto Cleanup; } else { bRet = FALSE; goto Cleanup; } } }
VariantClear(&varVal); SysFreeString(bstrAttribute);
// After checking "galleryimg" tag, check to see if turned off by the META tag
if (m_bGalleryMeta == FALSE) return FALSE;
// check for mappings on the image...
bstrAttribute=SysAllocString(L"usemap"); if (!bstrAttribute) return (bRet);
if (SUCCEEDED(pEle->getAttribute(bstrAttribute, 0, &varVal))) { if (varVal.vt == VT_BSTR) { // What do we do here?
bRet = (varVal.bstrVal == NULL); if (!bRet) goto Cleanup; } } VariantClear(&varVal); SysFreeString(bstrAttribute);
// check for mappings on the image...
bstrAttribute=SysAllocString(L"ismap"); if (!bstrAttribute) return (bRet);
if (SUCCEEDED(pEle->getAttribute(bstrAttribute, 0, &varVal))) { // If the attribute exists, then we need to return FALSE *unless* we see a value of FALSE
bRet = FALSE; if (varVal.vt == VT_BOOL && varVal.boolVal == VARIANT_FALSE) { // "ismap" is false, so we can show the hover bar over this image.
bRet = TRUE; } } if (!bRet) goto Cleanup;
bRet = FALSE; // If any of the calls below fail, we'll exit with "FALSE".
// Now check to see if we pass the size filter.
// get an IHTMLElement2 from the IHTMLElement passed in...
if (FAILED(pEle->QueryInterface(IID_IHTMLElement2, (void **)&pEle2) )) goto Cleanup;
// get coords...
if (FAILED(pEle2->getBoundingClientRect(&pRect) )) goto Cleanup;
if (FAILED(pRect->get_left(&lLeft) )) goto Cleanup;
if (FAILED(pRect->get_right(&lRight) )) goto Cleanup;
if (FAILED(pRect->get_top(&lTop) )) goto Cleanup;
if (FAILED(pRect->get_bottom(&lBottom) )) goto Cleanup;
dwFilter = MP_GetFilterInfoFromRegistry();
// see if this picture is big enough to qualify as a "Photo"...
// TODO: decide if we like checking aspect ratio or not
if ( (lRight - lLeft >= (LONG)dwFilter && lBottom - lTop >= (LONG)dwFilter) /*&& !(2*(min(lRight-lLeft,lBottom-lTop)) < max(lRight-lLeft,lBottom-lTop)) */) bRet = TRUE;
if (FAILED(pEle2->QueryInterface(IID_IHTMLElement3, (void **)&pEle3) )) goto Cleanup;
if (FAILED(pEle3->get_isContentEditable(&bEdit) )) goto Cleanup;
if (bEdit) bRet = FALSE;
Cleanup: VariantClear(&varVal); if (bstrAttribute) SysFreeString(bstrAttribute);
SAFERELEASE(pOleCommandTarget);
SAFERELEASE(pEle3); SAFERELEASE(pRect); SAFERELEASE(pEle2); TraceMsg(TF_MYPICS, "-CMyPics::ShouldAppearOnThisElement");
return bRet; }
HRESULT CMyPics::CreateHover() { HRESULT hr = S_OK; SIZE size = {0,0}; WORD wImage; HBITMAP hbmp = NULL; HBITMAP hbmpHot = NULL;
TraceMsg(TF_MYPICS, "+CMyPics::CreateHover, this=%p, m_hoverState=%d", this, m_hoverState);
InitCommonControls();
WNDCLASS wc = {0}; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpszClassName = TEXT("MyPicturesHost"); wc.lpfnWndProc = s_WndProc; wc.hInstance = g_hinst; wc.hbrBackground = HBRUSH(COLOR_BTNFACE); RegisterClass(&wc);
// create the rebar to hold the toolbar...
if (!m_hWndHover) {
m_hWndHover = CreateWindow(TEXT("MyPicturesHost"), TEXT(""), WS_DLGFRAME | WS_VISIBLE | WS_CHILD, 0, 0, 0, 0, m_Hwnd, NULL, g_hinst, NULL);
if (!m_hWndHover) { TraceMsg(TF_MYPICS | TF_WARNING, "CMyPics::CreateHover, unable to create m_hWndHover"); hr = E_FAIL; goto Cleanup; }
ASSERT(GetWindowPtr(m_hWndHover, GWLP_USERDATA) == NULL); SetWindowPtr(m_hWndHover, GWLP_USERDATA, this);
// set cc version
SendMessage(m_hWndHover, CCM_SETVERSION, COMCTL32_VERSION, 0); } // create the toolbar...
if (!m_hWndMyPicsToolBar) {
m_hWndMyPicsToolBar = CreateWindow(TOOLBARCLASSNAME, TEXT(""), TBSTYLE_TOOLTIPS | CCS_NODIVIDER | TBSTYLE_FLAT | WS_VISIBLE | WS_CHILD, 0,0,0,0, m_hWndHover, NULL, g_hinst, NULL);
if (!m_hWndMyPicsToolBar) { TraceMsg(TF_MYPICS | TF_WARNING, "CMyPics::CreateHover, unable to create m_hWndMyPicsToolBar"); hr = E_FAIL; goto Cleanup; } SetWindowPtr(m_hWndMyPicsToolBar, GWLP_USERDATA, this); // for the timer proc
// set cc version for this too, and the sizeof tbbutton struct...
SendMessage(m_hWndMyPicsToolBar, CCM_SETVERSION, COMCTL32_VERSION, 0); SendMessage(m_hWndMyPicsToolBar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); }
// create image lists...
wImage = ((IsOS(OS_WHISTLERORGREATER)) ? IDB_MYPICS_TOOLBARGW : IDB_MYPICS_TOOLBARG);
if (!m_himlHover) { m_himlHover = ImageList_LoadImage(HINST_THISDLL, MAKEINTRESOURCE(wImage), 16, 0, CLR_DEFAULT, IMAGE_BITMAP, LR_CREATEDIBSECTION); if (!m_himlHover) { TraceMsg(TF_MYPICS | TF_WARNING, "CMyPics::CreateHover, unable to create m_himlHover"); } }
wImage = ((IsOS(OS_WHISTLERORGREATER)) ? IDB_MYPICS_TOOLBARW : IDB_MYPICS_TOOLBAR);
if (!m_himlHoverHot) { m_himlHoverHot = ImageList_LoadImage(HINST_THISDLL, MAKEINTRESOURCE(wImage) , 16, 0, CLR_DEFAULT, IMAGE_BITMAP, LR_CREATEDIBSECTION); if (!m_himlHoverHot) { TraceMsg(TF_MYPICS | TF_WARNING, "CMyPics::CreateHover, unable to create m_himlHoverHot"); } }
// set image list and hot image list
SendMessage(m_hWndMyPicsToolBar, TB_SETIMAGELIST, 0, (LPARAM)m_himlHover ); SendMessage(m_hWndMyPicsToolBar, TB_SETHOTIMAGELIST, 0, (LPARAM)m_himlHoverHot);
TBBUTTON tbButton;
// set bitmap indexes in tbbutton structure (this may not be necessary)
for (int i=0;i<MP_NUM_TBBITMAPS;i++) { tbButton.iBitmap = MAKELONG(i,0); tbButton.fsState = TBSTATE_ENABLED; tbButton.fsStyle = TBSTYLE_BUTTON; tbButton.dwData = 0; tbButton.iString = 0; switch(i) { case 0: tbButton.idCommand = IDM_MYPICS_SAVE; break; case 1: tbButton.idCommand = IDM_MYPICS_PRINT; break; case 2: tbButton.idCommand = IDM_MYPICS_EMAIL; break; case 3: tbButton.idCommand = IDM_MYPICS_MYPICS; break; } SendMessage(m_hWndMyPicsToolBar, TB_INSERTBUTTON, i, (LPARAM)&tbButton); }
Cleanup:
TraceMsg(TF_MYPICS, "-CMyPics::CreateHover, this=%p, m_hoverState=%d", this, m_hoverState);
return hr; }
HRESULT CMyPics::DestroyHover() { HRESULT hr = S_OK;
TraceMsg(TF_MYPICS, "+CMyPics::DestroyHover, this=%p, m_hoverState=%d", this, m_hoverState);
// If we have a MyPicsToolBar...
if (m_hWndMyPicsToolBar) { // first destroy the toolbar
if (!DestroyWindow(m_hWndMyPicsToolBar)) { TraceMsg(TF_MYPICS, "In CMyPics::DestroyHover, DestroyWindow(m_hWndMyPicsToolBar) failed"); hr = E_FAIL; } m_hWndMyPicsToolBar=NULL; }
// If we have a hover window...
if (m_hWndHover) { // Clear the window word
SetWindowPtr(m_hWndHover, GWLP_USERDATA, NULL);
// then destroy the rebar
if (!DestroyWindow(m_hWndHover)) { hr = E_FAIL; goto Cleanup; } m_hWndHover = NULL; }
// and destroy the image lists...
if (m_himlHover) { ImageList_Destroy(m_himlHover); m_himlHover = NULL; }
if (m_himlHoverHot) { ImageList_Destroy(m_himlHoverHot); m_himlHoverHot = NULL; }
Cleanup: TraceMsg(TF_MYPICS, "-CMyPics::DestroyHover, this=%p, hr=%x", this, hr);
return hr; }
HRESULT CMyPics::HideHover() { HRESULT hr = S_OK;
TraceMsg(TF_MYPICS, "+CMyPics::HideHover, this=%p, m_hoverState=%d", this, m_hoverState);
if (m_hWndHover) { ShowWindow(m_hWndHover, SW_HIDE); m_hoverState = HOVERSTATE_HIDING; } else hr = E_FAIL;
TraceMsg(TF_MYPICS, "-CMyPics::HideHover, this=%p, m_hoverState=%d", this, m_hoverState);
return hr; }
IHTMLElement *CMyPics::GetIMGFromArea(IHTMLElement *pEleIn, POINT ptEvent) { // someone got an IHTMLElement and decided it was an area tag
// so find the img tag associated and return it as an IHTMLElement
BSTR bstrName = NULL; BSTR bstrUseMap = NULL; IHTMLElement *pEleParent = NULL; IHTMLElement *pEleMisc = NULL; IHTMLElement2 *pEle2Misc = NULL; IHTMLElement *pEleMiscPar = NULL; IHTMLMapElement *pEleMap = NULL; IHTMLImgElement *pEleImg = NULL; IHTMLElement *pEleOut = NULL; IHTMLElementCollection *pCollect = NULL; IHTMLElementCollection *pSubCollect = NULL; IDispatch *pDisp = NULL; VARIANT TagName; ULONG ulCount = 0; VARIANTARG va1; VARIANTARG va2; HRESULT hr; POINT ptMouse, ptScr; LONG xInIMG = 0, yInIMG = 0, lOffset = 0, lOffsetLeft = 0, lOffsetTop = 0, lScrollLeft = 0, lScrollTop = 0, lOffsetW = 0, lOffsetH = 0;
TagName.vt = VT_BSTR; TagName.bstrVal = (BSTR)c_bstr_IMG;
// first get the map element
if (SUCCEEDED(pEleIn->get_offsetParent(&pEleParent))) { // get the map element
hr=pEleParent->QueryInterface(IID_IHTMLMapElement, (void **)&pEleMap); if (FAILED(hr)) goto Cleanup;
// next get the name of the map
if (SUCCEEDED(pEleMap->get_name(&bstrName))) { //next get all tags
hr = m_pDoc2->get_all(&pCollect); if (FAILED(hr)) goto Cleanup;
//get all IMG tags
hr = pCollect->tags(TagName, &pDisp); if (FAILED(hr)) goto Cleanup; if (pDisp) { hr = pDisp->QueryInterface(IID_IHTMLElementCollection,(void **)&pSubCollect); ATOMICRELEASE(pDisp); } if (FAILED(hr)) goto Cleanup;
//get IMG tag count
hr = pSubCollect->get_length((LONG *)&ulCount); if (FAILED(hr)) goto Cleanup; va1.vt = VT_I4; va2.vt = VT_EMPTY;
ASSERT(pDisp==NULL); //iterate through tags looking for images that have the right usemap set
for (int i=0; i<(LONG)ulCount; i++) { ATOMICRELEASE(pEleImg); ATOMICRELEASE(pDisp); pDisp = NULL; bstrUseMap = NULL; xInIMG = 0; yInIMG = 0; lOffset = 0; lOffsetLeft = 0; lOffsetTop = 0; lScrollLeft = 0; lScrollTop = 0; lOffsetW = 0; lOffsetH = 0; va1.lVal = (LONG)i;
pSubCollect->item(va1, va2, &pDisp);
if (pDisp) { hr = pDisp->QueryInterface(IID_IHTMLImgElement, (void **)&pEleImg); if (FAILED(hr)) goto Cleanup;
hr = pEleImg->get_useMap(&bstrUseMap); if (FAILED(hr)) goto Cleanup;
// this will be non-null if set for this IMG element...
if (bstrUseMap){ // skip the prepended '#' and see if this is what we're looking for...
if (StrCmp(bstrUseMap + 1, bstrName) == 0) { m_pWin3->get_screenLeft(&ptScr.x); m_pWin3->get_screenTop (&ptScr.y);
//Ok, we found a candidate. See if the mouse is here...
ptMouse.x = ptEvent.x - ptScr.x; ptMouse.y = ptEvent.y - ptScr.y;
hr = pDisp->QueryInterface(IID_IHTMLElement, (void **)&pEleMisc); if (FAILED(hr)) goto Cleanup;
while (pEleMisc) { hr = pEleMisc->QueryInterface(IID_IHTMLElement2, (void **)&pEle2Misc); if (FAILED(hr)) goto Cleanup;
pEleMisc->get_offsetLeft(&lOffsetLeft); pEle2Misc->get_scrollLeft(&lScrollLeft);
lOffset += lOffsetLeft - lScrollLeft;
pEleMisc->get_offsetParent(&pEleMiscPar); ATOMICRELEASE(pEleMisc); ATOMICRELEASE(pEle2Misc); pEleMisc=pEleMiscPar;
}
ATOMICRELEASE(pEleMiscPar);
hr = pDisp->QueryInterface(IID_IHTMLElement, (void **)&pEleMisc); if (FAILED(hr)) goto Cleanup;
xInIMG = ptMouse.x - lOffset; pEleMisc->get_offsetWidth(&lOffsetW);
if ((xInIMG < 0) || (xInIMG > lOffsetW)) continue;
lOffset = 0;
while (pEleMisc) { hr = pEleMisc->QueryInterface(IID_IHTMLElement2, (void **)&pEle2Misc); if (FAILED(hr)) goto Cleanup;
pEleMisc->get_offsetTop(&lOffsetTop); pEle2Misc->get_scrollTop(&lScrollTop);
lOffset += lOffsetTop - lScrollTop;
pEleMisc->get_offsetParent(&pEleMiscPar); ATOMICRELEASE(pEleMisc); ATOMICRELEASE(pEle2Misc); pEleMisc=pEleMiscPar;
}
ATOMICRELEASE(pEleMiscPar);
hr = pDisp->QueryInterface(IID_IHTMLElement, (void **)&pEleMisc); if (FAILED(hr)) goto Cleanup;
yInIMG = ptMouse.y - lOffset; pEleMisc->get_offsetHeight(&lOffsetH);
ATOMICRELEASE(pEleMisc);
if ((yInIMG < 0) || (yInIMG > lOffsetH)) continue;
// if we get to this point we found our IMG element so...
// ...do the QI...
pEleImg->QueryInterface(IID_IHTMLElement, (void **)&pEleOut); // ...and we're done.
break;
} SysFreeString(bstrUseMap); bstrUseMap = NULL; } } } } }
Cleanup:
ATOMICRELEASE(pCollect); ATOMICRELEASE(pSubCollect); ATOMICRELEASE(pEleMap); ATOMICRELEASE(pEleParent); ATOMICRELEASE(pDisp); ATOMICRELEASE(pEleImg); ATOMICRELEASE(pEleMisc); ATOMICRELEASE(pEle2Misc); ATOMICRELEASE(pEleMiscPar); SysFreeString(bstrUseMap); SysFreeString(bstrName);
return (pEleOut); }
// sometimes coordinates are relative to a parent object, like in frames, etc. so this gets their real position relative
// to the browser window...
HRESULT CMyPics::GetRealCoords(IHTMLElement2 *pEle2, HWND hwnd, LONG *plLeft, LONG *plTop, LONG *plRight, LONG *plBottom) { LONG lScreenLeft = 0, lScreenTop = 0; HRESULT hr = E_FAIL; IHTMLRect *pRect = NULL; *plLeft = *plTop = *plRight = *plBottom = 0;
if (!pEle2) return hr;
if (SUCCEEDED(pEle2->getBoundingClientRect(&pRect)) && pRect) { LONG lLeft, lRight, lTop, lBottom;
pRect->get_left(&lLeft); pRect->get_right(&lRight); pRect->get_top(&lTop); pRect->get_bottom(&lBottom);
// if its an iframe and it scrolls past the top of the frame, we should correct a bit.
if (lTop <= 0) lTop = 0;
// dito for left side
if (lLeft <= 0) lLeft = 0; POINT pointTL, pointBR; // TL=Top,Left BR=Bottom,Right
ASSERT(m_pWin3); m_pWin3->get_screenLeft(&lScreenLeft); m_pWin3->get_screenTop(&lScreenTop);
// convert coords relative to the frame window to screen coords
pointTL.x = lScreenLeft + lLeft; pointTL.y = lScreenTop + lTop; pointBR.x = lScreenLeft + lRight; pointBR.y = lScreenTop + lBottom;
// now convert from screen coords to client coords and assign...
if (ScreenToClient(hwnd, &pointTL) && ScreenToClient(hwnd, &pointBR)) { *plLeft = pointTL.x; *plRight = pointBR.x; *plTop = pointTL.y; *plBottom = pointBR.y;
hr = S_OK; }
pRect->Release(); } return hr; }
HRESULT CMyPics::ShowHover() { HRESULT hr = S_OK; IHTMLElement2 *pEle2 = NULL; // cause we need an ele2 to get screen coords
IHTMLRect *pRect = NULL; // to get screen coords
LONG lLeft; // these are the screen coords
LONG lRight; // we get right and bottom to det size of image
LONG lTop; LONG lBottom; DWORD dwOffset;
DWORD dw; SIZE sz; RECT rc; TraceMsg(TF_MYPICS, "+CMyPics::ShowHover, this=%p, m_hoverState=%d", this, m_hoverState);
ASSERT(m_pEleCurr); ASSERT(m_Hwnd);
// get an IHTMLElement2 from the IHTMLElement cached...
hr = m_pEleCurr->QueryInterface(IID_IHTMLElement2, (void **)&pEle2); if (FAILED(hr)) goto Cleanup;
// get correct coords...
hr = GetRealCoords(pEle2, m_Hwnd, &lLeft, &lTop, &lRight, &lBottom); if (FAILED(hr)) goto Cleanup;
// adjust for offset...
dwOffset = MP_GetOffsetInfoFromRegistry(); lLeft += dwOffset; lTop += dwOffset;
// need to do some sanity checks to make sure the hover bar appears in a visible location...
RECT rcBrowserWnd; if (GetClientRect(m_Hwnd, &rcBrowserWnd)) { // check to make sure it'll appear somewhere we'll see it...
if (lLeft < rcBrowserWnd.left) lLeft = rcBrowserWnd.left + dwOffset;
if (lTop < rcBrowserWnd.top) lTop = rcBrowserWnd.top + dwOffset;
// check to make sure the entire hoverbar is over the image (so the user
// doesn't mouseout trying to get to the buttons!)
// If "galleryimg" was explicitly turned on, then bypass this code, which ensures that the entire
// toolbar will fit within the image.
if (!m_bGalleryImg) { if (lRight - lLeft < MP_MIN_CX + 10 - (LONG)dwOffset) goto Cleanup;
if (lBottom - lTop < MP_MIN_CY + 10) goto Cleanup;
// now check to make sure there is enough horiz and vert room for it to appear...
// if there isn't enough room, we just don't display it...
if ((rcBrowserWnd.right - MP_SCROLLBAR_SIZE) - lLeft < MP_MIN_CX) goto Cleanup;
if ((rcBrowserWnd.bottom - (MP_SCROLLBAR_SIZE+2)) - lTop < MP_MIN_CY) goto Cleanup; } }
dw = (DWORD)SendMessage(m_hWndMyPicsToolBar, TB_GETBUTTONSIZE, 0, 0); sz.cx = LOWORD(dw); sz.cy = HIWORD(dw); rc.left = rc.top = 0;
SendMessage(m_hWndMyPicsToolBar, TB_GETIDEALSIZE, FALSE, (LPARAM)&sz);
rc.right = sz.cx; rc.bottom = sz.cy; AdjustWindowRectEx(&rc, GetWindowLong(m_hWndHover, GWL_STYLE), FALSE, GetWindowLong(m_hWndHover, GWL_EXSTYLE));
if (SetWindowPos(m_hWndHover, NULL, lLeft, lTop, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER | SWP_SHOWWINDOW)) { m_hoverState = HOVERSTATE_SHOWING; }
Cleanup: ATOMICRELEASE(pRect); ATOMICRELEASE(pEle2);
TraceMsg(TF_MYPICS, "-CMyPics::ShowHover, this=%p, m_hoverState=%d", this, m_hoverState);
return hr; }
HRESULT CMyPics::HandleScroll() { TraceMsg(TF_MYPICS, "+CMyPics::HandleScroll, this=%p, m_hoverState=%d", this, m_hoverState);
HRESULT hr = S_OK;
switch(m_hoverState) { // I don't think we need to do anything in these cases.
//
case HOVERSTATE_HIDING: case HOVERSTATE_LOCKED: case HOVERSTATE_WAITINGTOSHOW: break;
case HOVERSTATE_SHOWING: { IHTMLElement2 *pEle2=NULL; IHTMLRect *pRect=NULL; RECT rect;
ASSERT(m_pEleCurr); ASSERT(m_Hwnd); ASSERT(m_hWndHover); // Ensure we do have a window
HideHover(); ShowHover();
// Redraw client area to get rid of window droppings scrolling causes.
// Try to redraw just the part where its likely to need it.
if (FAILED(m_pEleCurr->QueryInterface(IID_IHTMLElement2, (void **)&pEle2))) { goto CleanUp; } if (FAILED(pEle2->getBoundingClientRect(&pRect))) { goto CleanUp; } pRect->get_left(&rect.left); pRect->get_right(&rect.right); pRect->get_top(&rect.top); pRect->get_bottom(&rect.bottom);
rect.top -= 2*MP_MIN_CY; if (rect.top < 0) rect.top = 0;
rect.left -= 2*MP_MIN_CX; if (rect.left <0) rect.left = 0; rect.bottom *= 2; rect.right *= 2;
RedrawWindow(m_Hwnd, &rect, NULL, RDW_INVALIDATE | RDW_UPDATENOW); CleanUp: SAFERELEASE(pRect); SAFERELEASE(pEle2);
} break; }
TraceMsg(TF_MYPICS, "-CMyPics::HandleScroll, this=%p, m_hoverState=%d", this, m_hoverState);
return hr; }
HRESULT CMyPics::HandleMouseover(IHTMLElement *pEle) { HRESULT hr = S_OK; IOleWindow *pOleWindow;
TraceMsg(TF_MYPICS, "+CMyPics::HandleMouseover");
if (m_hoverState != HOVERSTATE_HIDING) { // Ensure we really have a hover window
ASSERT(m_hWndHover); return (S_OK); } else { // No bar. Release current element, if any.
ATOMICRELEASE(m_pEleCurr);
if (ShouldAppearOnThisElement(pEle)) { m_pEleCurr = pEle; pEle->AddRef();
// set m_Hwnd once...
if (!m_Hwnd) { // Get the Hwnd for the document...
hr = m_pDoc2->QueryInterface(IID_IOleWindow,(void **)&pOleWindow); if (FAILED(hr)) return hr;
pOleWindow->GetWindow(&m_Hwnd); pOleWindow->Release(); }
if (!m_hWndHover) { // We need a hover window now to conveniently set a timer.
hr = CreateHover(); // review: do we need to pass member variables as params?
}
// We're all set up. Set the state and start the timer.
m_hoverState=HOVERSTATE_WAITINGTOSHOW; SetTimer(m_hWndMyPicsToolBar, IDT_MP_TIMER, MP_TIMER, s_TimerProc); } }
TraceMsg(TF_MYPICS, "-CMyPics::HandleMouseover");
return hr; }
HRESULT CMyPics::HandleMouseout() { TraceMsg(TF_MYPICS, "+CMyPics::HandleMouseout");
switch(m_hoverState) { case HOVERSTATE_HIDING: // Nothing to do
break;
case HOVERSTATE_SHOWING: // Hide it
HideHover(); break;
case HOVERSTATE_LOCKED: // Noop
break;
case HOVERSTATE_WAITINGTOSHOW: m_hoverState = HOVERSTATE_HIDING; KillTimer(m_hWndMyPicsToolBar, IDT_MP_TIMER); break; }
TraceMsg(TF_MYPICS, "-CMyPics::HandleMouseout");
return S_OK; }
HRESULT CMyPics::HandleResize() { HRESULT hr = S_OK;
if (m_pEleCurr && (HOVERSTATE_SHOWING == m_hoverState)) { HideHover(); ShowHover(); }
return hr; }
HRESULT CMyPics::HandleEvent(IHTMLElement *pEle, EVENTS Event, IHTMLEventObj *pEventObj) { TraceMsg(TF_MYPICS, "CMyPics::HandleEvent Event=%ws", EventsToSink[Event].pwszEventName);
HRESULT hr = S_OK; BSTR bstrTagName = NULL; IHTMLElement *pEleUse = NULL; BOOL fWasArea = FALSE; // if this is an area tag we need to find the IMG tag that corresponds
if (pEle && SUCCEEDED(pEle->get_tagName(&bstrTagName))) { // if its an area tag, we need to find the img tag associated with it...
if (StrCmpNI(bstrTagName, TEXT("area"), 4)==0) { POINT ptEvent;
if (FAILED(pEventObj->get_screenX(&ptEvent.x)) || FAILED(pEventObj->get_screenY(&ptEvent.y))) { hr = E_FAIL; goto Cleanup; }
fWasArea = TRUE; pEleUse = GetIMGFromArea(pEle, ptEvent); } }
// has the user turned this off?
if (m_bIsOffForSession) goto Cleanup;
switch(Event) { case EVENT_SCROLL: HandleScroll(); break;
case EVENT_MOUSEOVER: hr = HandleMouseover(fWasArea ? pEleUse : pEle); break;
case EVENT_MOUSEOUT: hr = HandleMouseout(); break;
case EVENT_RESIZE: hr = HandleResize(); break;
default: //do nothing?
break; }
Cleanup: if (pEleUse) ATOMICRELEASE(pEleUse);
if (bstrTagName) SysFreeString(bstrTagName);
return (hr); }
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
// this is stolen from iforms.cpp:
//=========================================================================
//
// Event sinking class
//
// We simply implement IDispatch and make a call into our parent when
// we receive a sinked event.
//
//=========================================================================
CMyPics::CEventSink::CEventSink(CMyPicsEventSinkCallback *pParent) { TraceMsg(TF_MYPICS, "CMyPics::CEventSink::CEventSink"); DllAddRef(); m_cRef = 1; m_pParent = pParent; }
CMyPics::CEventSink::~CEventSink() { TraceMsg(TF_MYPICS, "CMyPics::CEventSink::~CEventSink"); ASSERT( m_cRef == 0 ); DllRelease(); }
STDMETHODIMP CMyPics::CEventSink::QueryInterface(REFIID riid, void **ppv) { *ppv = NULL;
if ((IID_IDispatch == riid) || (IID_IUnknown == riid)) { *ppv = (IDispatch *)this; }
if (NULL != *ppv) { ((IUnknown *)*ppv)->AddRef(); return S_OK; }
return E_NOINTERFACE; }
STDMETHODIMP_(ULONG) CMyPics::CEventSink::AddRef(void) { return ++m_cRef; }
STDMETHODIMP_(ULONG) CMyPics::CEventSink::Release(void) { if (--m_cRef == 0) { delete this; return 0; }
return m_cRef; }
HRESULT CMyPics::CEventSink::SinkEvents(IHTMLElement2 *pEle2, int iNum, EVENTS *pEvents) { VARIANT_BOOL bSuccess = VARIANT_TRUE;
for (int i=0; i<iNum; i++) { BSTR bstrEvent = SysAllocString(CMyPicsEventSinkCallback::EventsToSink[(int)(pEvents[i])].pwszEventSubscribe);
if (bstrEvent) { pEle2->attachEvent(bstrEvent, (IDispatch *)this, &bSuccess);
SysFreeString(bstrEvent); } else { bSuccess = VARIANT_FALSE; }
if (!bSuccess) break; }
return (bSuccess) ? S_OK : E_FAIL; }
HRESULT CMyPics::CEventSink::SinkEvents(IHTMLWindow3 *pWin3, int iNum, EVENTS *pEvents) { VARIANT_BOOL bSuccess = VARIANT_TRUE;
for (int i=0; i<iNum; i++) { BSTR bstrEvent = SysAllocString(CMyPicsEventSinkCallback::EventsToSink[(int)(pEvents[i])].pwszEventSubscribe);
if (bstrEvent) { pWin3->attachEvent(bstrEvent, (IDispatch *)this, &bSuccess);
SysFreeString(bstrEvent); } else { bSuccess = VARIANT_FALSE; }
if (!bSuccess) break; }
return (bSuccess) ? S_OK : E_FAIL; }
HRESULT CMyPics::CEventSink::UnSinkEvents(IHTMLElement2 *pEle2, int iNum, EVENTS *pEvents) { for (int i=0; i<iNum; i++) { BSTR bstrEvent = SysAllocString(CMyPicsEventSinkCallback::EventsToSink[(int)(pEvents[i])].pwszEventSubscribe);
if (bstrEvent) { pEle2->detachEvent(bstrEvent, (IDispatch *)this);
SysFreeString(bstrEvent); } }
return S_OK; }
HRESULT CMyPics::CEventSink::UnSinkEvents(IHTMLWindow3 *pWin3, int iNum, EVENTS *pEvents) { for (int i=0; i<iNum; i++) { BSTR bstrEvent = SysAllocString(CMyPicsEventSinkCallback::EventsToSink[(int)(pEvents[i])].pwszEventSubscribe);
if (bstrEvent) { pWin3->detachEvent(bstrEvent, (IDispatch *)this);
SysFreeString(bstrEvent); } }
return S_OK; }
// IDispatch
STDMETHODIMP CMyPics::CEventSink::GetTypeInfoCount(UINT* /*pctinfo*/) { return E_NOTIMPL; }
STDMETHODIMP CMyPics::CEventSink::GetTypeInfo(/* [in] */ UINT /*iTInfo*/, /* [in] */ LCID /*lcid*/, /* [out] */ ITypeInfo** /*ppTInfo*/) { return E_NOTIMPL; }
STDMETHODIMP CMyPics::CEventSink::GetIDsOfNames( REFIID riid, OLECHAR** rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) { return E_NOTIMPL; }
STDMETHODIMP CMyPics::CEventSink::Invoke( DISPID dispIdMember, REFIID, LCID, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO*, UINT* puArgErr) { if (m_pParent && pDispParams && pDispParams->cArgs>=1) { if (pDispParams->rgvarg[0].vt == VT_DISPATCH) { IHTMLEventObj *pObj=NULL;
if (SUCCEEDED(pDispParams->rgvarg[0].pdispVal->QueryInterface(IID_IHTMLEventObj, (void **)&pObj) && pObj)) { EVENTS Event=EVENT_BOGUS; BSTR bstrEvent=NULL;
pObj->get_type(&bstrEvent);
if (bstrEvent) { for (int i=0; i<ARRAYSIZE(CMyPicsEventSinkCallback::EventsToSink); i++) { if (!StrCmpCW(bstrEvent, CMyPicsEventSinkCallback::EventsToSink[i].pwszEventName)) { Event = (EVENTS) i; break; } }
SysFreeString(bstrEvent); }
if (Event != EVENT_BOGUS) { IHTMLElement *pEle=NULL;
pObj->get_srcElement(&pEle);
// EVENT_SCROLL comes from our window so we won't have an
// element for it
if (pEle || (Event == EVENT_SCROLL)) { // Call the event handler here
m_pParent->HandleEvent(pEle, Event, pObj);
if (pEle) { pEle->Release(); } } }
pObj->Release(); } } }
return S_OK; }
//////////////////////////////////////////////////////////////////////////////
// {9E56BE60-C50F-11CF-9A2C-00A0C90A90CE}
EXTERN_C const GUID MP_CLSID_MailRecipient = {0x9E56BE60L, 0xC50F, 0x11CF, 0x9A, 0x2C, 0x00, 0xA0, 0xC9, 0x0A, 0x90, 0xCE};
HRESULT DropPicOnMailRecipient(IDataObject *pdtobj, DWORD grfKeyState) { IDropTarget *pdrop; HRESULT hres = CoCreateInstance(MP_CLSID_MailRecipient, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_PPV_ARG(IDropTarget, &pdrop));
if (SUCCEEDED(hres)) { hres = SHSimulateDrop(pdrop, pdtobj, grfKeyState, NULL, NULL); pdrop->Release(); } return hres; }
//
// This function cannot return Non -NULL pointers if
// it returns a FAILED(hr)
//
HRESULT CreateShortcutSetSiteAndGetDataObjectIfPIDLIsNetUrl( LPCITEMIDLIST pidl, IUnknown *pUnkSite, IUniformResourceLocator **ppUrlOut, IDataObject **ppdtobj ) { HRESULT hr; TCHAR szUrl[MAX_URL_STRING]; TCHAR *szTemp = NULL;
ASSERT(ppUrlOut); ASSERT(ppdtobj); *ppUrlOut = NULL; *ppdtobj = NULL; szUrl[0] = TEXT('\0');
hr = IEGetNameAndFlags(pidl, SHGDN_FORPARSING, szUrl, SIZECHARS(szUrl), NULL);
if ((S_OK == hr) && (*szUrl)) {
BOOL fIsHTML = FALSE; BOOL fHitsNet = UrlHitsNetW(szUrl);
if (!fHitsNet) { if (URL_SCHEME_FILE == GetUrlScheme(szUrl)) { TCHAR *szExt = PathFindExtension(szUrl); if (szExt) { fIsHTML = ((0 == StrCmpNI(szExt, TEXT(".htm"),4)) || (0 == StrCmpNI(szExt, TEXT(".html"),5))); } } }
if (fHitsNet || fIsHTML) { // Create a shortcut object and
HRESULT hr = CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUniformResourceLocator, ppUrlOut)); if (SUCCEEDED(hr)) {
hr = (*ppUrlOut)->SetURL(szUrl, 0); if (S_OK == hr) {
// Get the IDataObject and send that back for the Drag Drop
hr = (*ppUrlOut)->QueryInterface(IID_PPV_ARG(IDataObject, ppdtobj)); if (SUCCEEDED(hr)) { IUnknown_SetSite(*ppUrlOut, pUnkSite); // Only set the site if we're sure of
// returning SUCCESS
} } } } else { hr = E_FAIL; } }
if (FAILED(hr)) { SAFERELEASE(*ppUrlOut); SAFERELEASE(*ppdtobj); } return hr; }
HRESULT SendDocToMailRecipient(LPCITEMIDLIST pidl, UINT uiCodePage, DWORD grfKeyState, IUnknown *pUnkSite) { IDataObject *pdtobj = NULL; IUniformResourceLocator *purl = NULL; HRESULT hr = CreateShortcutSetSiteAndGetDataObjectIfPIDLIsNetUrl(pidl, pUnkSite, &purl, &pdtobj); if (FAILED(hr)) { ASSERT(NULL == pdtobj); ASSERT(NULL == purl); hr = GetDataObjectForPidl(pidl, &pdtobj); }
if (SUCCEEDED(hr)) { IQueryCodePage * pQcp; if (SUCCEEDED(pdtobj->QueryInterface(IID_PPV_ARG(IQueryCodePage, &pQcp)))) { pQcp->SetCodePage(uiCodePage); pQcp->Release(); } hr = DropPicOnMailRecipient(pdtobj, grfKeyState); pdtobj->Release(); }
if (purl) { IUnknown_SetSite(purl, NULL); purl->Release(); } return hr; }
//////////////////////////////////////////////////////////////////////////////
#undef TF_MYPICS
|