#include "precomp.h" #pragma hdrstop #include "prevwnd.h" #include DWORD g_dwThreadID = 0; class CAutoplayForSlideShow : public IHWEventHandler, public IDropTarget, public NonATLObject { public: CAutoplayForSlideShow() : _cRef(1) {} // IUnknown STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); // IHWEventHandler STDMETHOD(Initialize)(LPCWSTR pszParams); STDMETHOD(HandleEvent)(LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID, LPCWSTR pszEventType); STDMETHOD(HandleEventWithContent)(LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID, LPCWSTR pszEventType, LPCWSTR pszContentTypeHandler, IDataObject* pdtobj); // IDropTarget *** STDMETHODIMP DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); STDMETHODIMP DragLeave(void); STDMETHODIMP Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); private: LONG _cRef; }; STDMETHODIMP CAutoplayForSlideShow::QueryInterface(REFIID riid, void **ppv) { static const QITAB qit[] = { QITABENT(CAutoplayForSlideShow, IHWEventHandler), QITABENT(CAutoplayForSlideShow, IDropTarget), { 0 }, }; return QISearch(this, qit, riid, ppv); } STDMETHODIMP_(ULONG) CAutoplayForSlideShow::AddRef() { return InterlockedIncrement(&_cRef); } STDMETHODIMP_(ULONG) CAutoplayForSlideShow::Release() { ASSERT( 0 != _cRef ); ULONG cRef = InterlockedDecrement(&_cRef); if ( 0 == cRef ) { delete this; } return cRef; } STDAPI CAutoplayForSlideShow_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi) { CAutoplayForSlideShow* pass = new CAutoplayForSlideShow(); if (!pass) { *ppunk = NULL; // incase of failure return E_OUTOFMEMORY; } HRESULT hr = pass->QueryInterface(IID_PPV_ARG(IUnknown, ppunk)); pass->Release(); return hr; } STDMETHODIMP CAutoplayForSlideShow::Initialize(LPCWSTR) { // We don't care about params a this point return S_OK; } STDMETHODIMP CAutoplayForSlideShow::HandleEvent(LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID, LPCWSTR pszEventType) { return E_NOTIMPL; } DWORD WINAPI SlideShowThread(void* pv) { IStream *pstm = (IStream *)pv; IDataObject* pdtobj; HRESULT hr = CoGetInterfaceAndReleaseStream(pstm, IID_PPV_ARG(IDataObject, &pdtobj)); if (SUCCEEDED(hr)) { CPreviewWnd cwndPreview; hr = cwndPreview.Initialize(NULL, SLIDESHOW_MODE, TRUE); if (SUCCEEDED(hr)) { // 4 is the walk depth, make sure we pick up pictures if (cwndPreview.CreateSlideshowWindow(4)) { hr = cwndPreview.StartSlideShow(pdtobj); if (SUCCEEDED(hr)) { MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } ::PostThreadMessage(g_dwThreadID, WM_QUIT, 0, 0); } } else { hr = E_FAIL; } } pdtobj->Release(); } return hr; } HRESULT _StartSlideShowThread(IDataObject *pdo) { IStream *pstm; HRESULT hr = CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pdo, &pstm); if (SUCCEEDED(hr)) { // maybe do threadref? if (!SHCreateThread(SlideShowThread, pstm, CTF_COINIT, NULL)) { pstm->Release(); hr = E_FAIL; } } return hr; } STDMETHODIMP CAutoplayForSlideShow::HandleEventWithContent( LPCWSTR pszDeviceID, LPCWSTR pszAltDeviceID, LPCWSTR pszEventType, LPCWSTR pszContentTypeHandler, IDataObject* pdtobj) { return _StartSlideShowThread(pdtobj); } // IDropTarget::DragEnter HRESULT CAutoplayForSlideShow::DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect) { *pdwEffect = DROPEFFECT_COPY; return S_OK;; } // IDropTarget::DragOver HRESULT CAutoplayForSlideShow::DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect) { *pdwEffect = DROPEFFECT_COPY; return S_OK;; } // IDropTarget::DragLeave HRESULT CAutoplayForSlideShow::DragLeave(void) { return S_OK; } // IDropTarget::DragDrop HRESULT CAutoplayForSlideShow::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { *pdwEffect = DROPEFFECT_COPY; return _StartSlideShowThread(pdtobj); } void WINAPI ImageView_COMServer(HWND hwnd, HINSTANCE hAppInstance, LPTSTR pszCmdLine, int nCmdShow) { HRESULT hrOle = SHCoInitialize(); if (SUCCEEDED(hrOle)) { g_dwThreadID = GetCurrentThreadId(); IUnknown* punkFact; // the preview window will init GDI+ HRESULT hr = DllGetClassObject(CLSID_AutoplayForSlideShow, IID_PPV_ARG(IUnknown, &punkFact)); if (SUCCEEDED(hr)) { DWORD dwROC; hr = CoRegisterClassObject(CLSID_AutoplayForSlideShow, punkFact, CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &dwROC); if (SUCCEEDED(hr)) { MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } CoRevokeClassObject(dwROC); } punkFact->Release(); } SHCoUninitialize(hrOle); } }