dataobject.cpp 8.44 KB
Newer Older
Damien Fouilleul's avatar
 
Damien Fouilleul committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*****************************************************************************
 * viewobject.cpp: ActiveX control for VLC
 *****************************************************************************
 * Copyright (C) 2005 VideoLAN
 *
 * 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.
Damien Fouilleul's avatar
 
Damien Fouilleul committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
 *****************************************************************************/

#include "plugin.h"
#include "dataobject.h"

#include "utils.h"

using namespace std;

////////////////////////////////////////////////////////////////////////////////////////////////

class VLCEnumFORMATETC : public IEnumFORMATETC
{
public:

    VLCEnumFORMATETC(vector<FORMATETC> &v) :
        e(VLCEnum<FORMATETC>(IID_IEnumFORMATETC, v)) {};

    VLCEnumFORMATETC(const VLCEnumFORMATETC &vlcEnum) : e(vlcEnum.e) {};
    virtual ~VLCEnumFORMATETC() {};

    // IUnknown methods
    STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
        { return e.QueryInterface(riid, ppv); };
    STDMETHODIMP_(ULONG) AddRef(void)
        { return e.AddRef(); };
    STDMETHODIMP_(ULONG) Release(void)
        {return e.Release(); };

    //IEnumConnectionPoints
    STDMETHODIMP Next(ULONG celt, LPFORMATETC rgelt, ULONG *pceltFetched)
        { return e.Next(celt, rgelt, pceltFetched); };
    STDMETHODIMP Skip(ULONG celt)
        { return e.Skip(celt);};
    STDMETHODIMP Reset(void)
        { return e.Reset();};
    STDMETHODIMP Clone(LPENUMFORMATETC *ppenum)
        { if( NULL == ppenum ) return E_POINTER;
          *ppenum = dynamic_cast<LPENUMFORMATETC>(new VLCEnumFORMATETC(*this));
          return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
        };

private:

    VLCEnum<FORMATETC> e;
};

////////////////////////////////////////////////////////////////////////////////////////////////

static const FORMATETC _metaFileFormatEtc =
    {
        CF_METAFILEPICT,
        NULL,
        DVASPECT_CONTENT,
        -1,
        TYMED_MFPICT,
    };
static const FORMATETC _enhMetaFileFormatEtc =
    {
        CF_ENHMETAFILE,
        NULL,
        DVASPECT_CONTENT,
        -1,
        TYMED_ENHMF,
    };

VLCDataObject::VLCDataObject(VLCPlugin *p_instance) : _p_instance(p_instance)
{
    _v_formatEtc.push_back(_enhMetaFileFormatEtc);
    _v_formatEtc.push_back(_metaFileFormatEtc);
    CreateDataAdviseHolder(&_p_adviseHolder);
};

VLCDataObject::~VLCDataObject()
{
    _p_adviseHolder->Release();
};

////////////////////////////////////////////////////////////////////////////////////////////////

STDMETHODIMP VLCDataObject::DAdvise(LPFORMATETC pFormatEtc, DWORD padvf, LPADVISESINK pAdviseSink, LPDWORD pdwConnection)
{
    return _p_adviseHolder->Advise(this,
            pFormatEtc, padvf,pAdviseSink, pdwConnection);
};

STDMETHODIMP VLCDataObject::DUnadvise(DWORD dwConnection)
{
    return _p_adviseHolder->Unadvise(dwConnection);
};

STDMETHODIMP VLCDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
{
    return _p_adviseHolder->EnumAdvise(ppenumAdvise);
};

STDMETHODIMP VLCDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumformatetc)
{
    if( NULL == ppenumformatetc )
        return E_POINTER;

    *ppenumformatetc = new VLCEnumFORMATETC(_v_formatEtc);
    return NOERROR;
};

STDMETHODIMP VLCDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatEtcIn, LPFORMATETC pFormatEtcOut)
{
    HRESULT result = QueryGetData(pFormatEtcIn);
    if( FAILED(result) )
        return result;

    if( NULL == pFormatEtcOut )
        return E_POINTER;

    *pFormatEtcOut = *pFormatEtcIn;
    pFormatEtcOut->ptd = NULL;

    return DATA_S_SAMEFORMATETC;
};

STDMETHODIMP VLCDataObject::GetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
{
    if( NULL == pMedium )
        return E_POINTER;

    HRESULT result = QueryGetData(pFormatEtc);
    if( SUCCEEDED(result) )
    {
        switch( pFormatEtc->cfFormat )
        {
            case CF_METAFILEPICT:
                pMedium->tymed = TYMED_MFPICT;
                pMedium->hMetaFilePict = NULL;
                pMedium->pUnkForRelease = NULL;
                result = getMetaFileData(pFormatEtc, pMedium);
                break;
            case CF_ENHMETAFILE:
                pMedium->tymed = TYMED_ENHMF;
                pMedium->hEnhMetaFile = NULL;
                pMedium->pUnkForRelease = NULL;
                result = getEnhMetaFileData(pFormatEtc, pMedium);
                break;
            default:
                result = DV_E_FORMATETC;
        }
    }
    return result;
};

