oleobject.cpp 10.7 KB
Newer Older
1 2 3
/*****************************************************************************
 * oleobject.cpp: ActiveX control for VLC
 *****************************************************************************
4
 * Copyright (C) 2005 the VideoLAN team
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
Antoine Cellerier's avatar
Antoine Cellerier committed
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
 *****************************************************************************/

#include "plugin.h"
#include "oleobject.h"

#include "utils.h"

#include <docobj.h>

using namespace std;

VLCOleObject::VLCOleObject(VLCPlugin *p_instance) :
_p_clientsite(NULL), _p_instance(p_instance) 
{
    CreateOleAdviseHolder(&_p_advise_holder);
};

VLCOleObject::~VLCOleObject()
{
40 41
    SetClientSite(NULL);
    Close(OLECLOSE_NOSAVE);
42 43 44 45 46 47 48 49 50 51
    _p_advise_holder->Release();
};

STDMETHODIMP VLCOleObject::Advise(IAdviseSink *pAdvSink, DWORD *dwConnection)
{
    return _p_advise_holder->Advise(pAdvSink, dwConnection);
};

STDMETHODIMP VLCOleObject::Close(DWORD dwSaveOption)
{
52 53 54 55 56 57
    if( _p_instance->isRunning() )
    {
        _p_advise_holder->SendOnClose();
        return _p_instance->onClose(dwSaveOption);
    }
    return S_OK;
58 59 60 61 62 63 64 65 66 67
};

STDMETHODIMP VLCOleObject::DoVerb(LONG iVerb, LPMSG lpMsg, LPOLECLIENTSITE pActiveSite,
                                    LONG lIndex, HWND hwndParent, LPCRECT lprcPosRect)
{
    switch( iVerb )
    {
        case OLEIVERB_PRIMARY:
        case OLEIVERB_SHOW:
        case OLEIVERB_OPEN:
Damien Fouilleul's avatar
 
Damien Fouilleul committed
68 69
            // force control to be visible when activating in place
            _p_instance->setVisible(TRUE);
70
        case OLEIVERB_INPLACEACTIVATE:
71
            return doInPlaceActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
72 73 74 75 76 77 78 79 80 81 82 83

        case OLEIVERB_HIDE:
            _p_instance->setVisible(FALSE);
            return S_OK;

        case OLEIVERB_UIACTIVATE:
            return doUIActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);

        case OLEIVERB_DISCARDUNDOSTATE:
            return S_OK;

        default:
Damien Fouilleul's avatar
 
Damien Fouilleul committed
84 85 86 87 88 89
            if( iVerb > 0 ) {
                _p_instance->setVisible(TRUE);
                doInPlaceActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
                return OLEOBJ_S_INVALIDVERB;
            }
            return E_NOTIMPL;
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
    }
};

HRESULT VLCOleObject::doInPlaceActivate(LPMSG lpMsg, LPOLECLIENTSITE pActiveSite, HWND hwndParent, LPCRECT lprcPosRect)
{
    RECT posRect;
    RECT clipRect;
    LPCRECT lprcClipRect = lprcPosRect;

    if( NULL != pActiveSite )
    {
        // check if already activated
        if( _p_instance->isInPlaceActive() )
        {
            // just attempt to show object then
Damien Fouilleul's avatar
 
Damien Fouilleul committed
105 106
            if( _p_instance->getVisible() )
                pActiveSite->ShowObject();
107 108 109 110 111 112 113 114
            return S_OK;
        }

        LPOLEINPLACESITE p_inPlaceSite;

        if( SUCCEEDED(pActiveSite->QueryInterface(IID_IOleInPlaceSite, (void**)&p_inPlaceSite)) )
        {
            if( S_OK != p_inPlaceSite->CanInPlaceActivate() )
115
            {
116
                return OLEOBJ_S_CANNOT_DOVERB_NOW;
117
            }
118 119 120 121 122

            LPOLEINPLACEFRAME p_inPlaceFrame;
            LPOLEINPLACEUIWINDOW p_inPlaceUIWindow;
            OLEINPLACEFRAMEINFO oleFrameInfo;

123
            oleFrameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
124 125 126 127 128 129 130 131 132 133
            if( SUCCEEDED(p_inPlaceSite->GetWindowContext(&p_inPlaceFrame, &p_inPlaceUIWindow, &posRect, &clipRect, &oleFrameInfo)) )
            {
                lprcPosRect = &posRect;
                lprcClipRect = &clipRect;

                if( NULL != p_inPlaceFrame )
                    p_inPlaceFrame->Release();
                if( NULL != p_inPlaceUIWindow )
                    p_inPlaceUIWindow->Release();
            }
134 135 136 137 138 139

            if( (NULL == hwndParent) && FAILED(p_inPlaceSite->GetWindow(&hwndParent)) )
            {
                p_inPlaceSite->Release();
                return OLEOBJ_S_INVALIDHWND;
            }
140
        }
141
        else if( NULL == hwndParent )
142
        {
143
            return OLEOBJ_S_INVALIDHWND;
144
        }
145 146 147 148 149 150
        else if( NULL == lprcPosRect )
        {
            SetRect(&posRect, 0, 0, 0, 0);
            lprcPosRect = &posRect;
            lprcClipRect = &posRect;
        }
151 152

        if( FAILED(_p_instance->onActivateInPlace(lpMsg, hwndParent, lprcPosRect, lprcClipRect)) )
153 154 155 156 157
        {
            if( NULL != p_inPlaceSite )
                p_inPlaceSite->Release();
            return OLEOBJ_S_CANNOT_DOVERB_NOW;
        }
158 159 160 161

        if( NULL != p_inPlaceSite )
        {
            p_inPlaceSite->OnInPlaceActivate();
162
            p_inPlaceSite->OnPosRectChange(lprcPosRect);
163 164 165
            p_inPlaceSite->Release();
        }

166 167 168
        pActiveSite->ShowObject();
        _p_instance->setVisible(TRUE);

169 170 171 172 173 174 175 176 177 178 179 180 181 182
        if( NULL != lpMsg )
        {
            switch( lpMsg->message )
            {
                case WM_LBUTTONDOWN:
                case WM_LBUTTONDBLCLK:
                    doUIActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
                    break;
                default:
                    break;
            }
        }
        return S_OK;
    }
183
    return OLEOBJ_S_CANNOT_DOVERB_NOW;
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
};

HRESULT VLCOleObject::doUIActivate(LPMSG lpMsg, LPOLECLIENTSITE pActiveSite, HWND hwndParent, LPCRECT lprcPosRect)
{
    if( NULL != pActiveSite )
    {
        // check if already activated
        if( ! _p_instance->isInPlaceActive() )
            return OLE_E_NOT_INPLACEACTIVE;

        LPOLEINPLACESITE p_inPlaceSite;

        if( SUCCEEDED(pActiveSite->QueryInterface(IID_IOleInPlaceSite, (void**)&p_inPlaceSite)) )
        {
            p_inPlaceSite->OnUIActivate();

            if( NULL != lprcPosRect )
            {
                p_inPlaceSite->OnPosRectChange(lprcPosRect);
            }
            p_inPlaceSite->Release();
        }

        pActiveSite->ShowObject();
        _p_instance->setVisible(TRUE);
        _p_instance->setFocus(TRUE);

        return S_OK;
    }
    return E_FAIL;
};

STDMETHODIMP VLCOleObject::EnumAdvise(IEnumSTATDATA **ppEnumAdvise)
{
    return _p_advise_holder->EnumAdvise(ppEnumAdvise);
};

STDMETHODIMP VLCOleObject::EnumVerbs(IEnumOleVerb **ppEnumOleVerb)
{
Damien Fouilleul's avatar
 
Damien Fouilleul committed
223 224
    return OleRegEnumVerbs(_p_instance->getClassID(),
        ppEnumOleVerb);
225 226 227 228 229 230 231 232 233 234
};

STDMETHODIMP VLCOleObject::GetClientSite(LPOLECLIENTSITE *ppClientSite)
{
    if( NULL == ppClientSite )
        return E_POINTER;
 
    if( NULL != _p_clientsite )
        _p_clientsite->AddRef(); 

235
    *ppClientSite = _p_clientsite;
236 237 238 239 240
    return S_OK;
};

STDMETHODIMP VLCOleObject::GetClipboardData(DWORD dwReserved, LPDATAOBJECT *ppDataObject)
{
Damien Fouilleul's avatar
 
Damien Fouilleul committed
241
    return _p_instance->pUnkOuter->QueryInterface(IID_IDataObject, (void **)ppDataObject);
242 243 244 245
};

STDMETHODIMP VLCOleObject::GetExtent(DWORD dwDrawAspect, SIZEL *pSizel)
{
Damien Fouilleul's avatar
Damien Fouilleul committed
246 247 248 249 250 251 252 253 254 255
    if( NULL == pSizel )
        return E_POINTER;

    if( dwDrawAspect & DVASPECT_CONTENT )
    {
        *pSizel = _p_instance->getExtent();
        return S_OK;
    }
    pSizel->cx= 0L;
    pSizel->cy= 0L;
256 257 258 259 260
    return E_NOTIMPL;
};

STDMETHODIMP VLCOleObject::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus)
{
Damien Fouilleul's avatar
 
Damien Fouilleul committed
261
    if( NULL == pdwStatus )
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
        return E_POINTER;

    switch( dwAspect )
    {
        case DVASPECT_CONTENT:
            *pdwStatus = OLEMISC_RECOMPOSEONRESIZE
                | OLEMISC_CANTLINKINSIDE
                | OLEMISC_INSIDEOUT
                | OLEMISC_ACTIVATEWHENVISIBLE
                | OLEMISC_SETCLIENTSITEFIRST;
            break;
        default:
            *pdwStatus = 0;
    }

    return S_OK;
};

STDMETHODIMP VLCOleObject::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER *ppMoniker)
{
    if( NULL != _p_clientsite )
        return _p_clientsite->GetMoniker(dwAssign,dwWhichMoniker, ppMoniker);
 
    return E_UNEXPECTED;
};

STDMETHODIMP VLCOleObject::GetUserClassID(LPCLSID pClsid)
{
    if( NULL == pClsid )
        return E_POINTER;
 
Damien Fouilleul's avatar
 
Damien Fouilleul committed
293
    *pClsid = _p_instance->getClassID(); 
294 295 296 297 298
    return S_OK;
};

STDMETHODIMP VLCOleObject::GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType)
{
Damien Fouilleul's avatar
 
Damien Fouilleul committed
299 300
    return OleRegGetUserType(_p_instance->getClassID(),
        dwFormOfType, pszUserType);
301 302 303 304 305 306 307 308 309 310 311 312 313 314
};

STDMETHODIMP VLCOleObject::InitFromData(LPDATAOBJECT pDataObject, BOOL fCreation, DWORD dwReserved)
{
    return E_NOTIMPL;
};

STDMETHODIMP VLCOleObject::IsUpToDate(void)
{
    return S_OK;
};

STDMETHODIMP VLCOleObject::SetClientSite(LPOLECLIENTSITE pClientSite)
{
315 316 317
    if( NULL != _p_clientsite )
        _p_clientsite->Release();

318
    _p_clientsite = pClientSite;
319

320 321 322 323 324
    if( NULL != pClientSite )
    {
        pClientSite->AddRef();
        _p_instance->onAmbientChanged(pClientSite, DISPID_UNKNOWN);
    }
325 326 327 328 329 330 331 332 333 334
    return S_OK;
};

STDMETHODIMP VLCOleObject::SetColorScheme(LOGPALETTE *pLogpal)
{
    return E_NOTIMPL;
};

STDMETHODIMP VLCOleObject::SetExtent(DWORD dwDrawAspect, SIZEL *pSizel)
{
Damien Fouilleul's avatar
Damien Fouilleul committed
335 336 337
    if( NULL == pSizel )
        return E_POINTER;

338

Damien Fouilleul's avatar
Damien Fouilleul committed
339 340 341 342 343 344 345 346 347 348
    if( dwDrawAspect & DVASPECT_CONTENT )
    {
        _p_instance->setExtent(*pSizel);

        if( _p_instance->isInPlaceActive() )
        {
            LPOLEINPLACESITE p_inPlaceSite;

            if( SUCCEEDED(_p_clientsite->QueryInterface(IID_IOleInPlaceSite, (void**)&p_inPlaceSite)) )
            {
349
                HWND hwnd;
Damien Fouilleul's avatar
Damien Fouilleul committed
350

351
                if( SUCCEEDED(p_inPlaceSite->GetWindow(&hwnd)) )
Damien Fouilleul's avatar
Damien Fouilleul committed
352
                {
353 354 355
                    // use HIMETRIC to pixel transform 
                    RECT posRect = _p_instance->getPosRect();
                    HDC hDC = GetDC(hwnd);
Damien Fouilleul's avatar
Damien Fouilleul committed
356 357 358
                    posRect.right = (pSizel->cx*GetDeviceCaps(hDC, LOGPIXELSX)/2540L)+posRect.left;
                    posRect.bottom = (pSizel->cy*GetDeviceCaps(hDC, LOGPIXELSY)/2540L)+posRect.top;
                    DeleteDC(hDC);
359
                    p_inPlaceSite->OnPosRectChange(&posRect);
Damien Fouilleul's avatar
Damien Fouilleul committed
360 361 362 363 364 365
                }
                p_inPlaceSite->Release();
            }
        }
        return S_OK;
    }
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
    return E_NOTIMPL;
};

STDMETHODIMP VLCOleObject::SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
{
    return S_OK;
};

STDMETHODIMP VLCOleObject::SetMoniker(DWORD dwWhichMoniker, LPMONIKER pMoniker)
{
    return _p_advise_holder->SendOnRename(pMoniker);
};

STDMETHODIMP VLCOleObject::Unadvise(DWORD dwConnection)
{
    return _p_advise_holder->Unadvise(dwConnection);
};

STDMETHODIMP VLCOleObject::Update(void)
{
    return S_OK;
};