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