]> git.sesse.net Git - vlc/blob - activex/oleobject.cpp
Improved compatibility
[vlc] / activex / oleobject.cpp
1 /*****************************************************************************
2  * oleobject.cpp: ActiveX control for VLC
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
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 "oleobject.h"
25
26 #include "utils.h"
27
28 #include <docobj.h>
29
30 using namespace std;
31
32 VLCOleObject::VLCOleObject(VLCPlugin *p_instance) :
33 _p_clientsite(NULL), _p_instance(p_instance) 
34 {
35     CreateOleAdviseHolder(&_p_advise_holder);
36 };
37
38 VLCOleObject::~VLCOleObject()
39 {
40     _p_advise_holder->Release();
41     SetClientSite(NULL); 
42 };
43
44 STDMETHODIMP VLCOleObject::Advise(IAdviseSink *pAdvSink, DWORD *dwConnection)
45 {
46     return _p_advise_holder->Advise(pAdvSink, dwConnection);
47 };
48
49 STDMETHODIMP VLCOleObject::Close(DWORD dwSaveOption)
50 {
51     _p_advise_holder->SendOnClose();
52     return _p_instance->onClose(dwSaveOption);
53 };
54
55 STDMETHODIMP VLCOleObject::DoVerb(LONG iVerb, LPMSG lpMsg, LPOLECLIENTSITE pActiveSite,
56                                     LONG lIndex, HWND hwndParent, LPCRECT lprcPosRect)
57 {
58     switch( iVerb )
59     {
60         case OLEIVERB_PRIMARY:
61         case OLEIVERB_SHOW:
62         case OLEIVERB_OPEN:
63             // force control to be visible when activating in place
64             _p_instance->setVisible(TRUE);
65         case OLEIVERB_INPLACEACTIVATE:
66             return doInPlaceActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
67
68         case OLEIVERB_HIDE:
69             _p_instance->setVisible(FALSE);
70             return S_OK;
71
72         case OLEIVERB_UIACTIVATE:
73             return doUIActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
74
75         case OLEIVERB_DISCARDUNDOSTATE:
76             return S_OK;
77
78         default:
79             if( iVerb > 0 ) {
80                 _p_instance->setVisible(TRUE);
81                 doInPlaceActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
82                 return OLEOBJ_S_INVALIDVERB;
83             }
84             return E_NOTIMPL;
85     }
86 };
87
88 HRESULT VLCOleObject::doInPlaceActivate(LPMSG lpMsg, LPOLECLIENTSITE pActiveSite, HWND hwndParent, LPCRECT lprcPosRect)
89 {
90     RECT posRect;
91     RECT clipRect;
92     LPCRECT lprcClipRect = lprcPosRect;
93
94     if( NULL != pActiveSite )
95     {
96         // check if already activated
97         if( _p_instance->isInPlaceActive() )
98         {
99             // just attempt to show object then
100             if( _p_instance->getVisible() )
101                 pActiveSite->ShowObject();
102             return S_OK;
103         }
104
105         LPOLEINPLACESITE p_inPlaceSite;
106
107         if( SUCCEEDED(pActiveSite->QueryInterface(IID_IOleInPlaceSite, (void**)&p_inPlaceSite)) )
108         {
109             if( S_OK != p_inPlaceSite->CanInPlaceActivate() )
110             {
111                 return OLEOBJ_S_CANNOT_DOVERB_NOW;
112             }
113
114             LPOLEINPLACEFRAME p_inPlaceFrame;
115             LPOLEINPLACEUIWINDOW p_inPlaceUIWindow;
116             OLEINPLACEFRAMEINFO oleFrameInfo;
117
118             if( SUCCEEDED(p_inPlaceSite->GetWindowContext(&p_inPlaceFrame, &p_inPlaceUIWindow, &posRect, &clipRect, &oleFrameInfo)) )
119             {
120                 lprcPosRect = &posRect;
121                 lprcClipRect = &clipRect;
122
123                 if( NULL != p_inPlaceFrame )
124                     p_inPlaceFrame->Release();
125                 if( NULL != p_inPlaceUIWindow )
126                     p_inPlaceUIWindow->Release();
127             }
128
129             if( (NULL == hwndParent) && FAILED(p_inPlaceSite->GetWindow(&hwndParent)) )
130             {
131                 p_inPlaceSite->Release();
132                 return OLEOBJ_S_INVALIDHWND;
133             }
134         }
135         else if( NULL == hwndParent )
136         {
137             return OLEOBJ_S_INVALIDHWND;
138         }
139
140         if( FAILED(_p_instance->onActivateInPlace(lpMsg, hwndParent, lprcPosRect, lprcClipRect)) )
141         {
142             if( NULL != p_inPlaceSite )
143                 p_inPlaceSite->Release();
144             return OLEOBJ_S_CANNOT_DOVERB_NOW;
145         }
146
147         if( NULL != p_inPlaceSite )
148             p_inPlaceSite->OnPosRectChange(lprcPosRect);
149
150         pActiveSite->ShowObject();
151         _p_instance->setVisible(TRUE);
152
153         if( NULL != p_inPlaceSite )
154         {
155             p_inPlaceSite->OnInPlaceActivate();
156             p_inPlaceSite->Release();
157         }
158
159         if( NULL != lpMsg )
160         {
161             switch( lpMsg->message )
162             {
163                 case WM_LBUTTONDOWN:
164                 case WM_LBUTTONDBLCLK:
165                     doUIActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
166                     break;
167                 default:
168                     break;
169             }
170         }
171         return S_OK;
172     }
173     return OLEOBJ_S_CANNOT_DOVERB_NOW;
174 };
175
176 HRESULT VLCOleObject::doUIActivate(LPMSG lpMsg, LPOLECLIENTSITE pActiveSite, HWND hwndParent, LPCRECT lprcPosRect)
177 {
178     if( NULL != pActiveSite )
179     {
180         // check if already activated
181         if( ! _p_instance->isInPlaceActive() )
182             return OLE_E_NOT_INPLACEACTIVE;
183
184         LPOLEINPLACESITE p_inPlaceSite;
185
186         if( SUCCEEDED(pActiveSite->QueryInterface(IID_IOleInPlaceSite, (void**)&p_inPlaceSite)) )
187         {
188             p_inPlaceSite->OnUIActivate();
189
190             if( NULL != lprcPosRect )
191             {
192                 p_inPlaceSite->OnPosRectChange(lprcPosRect);
193             }
194             p_inPlaceSite->Release();
195         }
196
197         pActiveSite->ShowObject();
198         _p_instance->setVisible(TRUE);
199         _p_instance->setFocus(TRUE);
200
201         return S_OK;
202     }
203     return E_FAIL;
204 };
205
206 STDMETHODIMP VLCOleObject::EnumAdvise(IEnumSTATDATA **ppEnumAdvise)
207 {
208     return _p_advise_holder->EnumAdvise(ppEnumAdvise);
209 };
210
211 STDMETHODIMP VLCOleObject::EnumVerbs(IEnumOleVerb **ppEnumOleVerb)
212 {
213     return OleRegEnumVerbs(_p_instance->getClassID(),
214         ppEnumOleVerb);
215 };
216
217 STDMETHODIMP VLCOleObject::GetClientSite(LPOLECLIENTSITE *ppClientSite)
218 {
219     if( NULL == ppClientSite )
220         return E_POINTER;
221  
222     if( NULL != _p_clientsite )
223         _p_clientsite->AddRef(); 
224
225     *ppClientSite = _p_clientsite;
226     return S_OK;
227 };
228
229 STDMETHODIMP VLCOleObject::GetClipboardData(DWORD dwReserved, LPDATAOBJECT *ppDataObject)
230 {
231     return _p_instance->pUnkOuter->QueryInterface(IID_IDataObject, (void **)ppDataObject);
232 };
233
234 STDMETHODIMP VLCOleObject::GetExtent(DWORD dwDrawAspect, SIZEL *pSizel)
235 {
236     if( NULL == pSizel )
237         return E_POINTER;
238
239     if( dwDrawAspect & DVASPECT_CONTENT )
240     {
241         *pSizel = _p_instance->getExtent();
242         return S_OK;
243     }
244     pSizel->cx= 0L;
245     pSizel->cy= 0L;
246     return E_NOTIMPL;
247 };
248
249 STDMETHODIMP VLCOleObject::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus)
250 {
251     if( NULL == pdwStatus )
252         return E_POINTER;
253
254     switch( dwAspect )
255     {
256         case DVASPECT_CONTENT:
257             *pdwStatus = OLEMISC_RECOMPOSEONRESIZE
258                 | OLEMISC_CANTLINKINSIDE
259                 | OLEMISC_INSIDEOUT
260                 | OLEMISC_ACTIVATEWHENVISIBLE
261                 | OLEMISC_SETCLIENTSITEFIRST;
262             break;
263         default:
264             *pdwStatus = 0;
265     }
266
267     return S_OK;
268 };
269
270 STDMETHODIMP VLCOleObject::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER *ppMoniker)
271 {
272     if( NULL != _p_clientsite )
273         return _p_clientsite->GetMoniker(dwAssign,dwWhichMoniker, ppMoniker);
274  
275     return E_UNEXPECTED;
276 };
277
278 STDMETHODIMP VLCOleObject::GetUserClassID(LPCLSID pClsid)
279 {
280     if( NULL == pClsid )
281         return E_POINTER;
282  
283     *pClsid = _p_instance->getClassID(); 
284     return S_OK;
285 };
286
287 STDMETHODIMP VLCOleObject::GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType)
288 {
289     return OleRegGetUserType(_p_instance->getClassID(),
290         dwFormOfType, pszUserType);
291 };
292
293 STDMETHODIMP VLCOleObject::InitFromData(LPDATAOBJECT pDataObject, BOOL fCreation, DWORD dwReserved)
294 {
295     return E_NOTIMPL;
296 };
297
298 STDMETHODIMP VLCOleObject::IsUpToDate(void)
299 {
300     return S_OK;
301 };
302
303 STDMETHODIMP VLCOleObject::SetClientSite(LPOLECLIENTSITE pClientSite)
304 {
305     if( NULL != pClientSite )
306     {
307         pClientSite->AddRef();
308
309         /*
310         ** retrieve container ambient properties
311         */
312         VARIANT v;
313         VariantInit(&v);
314         V_VT(&v) = VT_I4;
315         if( SUCCEEDED(GetObjectProperty(pClientSite, DISPID_AMBIENT_CODEPAGE, v)) )
316         {
317             _p_instance->setCodePage(V_I4(&v));
318             VariantClear(&v);
319         }
320     }
321
322     if( NULL != _p_clientsite )
323         _p_clientsite->Release();
324
325     _p_clientsite = pClientSite;
326     _p_instance->onClientSiteChanged(pClientSite);
327
328     return S_OK;
329 };
330
331 STDMETHODIMP VLCOleObject::SetColorScheme(LOGPALETTE *pLogpal)
332 {
333     return E_NOTIMPL;
334 };
335
336 STDMETHODIMP VLCOleObject::SetExtent(DWORD dwDrawAspect, SIZEL *pSizel)
337 {
338     if( NULL == pSizel )
339         return E_POINTER;
340
341     if( dwDrawAspect & DVASPECT_CONTENT )
342     {
343         _p_instance->setExtent(*pSizel);
344
345         if( _p_instance->isInPlaceActive() )
346         {
347             LPOLEINPLACESITE p_inPlaceSite;
348
349             if( SUCCEEDED(_p_clientsite->QueryInterface(IID_IOleInPlaceSite, (void**)&p_inPlaceSite)) )
350             {
351                 HWND hwnd;
352
353                 if( SUCCEEDED(p_inPlaceSite->GetWindow(&hwnd)) )
354                 {
355                     // use HIMETRIC to pixel transform 
356                     RECT posRect = _p_instance->getPosRect();
357                     HDC hDC = GetDC(hwnd);
358                     posRect.right = (pSizel->cx*GetDeviceCaps(hDC, LOGPIXELSX)/2540L)+posRect.left;
359                     posRect.bottom = (pSizel->cy*GetDeviceCaps(hDC, LOGPIXELSY)/2540L)+posRect.top;
360                     DeleteDC(hDC);
361                     p_inPlaceSite->OnPosRectChange(&posRect);
362                 }
363                 p_inPlaceSite->Release();
364             }
365         }
366         return S_OK;
367     }
368     return E_NOTIMPL;
369 };
370
371 STDMETHODIMP VLCOleObject::SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
372 {
373     return S_OK;
374 };
375
376 STDMETHODIMP VLCOleObject::SetMoniker(DWORD dwWhichMoniker, LPMONIKER pMoniker)
377 {
378     return _p_advise_holder->SendOnRename(pMoniker);
379 };
380
381 STDMETHODIMP VLCOleObject::Unadvise(DWORD dwConnection)
382 {
383     return _p_advise_holder->Unadvise(dwConnection);
384 };
385
386 STDMETHODIMP VLCOleObject::Update(void)
387 {
388     return S_OK;
389 };
390