]> git.sesse.net Git - vlc/blob - activex/oleobject.cpp
bump version to 0.8.4-test3
[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     SetClientSite(NULL);
41     Close(OLECLOSE_NOSAVE);
42     _p_advise_holder->Release();
43 };
44
45 STDMETHODIMP VLCOleObject::Advise(IAdviseSink *pAdvSink, DWORD *dwConnection)
46 {
47     return _p_advise_holder->Advise(pAdvSink, dwConnection);
48 };
49
50 STDMETHODIMP VLCOleObject::Close(DWORD dwSaveOption)
51 {
52     if( _p_instance->isRunning() )
53     {
54         _p_advise_holder->SendOnClose();
55         return _p_instance->onClose(dwSaveOption);
56     }
57     return S_OK;
58 };
59
60 STDMETHODIMP VLCOleObject::DoVerb(LONG iVerb, LPMSG lpMsg, LPOLECLIENTSITE pActiveSite,
61                                     LONG lIndex, HWND hwndParent, LPCRECT lprcPosRect)
62 {
63     switch( iVerb )
64     {
65         case OLEIVERB_PRIMARY:
66         case OLEIVERB_SHOW:
67         case OLEIVERB_OPEN:
68             // force control to be visible when activating in place
69             _p_instance->setVisible(TRUE);
70         case OLEIVERB_INPLACEACTIVATE:
71             return doInPlaceActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
72
73         case OLEIVERB_HIDE:
74             _p_instance->setVisible(FALSE);
75             return S_OK;
76
77         case OLEIVERB_UIACTIVATE:
78             return doUIActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
79
80         case OLEIVERB_DISCARDUNDOSTATE:
81             return S_OK;
82
83         default:
84             if( iVerb > 0 ) {
85                 _p_instance->setVisible(TRUE);
86                 doInPlaceActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
87                 return OLEOBJ_S_INVALIDVERB;
88             }
89             return E_NOTIMPL;
90     }
91 };
92
93 HRESULT VLCOleObject::doInPlaceActivate(LPMSG lpMsg, LPOLECLIENTSITE pActiveSite, HWND hwndParent, LPCRECT lprcPosRect)
94 {
95     RECT posRect;
96     RECT clipRect;
97     LPCRECT lprcClipRect = lprcPosRect;
98
99     if( NULL != pActiveSite )
100     {
101         // check if already activated
102         if( _p_instance->isInPlaceActive() )
103         {
104             // just attempt to show object then
105             if( _p_instance->getVisible() )
106                 pActiveSite->ShowObject();
107             return S_OK;
108         }
109
110         LPOLEINPLACESITE p_inPlaceSite;
111
112         if( SUCCEEDED(pActiveSite->QueryInterface(IID_IOleInPlaceSite, (void**)&p_inPlaceSite)) )
113         {
114             if( S_OK != p_inPlaceSite->CanInPlaceActivate() )
115             {
116                 return OLEOBJ_S_CANNOT_DOVERB_NOW;
117             }
118
119             LPOLEINPLACEFRAME p_inPlaceFrame;
120             LPOLEINPLACEUIWINDOW p_inPlaceUIWindow;
121             OLEINPLACEFRAMEINFO oleFrameInfo;
122
123             oleFrameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
124             if( SUCCEEDED(p_inPlaceSite->GetWindowContext(&p_inPlaceFrame, &p_inPlaceUIWindow, &posRect, &clipRect, &oleFrameInfo)) )
125             {
126                 lprcPosRect = &posRect;
127                 lprcClipRect = &clipRect;
128
129                 if( NULL != p_inPlaceFrame )
130                     p_inPlaceFrame->Release();
131                 if( NULL != p_inPlaceUIWindow )
132                     p_inPlaceUIWindow->Release();
133             }
134
135             if( (NULL == hwndParent) && FAILED(p_inPlaceSite->GetWindow(&hwndParent)) )
136             {
137                 p_inPlaceSite->Release();
138                 return OLEOBJ_S_INVALIDHWND;
139             }
140         }
141         else if( NULL == hwndParent )
142         {
143             return OLEOBJ_S_INVALIDHWND;
144         }
145
146         if( FAILED(_p_instance->onActivateInPlace(lpMsg, hwndParent, lprcPosRect, lprcClipRect)) )
147         {
148             if( NULL != p_inPlaceSite )
149                 p_inPlaceSite->Release();
150             return OLEOBJ_S_CANNOT_DOVERB_NOW;
151         }
152
153         if( NULL != p_inPlaceSite )
154             p_inPlaceSite->OnPosRectChange(lprcPosRect);
155
156         pActiveSite->ShowObject();
157         _p_instance->setVisible(TRUE);
158
159         if( NULL != p_inPlaceSite )
160         {
161             p_inPlaceSite->OnInPlaceActivate();
162             p_inPlaceSite->Release();
163         }
164
165         if( NULL != lpMsg )
166         {
167             switch( lpMsg->message )
168             {
169                 case WM_LBUTTONDOWN:
170                 case WM_LBUTTONDBLCLK:
171                     doUIActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
172                     break;
173                 default:
174                     break;
175             }
176         }
177         return S_OK;
178     }
179     return OLEOBJ_S_CANNOT_DOVERB_NOW;
180 };
181
182 HRESULT VLCOleObject::doUIActivate(LPMSG lpMsg, LPOLECLIENTSITE pActiveSite, HWND hwndParent, LPCRECT lprcPosRect)
183 {
184     if( NULL != pActiveSite )
185     {
186         // check if already activated
187         if( ! _p_instance->isInPlaceActive() )
188             return OLE_E_NOT_INPLACEACTIVE;
189
190         LPOLEINPLACESITE p_inPlaceSite;
191
192         if( SUCCEEDED(pActiveSite->QueryInterface(IID_IOleInPlaceSite, (void**)&p_inPlaceSite)) )
193         {
194             p_inPlaceSite->OnUIActivate();
195
196             if( NULL != lprcPosRect )
197             {
198                 p_inPlaceSite->OnPosRectChange(lprcPosRect);
199             }
200             p_inPlaceSite->Release();
201         }
202
203         pActiveSite->ShowObject();
204         _p_instance->setVisible(TRUE);
205         _p_instance->setFocus(TRUE);
206
207         return S_OK;
208     }
209     return E_FAIL;
210 };
211
212 STDMETHODIMP VLCOleObject::EnumAdvise(IEnumSTATDATA **ppEnumAdvise)
213 {
214     return _p_advise_holder->EnumAdvise(ppEnumAdvise);
215 };
216
217 STDMETHODIMP VLCOleObject::EnumVerbs(IEnumOleVerb **ppEnumOleVerb)
218 {
219     return OleRegEnumVerbs(_p_instance->getClassID(),
220         ppEnumOleVerb);
221 };
222
223 STDMETHODIMP VLCOleObject::GetClientSite(LPOLECLIENTSITE *ppClientSite)
224 {
225     if( NULL == ppClientSite )
226         return E_POINTER;
227  
228     if( NULL != _p_clientsite )
229         _p_clientsite->AddRef(); 
230
231     *ppClientSite = _p_clientsite;
232     return S_OK;
233 };
234
235 STDMETHODIMP VLCOleObject::GetClipboardData(DWORD dwReserved, LPDATAOBJECT *ppDataObject)
236 {
237     return _p_instance->pUnkOuter->QueryInterface(IID_IDataObject, (void **)ppDataObject);
238 };
239
240 STDMETHODIMP VLCOleObject::GetExtent(DWORD dwDrawAspect, SIZEL *pSizel)
241 {
242     if( NULL == pSizel )
243         return E_POINTER;
244
245     if( dwDrawAspect & DVASPECT_CONTENT )
246     {
247         *pSizel = _p_instance->getExtent();
248         return S_OK;
249     }
250     pSizel->cx= 0L;
251     pSizel->cy= 0L;
252     return E_NOTIMPL;
253 };
254
255 STDMETHODIMP VLCOleObject::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus)
256 {
257     if( NULL == pdwStatus )
258         return E_POINTER;
259
260     switch( dwAspect )
261     {
262         case DVASPECT_CONTENT:
263             *pdwStatus = OLEMISC_RECOMPOSEONRESIZE
264                 | OLEMISC_CANTLINKINSIDE
265                 | OLEMISC_INSIDEOUT
266                 | OLEMISC_ACTIVATEWHENVISIBLE
267                 | OLEMISC_SETCLIENTSITEFIRST;
268             break;
269         default:
270             *pdwStatus = 0;
271     }
272
273     return S_OK;
274 };
275
276 STDMETHODIMP VLCOleObject::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER *ppMoniker)
277 {
278     if( NULL != _p_clientsite )
279         return _p_clientsite->GetMoniker(dwAssign,dwWhichMoniker, ppMoniker);
280  
281     return E_UNEXPECTED;
282 };
283
284 STDMETHODIMP VLCOleObject::GetUserClassID(LPCLSID pClsid)
285 {
286     if( NULL == pClsid )
287         return E_POINTER;
288  
289     *pClsid = _p_instance->getClassID(); 
290     return S_OK;
291 };
292
293 STDMETHODIMP VLCOleObject::GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType)
294 {
295     return OleRegGetUserType(_p_instance->getClassID(),
296         dwFormOfType, pszUserType);
297 };
298
299 STDMETHODIMP VLCOleObject::InitFromData(LPDATAOBJECT pDataObject, BOOL fCreation, DWORD dwReserved)
300 {
301     return E_NOTIMPL;
302 };
303
304 STDMETHODIMP VLCOleObject::IsUpToDate(void)
305 {
306     return S_OK;
307 };
308
309 STDMETHODIMP VLCOleObject::SetClientSite(LPOLECLIENTSITE pClientSite)
310 {
311     if( NULL != _p_clientsite )
312         _p_clientsite->Release();
313
314     _p_clientsite = pClientSite;
315
316     if( NULL != pClientSite )
317     {
318         pClientSite->AddRef();
319         _p_instance->onAmbientChanged(pClientSite, DISPID_UNKNOWN);
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