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