]> git.sesse.net Git - vlc/blob - activex/dataobject.cpp
Improved compatibility
[vlc] / activex / dataobject.cpp
1 /*****************************************************************************
2  * viewobject.cpp: ActiveX control for VLC
3  *****************************************************************************
4  * Copyright (C) 2005 VideoLAN
5  *
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 #include "plugin.h"
24 #include "dataobject.h"
25
26 #include "utils.h"
27
28 using namespace std;
29
30 ////////////////////////////////////////////////////////////////////////////////////////////////
31
32 class VLCEnumFORMATETC : public IEnumFORMATETC
33 {
34 public:
35
36     VLCEnumFORMATETC(vector<FORMATETC> &v) :
37         e(VLCEnum<FORMATETC>(IID_IEnumFORMATETC, v)) {};
38
39     VLCEnumFORMATETC(const VLCEnumFORMATETC &vlcEnum) : e(vlcEnum.e) {};
40     virtual ~VLCEnumFORMATETC() {};
41
42     // IUnknown methods
43     STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
44         { return e.QueryInterface(riid, ppv); };
45     STDMETHODIMP_(ULONG) AddRef(void)
46         { return e.AddRef(); };
47     STDMETHODIMP_(ULONG) Release(void)
48         {return e.Release(); };
49
50     //IEnumConnectionPoints
51     STDMETHODIMP Next(ULONG celt, LPFORMATETC rgelt, ULONG *pceltFetched)
52         { return e.Next(celt, rgelt, pceltFetched); };
53     STDMETHODIMP Skip(ULONG celt)
54         { return e.Skip(celt);};
55     STDMETHODIMP Reset(void)
56         { return e.Reset();};
57     STDMETHODIMP Clone(LPENUMFORMATETC *ppenum)
58         { if( NULL == ppenum ) return E_POINTER;
59           *ppenum = dynamic_cast<LPENUMFORMATETC>(new VLCEnumFORMATETC(*this));
60           return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
61         };
62
63 private:
64
65     VLCEnum<FORMATETC> e;
66 };
67
68 ////////////////////////////////////////////////////////////////////////////////////////////////
69
70 static const FORMATETC _metaFileFormatEtc =
71     {
72         CF_METAFILEPICT,
73         NULL,
74         DVASPECT_CONTENT,
75         -1,
76         TYMED_MFPICT,
77     };
78 static const FORMATETC _enhMetaFileFormatEtc =
79     {
80         CF_ENHMETAFILE,
81         NULL,
82         DVASPECT_CONTENT,
83         -1,
84         TYMED_ENHMF,
85     };
86
87 VLCDataObject::VLCDataObject(VLCPlugin *p_instance) : _p_instance(p_instance)
88 {
89     _v_formatEtc.push_back(_enhMetaFileFormatEtc);
90     _v_formatEtc.push_back(_metaFileFormatEtc);
91     CreateDataAdviseHolder(&_p_adviseHolder);
92 };
93
94 VLCDataObject::~VLCDataObject()
95 {
96     _p_adviseHolder->Release();
97 };
98
99 ////////////////////////////////////////////////////////////////////////////////////////////////
100
101 STDMETHODIMP VLCDataObject::DAdvise(LPFORMATETC pFormatEtc, DWORD padvf, LPADVISESINK pAdviseSink, LPDWORD pdwConnection)
102 {
103     return _p_adviseHolder->Advise(this,
104             pFormatEtc, padvf,pAdviseSink, pdwConnection);
105 };
106
107 STDMETHODIMP VLCDataObject::DUnadvise(DWORD dwConnection)
108 {
109     return _p_adviseHolder->Unadvise(dwConnection);
110 };
111
112 STDMETHODIMP VLCDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
113 {
114     return _p_adviseHolder->EnumAdvise(ppenumAdvise);
115 };
116
117 STDMETHODIMP VLCDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumformatetc)
118 {
119     if( NULL == ppenumformatetc )
120         return E_POINTER;
121
122     *ppenumformatetc = new VLCEnumFORMATETC(_v_formatEtc);
123     return NOERROR;
124 };
125
126 STDMETHODIMP VLCDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatEtcIn, LPFORMATETC pFormatEtcOut)
127 {
128     HRESULT result = QueryGetData(pFormatEtcIn);
129     if( FAILED(result) )
130         return result;
131
132     if( NULL == pFormatEtcOut )
133         return E_POINTER;
134
135     *pFormatEtcOut = *pFormatEtcIn;
136     pFormatEtcOut->ptd = NULL;
137
138     return DATA_S_SAMEFORMATETC;
139 };
140
141 STDMETHODIMP VLCDataObject::GetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
142 {
143     if( NULL == pMedium )
144         return E_POINTER;
145
146     HRESULT result = QueryGetData(pFormatEtc);
147     if( SUCCEEDED(result) )
148     {
149         switch( pFormatEtc->cfFormat )
150         {
151             case CF_METAFILEPICT:
152                 pMedium->tymed = TYMED_MFPICT;
153                 pMedium->hMetaFilePict = NULL;
154                 pMedium->pUnkForRelease = NULL;
155                 result = getMetaFileData(pFormatEtc, pMedium);
156                 break;
157             case CF_ENHMETAFILE:
158                 pMedium->tymed = TYMED_ENHMF;
159                 pMedium->hEnhMetaFile = NULL;
160                 pMedium->pUnkForRelease = NULL;
161                 result = getEnhMetaFileData(pFormatEtc, pMedium);
162                 break;
163             default:
164                 result = DV_E_FORMATETC;
165         }
166     }
167     return result;
168 };
169
170 STDMETHODIMP VLCDataObject::GetDataHere(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
171 {
172     if( NULL == pMedium )
173         return E_POINTER;
174
175     return E_NOTIMPL;
176 }
177
178 ////////////////////////////////////////////////////////////////////////////////////////////////
179
180 HRESULT VLCDataObject::getMetaFileData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
181 {
182     HDC hicTargetDev = CreateDevDC(pFormatEtc->ptd);
183     if( NULL == hicTargetDev )
184         return E_FAIL;
185
186     HDC hdcMeta = CreateMetaFile(NULL); 
187     if( NULL != hdcMeta )
188     {
189         LPMETAFILEPICT pMetaFilePict = (LPMETAFILEPICT)CoTaskMemAlloc(sizeof(METAFILEPICT));
190         if( NULL != pMetaFilePict )
191         {
192             SIZEL size = _p_instance->getExtent();
193             RECTL wBounds = { 0L, 0L, size.cx, size.cy };
194
195             LONG width = size.cx*GetDeviceCaps(hicTargetDev, LOGPIXELSX)/2540L;
196             LONG height = size.cy*GetDeviceCaps(hicTargetDev, LOGPIXELSY)/2540L;
197
198             pMetaFilePict->mm   = MM_ANISOTROPIC;
199             pMetaFilePict->xExt = size.cx;
200             pMetaFilePict->yExt = size.cy;
201
202             SetMapMode(hdcMeta, MM_ANISOTROPIC);
203             SetWindowOrgEx(hdcMeta, 0, 0, NULL);
204             SetWindowExtEx(hdcMeta, width, height, NULL);
205
206             RECTL bounds = { 0L, 0L, width, height };
207
208             _p_instance->onDraw(pFormatEtc->ptd, hicTargetDev, hdcMeta, &bounds, &wBounds);
209             pMetaFilePict->hMF = CloseMetaFile(hdcMeta);
210             if( NULL != pMetaFilePict->hMF )
211                 pMedium->hMetaFilePict = pMetaFilePict;
212             else
213                 CoTaskMemFree(pMetaFilePict);
214         }
215     }
216     DeleteDC(hicTargetDev);
217     return (NULL != pMedium->hMetaFilePict) ? S_OK : E_FAIL;
218 };
219
220 HRESULT VLCDataObject::getEnhMetaFileData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
221 {
222     HDC hicTargetDev = CreateDevDC(pFormatEtc->ptd);
223     if( NULL == hicTargetDev )
224         return E_FAIL;
225
226     SIZEL size = _p_instance->getExtent();
227
228     HDC hdcMeta = CreateEnhMetaFile(hicTargetDev, NULL, NULL, NULL); 
229     if( NULL != hdcMeta )
230     {
231         RECTL wBounds = { 0L, 0L, size.cx, size.cy };
232
233         LONG width = size.cx*GetDeviceCaps(hicTargetDev, LOGPIXELSX)/2540L;
234         LONG height = size.cy*GetDeviceCaps(hicTargetDev, LOGPIXELSY)/2540L;
235
236         RECTL bounds = { 0L, 0L, width, height };
237
238         _p_instance->onDraw(pFormatEtc->ptd, hicTargetDev, hdcMeta, &bounds, &wBounds);
239         pMedium->hEnhMetaFile = CloseEnhMetaFile(hdcMeta);
240     }
241     DeleteDC(hicTargetDev);
242
243     return (NULL != pMedium->hEnhMetaFile) ? S_OK : E_FAIL;
244 };
245
246 STDMETHODIMP VLCDataObject::QueryGetData(LPFORMATETC pFormatEtc)
247 {
248     if( NULL == pFormatEtc )
249         return E_POINTER;
250
251     const FORMATETC *formatEtc;
252
253     switch( pFormatEtc->cfFormat )
254     {
255         case CF_METAFILEPICT:
256             formatEtc = &_metaFileFormatEtc;
257             break;
258         case CF_ENHMETAFILE:
259             formatEtc = &_enhMetaFileFormatEtc;
260             break;
261         default:
262             return DV_E_FORMATETC;
263     }
264     
265     if( pFormatEtc->dwAspect != formatEtc->dwAspect )
266         return DV_E_DVASPECT;
267
268     if( pFormatEtc->lindex != formatEtc->lindex )
269         return DV_E_LINDEX;
270
271     if( pFormatEtc->tymed != formatEtc->tymed )
272         return DV_E_TYMED;
273
274     return S_OK;
275 };
276
277 STDMETHODIMP VLCDataObject::SetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease)
278 {
279     return E_NOTIMPL;
280 };
281
282 void VLCDataObject::onClose(void)
283 {
284     _p_adviseHolder->SendOnDataChange(this, 0, ADVF_DATAONSTOP);
285     if( S_OK == OleIsCurrentClipboard(dynamic_cast<LPDATAOBJECT>(this)) )
286         OleFlushClipboard();
287 };
288