🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #14582

Re: OLE drag and drop to Win Explorer

#14582
From: Kiril Dunn
Date: Fri, 08 Aug 2003 05:37
171 lines
7170 bytes
"Remy Lebeau \(TeamB\)" <gambit47@yahoo.com> wrote:
>
>Are you sure that you are responding to
>the CF_HDROP correctly?

No. My preference is actually to use FileContents and FileGroupDescriptor - I added CF_HDROP as an excercise to see if that worked instead. I've since taken it out as it didn't make any difference.

>What OS are you running under?

WinXP Pro SP1 (with other hotfixes)

>What does your actual code look like?

Two classes - OLEDataObject which implements IDataObject; and EnumFmtEtc which implements IEnumFORMATETC. The important methods are below, let me know if you need more.

Thanks heaps,

Kiril

//---------------------------------------------------------------------------

HRESULT __stdcall OLEDataObject::GetData(FORMATETC* pFormatetc,
                                         STGMEDIUM* pmedium) {

    if ((pFormatetc->cfFormat == CF_EZIFILE) && (pFormatetc->tymed & TYMED_ISTREAM)) {
        // supports the IStream data type
        pmedium->tymed = TYMED_ISTREAM;

        // allocate a memory stream and stream out the data
        EzifileLinkStream* stream = new EzifileLinkStream(new TMemoryStream());
        stream->writeObjects(objects);

        pmedium->pstm = (IStream*) stream;

    } else if ((pFormatetc->cfFormat == CF_FILECONTENTS) && (pFormatetc->tymed & TYMED_ISTREAM)) {
        // supports the IStream format.
        // The lindex param is the index of the file to return
        // this will be a "link" file containing the IOR

        // allocate a memory stream and stream out the data
        EzifileLinkStream* stream = new EzifileLinkStream(new TMemoryStream());
        if (pFormatetc->lindex == -1) {
            stream->writeObjects(objects);
        } else {
            if (pFormatetc->lindex >= (LONG) objects.size()) {
                return DV_E_LINDEX;
            }
            stream->writeObject(objects[pFormatetc->lindex]);
        }

        pmedium->pstm = (IStream*) stream;
        pmedium->tymed = TYMED_ISTREAM;

    } else if ((pFormatetc->cfFormat == CF_FILEDESCRIPTOR) && (pFormatetc->tymed & TYMED_HGLOBAL)) {
        // supports the global mem data type
        // simply the file name list for the link files
        unsigned int dataSize = sizeof(FILEGROUPDESCRIPTOR) + ((objects.size() - 1) * sizeof(FILEDESCRIPTOR));
        HGLOBAL data = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, dataSize);
        if (!data) {
            RaiseLastOSError();
        }

        FILEGROUPDESCRIPTOR* files = (FILEGROUPDESCRIPTOR*) GlobalLock(data);
        try {
            files->cItems = objects.size();
            for (unsigned int i = 0; i < objects.size(); i++) {
                ClientStorageObject* obj = objects[i];
                strncpy(files->fgd[i].cFileName, obj->getName().c_str(), MAX_PATH);
            }
        } __finally {
            GlobalUnlock(data);
        }

        pmedium->hGlobal = data;
        pmedium->tymed = TYMED_HGLOBAL;

    } else if ((pFormatetc->cfFormat == CF_PERFORMEDDROPEFFECT) && (pFormatetc->tymed & TYMED_HGLOBAL)) {
        // Return the value that was set by the target
        HGLOBAL data = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD));
        DWORD* effect = (DWORD*) GlobalLock(data);
        if (!effect) {
            RaiseLastOSError();
        }
        try {
            (*effect) = performedDropEffect;
        } __finally {
            GlobalUnlock(data);
        }
        pmedium->hGlobal = data;
        pmedium->tymed = TYMED_HGLOBAL;

    } else {
        return E_INVALIDARG;
    }
    return S_OK;
}

//---------------------------------------------------------------------------

