/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Other objects querying to see if we support a particular format
STDMETHODIMP nsDataObjCollection::QueryGetData(LPFORMATETC pFE) {
UINT format = nsClipboard::GetFormat(MULTI_MIME);
if (format == pFE->cfFormat) { return S_OK;
}
for (uint32_t i = 0; i < mDataObjects.Length(); ++i) {
IDataObject* dataObj = mDataObjects.ElementAt(i); if (S_OK == dataObj->QueryGetData(pFE)) { return S_OK;
}
}
return DV_E_FORMATETC;
}
STDMETHODIMP nsDataObjCollection::SetData(LPFORMATETC pFE, LPSTGMEDIUM pSTM, BOOL fRelease) { // Set arbitrary data formats on the first object in the collection and let // it handle the heavy lifting if (mDataObjects.Length() == 0) return E_FAIL; return mDataObjects.ElementAt(0)->SetData(pFE, pSTM, fRelease);
}
// Registers a DataFlavor/FE pair void nsDataObjCollection::AddDataFlavor(constchar* aDataFlavor,
LPFORMATETC aFE) { // Add the FormatEtc to our list if it's not already there. We don't care // about the internal aDataFlavor because nsDataObj handles that.
IEnumFORMATETC* ifEtc;
FORMATETC fEtc;
ULONG num; if (S_OK != this->EnumFormatEtc(DATADIR_GET, &ifEtc)) return; while (S_OK == ifEtc->Next(1, &fEtc, &num)) {
NS_ASSERTION(
1 == num, "Bit off more than we can chew in nsDataObjCollection::AddDataFlavor"); if (FormatsMatch(fEtc, *aFE)) {
ifEtc->Release(); return;
}
} // If we didn't find a matching format, add this one
ifEtc->Release();
m_enumFE->AddFormatEtc(aFE);
}
// We accept ownership of the nsDataObj which we free on destruction void nsDataObjCollection::AddDataObject(IDataObject* aDataObj) {
nsDataObj* dataObj = reinterpret_cast<nsDataObj*>(aDataObj);
mDataObjects.AppendElement(dataObj);
}
// Methods for getting data
HRESULT nsDataObjCollection::GetFile(LPFORMATETC pFE, LPSTGMEDIUM pSTM) {
STGMEDIUM workingmedium;
FORMATETC fe = *pFE;
HGLOBAL hGlobalMemory;
HRESULT hr; // Make enough space for the header and the trailing null
uint32_t buffersize = sizeof(DROPFILES) + sizeof(char16_t);
uint32_t alloclen = 0;
char16_t* realbuffer;
nsAutoString filename;
hGlobalMemory = GlobalAlloc(GHND, buffersize);
for (uint32_t i = 0; i < mDataObjects.Length(); ++i) {
nsDataObj* dataObj = mDataObjects.ElementAt(i);
hr = dataObj->GetData(&fe, &workingmedium); if (hr != S_OK) { switch (hr) { case DV_E_FORMATETC: continue; default: return hr;
}
} // Now we need to pull out the filename
char16_t* buffer = (char16_t*)GlobalLock(workingmedium.hGlobal); if (buffer == nullptr) return E_FAIL;
buffer += sizeof(DROPFILES) / sizeof(char16_t);
filename = buffer;
GlobalUnlock(workingmedium.hGlobal);
ReleaseStgMedium(&workingmedium); // Now put the filename into our buffer
alloclen = (filename.Length() + 1) * sizeof(char16_t);
hGlobalMemory = ::GlobalReAlloc(hGlobalMemory, buffersize + alloclen, GHND); if (hGlobalMemory == nullptr) return E_FAIL;
realbuffer = (char16_t*)((char*)GlobalLock(hGlobalMemory) + buffersize); if (!realbuffer) return E_FAIL;
realbuffer--; // Overwrite the preceding null
memcpy(realbuffer, filename.get(), alloclen);
GlobalUnlock(hGlobalMemory);
buffersize += alloclen;
} // We get the last null (on the double null terminator) for free since we used // the zero memory flag when we allocated. All we need to do is fill the // DROPFILES structure
DROPFILES* df = (DROPFILES*)GlobalLock(hGlobalMemory); if (!df) return E_FAIL;
df->pFiles = sizeof(DROPFILES); // Offset to start of file name string
df->fNC = 0;
df->pt.x = 0;
df->pt.y = 0;
df->fWide = TRUE; // utf-16 chars
GlobalUnlock(hGlobalMemory); // Finally fill out the STGMEDIUM struct
pSTM->tymed = TYMED_HGLOBAL;
pSTM->pUnkForRelease = nullptr; // Caller gets to free the data
pSTM->hGlobal = hGlobalMemory; return S_OK;
}
for (uint32_t i = 0; i < mDataObjects.Length(); ++i) {
nsDataObj* dataObj = mDataObjects.ElementAt(i);
hr = dataObj->GetData(&fe, &workingmedium); if (hr != S_OK) { switch (hr) { case DV_E_FORMATETC: continue; default: return hr;
}
} // Now we need to pull out the filedescriptor
FILEDESCRIPTOR* buffer =
(FILEDESCRIPTOR*)((char*)GlobalLock(workingmedium.hGlobal) + sizeof(UINT)); if (buffer == nullptr) return E_FAIL;
hGlobalMemory = ::GlobalReAlloc(hGlobalMemory, buffersize + alloclen, GHND); if (hGlobalMemory == nullptr) return E_FAIL;
FILEGROUPDESCRIPTOR* realbuffer =
(FILEGROUPDESCRIPTOR*)GlobalLock(hGlobalMemory); if (!realbuffer) return E_FAIL;
FILEDESCRIPTOR* copyloc = (FILEDESCRIPTOR*)((char*)realbuffer + buffersize);
memcpy(copyloc, buffer, alloclen);
realbuffer->cItems++;
GlobalUnlock(hGlobalMemory);
GlobalUnlock(workingmedium.hGlobal);
ReleaseStgMedium(&workingmedium);
buffersize += alloclen;
}
pSTM->tymed = TYMED_HGLOBAL;
pSTM->pUnkForRelease = nullptr; // Caller gets to free the data
pSTM->hGlobal = hGlobalMemory; return S_OK;
}
HRESULT nsDataObjCollection::GetFileContents(LPFORMATETC pFE,
LPSTGMEDIUM pSTM) {
ULONG num = 0;
ULONG numwanted = (pFE->lindex == -1) ? 0 : pFE->lindex;
FORMATETC fEtc = *pFE;
fEtc.lindex = -1; // We're lying to the data object so it thinks it's alone
// The key for this data type is to figure out which data object the index // corresponds to and then just pass it along for (uint32_t i = 0; i < mDataObjects.Length(); ++i) {
nsDataObj* dataObj = mDataObjects.ElementAt(i); if (dataObj->QueryGetData(&fEtc) != S_OK) continue; if (num == numwanted) return dataObj->GetData(pFE, pSTM);
num++;
} return DV_E_LINDEX;
}
HRESULT nsDataObjCollection::GetFirstSupporting(LPFORMATETC pFE,
LPSTGMEDIUM pSTM) { // There is no way to pass more than one of this, so just find the first data // object that supports it and pass it along for (uint32_t i = 0; i < mDataObjects.Length(); ++i) { if (mDataObjects.ElementAt(i)->QueryGetData(pFE) == S_OK) return mDataObjects.ElementAt(i)->GetData(pFE, pSTM);
} return DV_E_FORMATETC;
}
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.