STDMETHODIMP VLCDataObject::GetDataHere(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
{
    if( NULL == pMedium )
        return E_POINTER;

    return E_NOTIMPL;
}

////////////////////////////////////////////////////////////////////////////////////////////////

HRESULT VLCDataObject::getMetaFileData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
{
    HDC hicTargetDev = CreateDevDC(pFormatEtc->ptd);
    if( NULL == hicTargetDev )
        return E_FAIL;

    HDC hdcMeta = CreateMetaFile(NULL); 
    if( NULL != hdcMeta )
    {
        LPMETAFILEPICT pMetaFilePict = (LPMETAFILEPICT)CoTaskMemAlloc(sizeof(METAFILEPICT));
        if( NULL != pMetaFilePict )
        {
            SIZEL size = _p_instance->getExtent();
            RECTL wBounds = { 0L, 0L, size.cx, size.cy };

            pMetaFilePict->mm   = MM_ANISOTROPIC;
            pMetaFilePict->xExt = size.cx;
            pMetaFilePict->yExt = size.cy;

199 200
            DPFromHimetric(hicTargetDev, (LPPOINT)&size, 1);

Damien Fouilleul's avatar
 
Damien Fouilleul committed
201
            SetMapMode(hdcMeta, MM_ANISOTROPIC);
202
            SetWindowExtEx(hdcMeta, size.cx, size.cy, NULL);
Damien Fouilleul's avatar
 
Damien Fouilleul committed
203

204
            RECTL bounds = { 0L, 0L, size.cx, size.cy };
Damien Fouilleul's avatar
 
Damien Fouilleul committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230

            _p_instance->onDraw(pFormatEtc->ptd, hicTargetDev, hdcMeta, &bounds, &wBounds);
            pMetaFilePict->hMF = CloseMetaFile(hdcMeta);
            if( NULL != pMetaFilePict->hMF )
                pMedium->hMetaFilePict = pMetaFilePict;
            else
                CoTaskMemFree(pMetaFilePict);
        }
    }
    DeleteDC(hicTargetDev);
    return (NULL != pMedium->hMetaFilePict) ? S_OK : E_FAIL;
};

HRESULT VLCDataObject::getEnhMetaFileData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
{
    HDC hicTargetDev = CreateDevDC(pFormatEtc->ptd);
    if( NULL == hicTargetDev )
        return E_FAIL;

    SIZEL size = _p_instance->getExtent();

    HDC hdcMeta = CreateEnhMetaFile(hicTargetDev, NULL, NULL, NULL); 
    if( NULL != hdcMeta )
    {
        RECTL wBounds = { 0L, 0L, size.cx, size.cy };

231
        DPFromHimetric(hicTargetDev, (LPPOINT)&size, 1);
Damien Fouilleul's avatar
 
Damien Fouilleul committed
232

233
        RECTL bounds = { 0L, 0L, size.cx, size.cy };
Damien Fouilleul's avatar
 
Damien Fouilleul committed
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278

        _p_instance->onDraw(pFormatEtc->ptd, hicTargetDev, hdcMeta, &bounds, &wBounds);
        pMedium->hEnhMetaFile = CloseEnhMetaFile(hdcMeta);
    }
    DeleteDC(hicTargetDev);

    return (NULL != pMedium->hEnhMetaFile) ? S_OK : E_FAIL;
};

STDMETHODIMP VLCDataObject::QueryGetData(LPFORMATETC pFormatEtc)
{
    if( NULL == pFormatEtc )
        return E_POINTER;

    const FORMATETC *formatEtc;

    switch( pFormatEtc->cfFormat )
    {
        case CF_METAFILEPICT:
            formatEtc = &_metaFileFormatEtc;
            break;
        case CF_ENHMETAFILE:
            formatEtc = &_enhMetaFileFormatEtc;
            break;
        default:
            return DV_E_FORMATETC;
    }
    
    if( pFormatEtc->dwAspect != formatEtc->dwAspect )
        return DV_E_DVASPECT;

    if( pFormatEtc->lindex != formatEtc->lindex )
        return DV_E_LINDEX;

    if( pFormatEtc->tymed != formatEtc->tymed )
        return DV_E_TYMED;

    return S_OK;
};

STDMETHODIMP VLCDataObject::SetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease)
{
    return E_NOTIMPL;
};

279 280 281 282 283
/*void VLCDataObject::onDataChange(void)
{
    _p_adviseHolder->SendOnDataChange(this, 0, 0);
};*/

Damien Fouilleul's avatar
 
Damien Fouilleul committed
284 285 286 287 288 289 290
void VLCDataObject::onClose(void)
{
    _p_adviseHolder->SendOnDataChange(this, 0, ADVF_DATAONSTOP);
    if( S_OK == OleIsCurrentClipboard(dynamic_cast<LPDATAOBJECT>(this)) )
        OleFlushClipboard();
};