HRESULT __stdcall OLEDataObject::QueryGetData(FORMATETC* pformatetc) {
    if ((pformatetc->cfFormat == CF_EZIFILE) &&
        (pformatetc->tymed & TYMED_ISTREAM) &&
        (pformatetc->dwAspect & DVASPECT_CONTENT) &&
        (pformatetc->lindex == -1)) {

        return S_OK;

    } else if ((pformatetc->cfFormat == CF_FILECONTENTS) &&
               (pformatetc->tymed & TYMED_ISTREAM) &&
               (pformatetc->dwAspect & DVASPECT_CONTENT) &&
               (pformatetc->lindex >= -1)) {

        return S_OK;

    } else if ((pformatetc->cfFormat == CF_FILEDESCRIPTOR) &&
              (pformatetc->tymed & TYMED_HGLOBAL) &&
              (pformatetc->dwAspect & DVASPECT_CONTENT) &&
              (pformatetc->lindex == -1)) {

        return S_OK;

    } else if ((pformatetc->cfFormat == CF_PERFORMEDDROPEFFECT) &&
              (pformatetc->tymed & TYMED_HGLOBAL) &&
              (pformatetc->dwAspect & DVASPECT_CONTENT) &&
              (pformatetc->lindex == -1)) {

        return S_OK;
    }

    return DV_E_FORMATETC;
}

//---------------------------------------------------------------------------

HRESULT __stdcall OLEDataObject::EnumFormatEtc(DWORD dwDirection,
                                               IEnumFORMATETC **ppenumFormatEtc) {

    EnumFmtEtc* format = new EnumFmtEtc();
    if (dwDirection == DATADIR_GET) {
        format->addFormat(CF_EZIFILE, TYMED_ISTREAM);
        format->addFormat(CF_FILECONTENTS, TYMED_ISTREAM);
        format->addFormat(CF_FILEDESCRIPTOR, TYMED_HGLOBAL);
        format->addFormat(CF_PERFORMEDDROPEFFECT, TYMED_HGLOBAL);
    } else if (dwDirection == DATADIR_SET) {
        format->addFormat(CF_PERFORMEDDROPEFFECT, TYMED_HGLOBAL);
    } else {
        return E_INVALIDARG;
    }
    *ppenumFormatEtc = dynamic_cast<IEnumFORMATETC*>(format);
    return S_OK;
}

//---------------------------------------------------------------------------

HRESULT STDMETHODCALLTYPE OLEDataObject::EnumFmtEtc::Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) {
    unsigned long i = 0;
    while ((i < celt) && (currentIndex < formats.size())) {
        rgelt[i++] = formats[currentIndex++];
    }

    if (pceltFetched != NULL) {
        *pceltFetched = i;
    }

    if (i == celt) {
        return S_OK;
    } else {
        return S_FALSE;
    }
}
Technical Details
Message-ID: <3f333712$1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!sn-xit-03!sn-xit-01!sn-xit-08!supernews.com!news.tele.dk!news.tele.dk!small.news.tele.dk!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail
References: <3f3312c3$1@newsgroups.borland.com> <3f3325da$1@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 10cc67,9ab32f79cfce460e
X-Google-Attributes: gid10cc67,public
X-Google-ArrivalTime: 2003-08-07 22:40:06 PST
From: "Kiril Dunn" <kiril.dunn@ezifile.com>
Sender: "Kiril Dunn" <kiril.dunn@ezifile.com>
Reply-To: "Kiril Dunn" <kiril.dunn@ezifile.com>
Subject: Re: OLE drag and drop to Win Explorer
Newsgroups: borland.public.cppbuilder.nativeapi
X-User-Info: 210.9.242.77 210.9.242.77    
X-Forwarded-For: unknown
References: <3f3312c3$1@newsgroups.borland.com> <3f3325da$1@newsgroups.borland.com>
NNTP-Posting-Host: 207.105.83.65
Message-ID: <3f333712$1@newsgroups.borland.com>
Date: 7 Aug 2003 22:37:22 -0700
X-Trace: newsgroups.borland.com 1060321042 207.105.83.65 (7 Aug 2003 22:37:22 -0700)
Lines: 172
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!sn-xit-03!sn-xit-01!sn-xit-08!supernews.com!news.tele.dk!news.tele.dk!small.news.tele.dk!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail