diff options
Diffstat (limited to 'libs/mTextControl/src/ImageDataObjectHlp.cpp')
-rw-r--r-- | libs/mTextControl/src/ImageDataObjectHlp.cpp | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/libs/mTextControl/src/ImageDataObjectHlp.cpp b/libs/mTextControl/src/ImageDataObjectHlp.cpp new file mode 100644 index 0000000000..358ce0b1ef --- /dev/null +++ b/libs/mTextControl/src/ImageDataObjectHlp.cpp @@ -0,0 +1,209 @@ +/* +Miranda SmileyAdd Plugin +Copyright (C) 2004-2005 Rein-Peter de Boer (peacow) and followers + +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 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +//imagedataobject +//code taken partly from public example on the internet, source unknown. + +#include "stdafx.h" +#include "ImageDataObjectHlp.h" + +struct EMFCACHE +{ + HENHMETAFILE hEmf; + HICON hIcon; + EMFCACHE *prev; + EMFCACHE *next; +} *emfCache = nullptr; +int emfCacheSize = 0; +mir_cs csEmfCache; + +void UnloadEmfCache() +{ + while (emfCache) + { + EMFCACHE *tmp = emfCache->next; + delete emfCache; + emfCache = tmp; + } +} + +HENHMETAFILE CacheIconToEmf(HICON hIcon) +{ + HENHMETAFILE result = nullptr; + mir_cslock lck(csEmfCache); + for (EMFCACHE *p = emfCache; p; p = p->next) + if (p->hIcon == hIcon) + { + if (p->prev) + { + p->prev->next = p->next; + if (p->next) p->next->prev = p->prev; + p->prev = nullptr; + emfCache->prev = p; + p->next = emfCache; + emfCache = p; + result = CopyEnhMetaFile(emfCache->hEmf, nullptr); + break; + } + } + + // cache new item + if (!result) + { + EMFCACHE *newItem = new EMFCACHE; + newItem->prev = nullptr; + newItem->next = emfCache; + if (emfCache) emfCache->prev = newItem; + emfCache = newItem; + emfCacheSize++; + + HDC emfdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, L"icon"); + DrawIconEx(emfdc, 0, 0, (HICON)hIcon, 16, 16, 0, nullptr, DI_NORMAL); + emfCache->hIcon = hIcon; + emfCache->hEmf = CloseEnhMetaFile(emfdc); + result = CopyEnhMetaFile(emfCache->hEmf, nullptr); + } + + // tail cutoff + if (emfCacheSize > 20) + { + int n = 0; + EMFCACHE *p; + for (p = emfCache; p; p = p->next) + if (++n > 20) + break; + while (p->next) + { + EMFCACHE *tmp = p->next; + p->next = p->next->next; + delete tmp; + } + if (p->next) p->next->prev = p; + emfCacheSize = 20; + } + + return result; +} + +HRESULT CreateDataObject(const FORMATETC *fmtetc, const STGMEDIUM *stgmed, UINT count, IDataObject **ppDataObject); + +// returns true on success, false on failure +//bool InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap, HGLOBAL hGlobal) +bool InsertBitmap(IRichEditOle* pRichEditOle, HENHMETAFILE hEmf) +{ + SCODE sc; + + // Get the image data object + // + static const FORMATETC lc_format[] = + { + { CF_ENHMETAFILE, nullptr, DVASPECT_CONTENT, -1, TYMED_ENHMF }//, + // { CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, + // { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } + }; + + STGMEDIUM lc_stgmed[] = + { + { TYMED_ENHMF, { (HBITMAP)hEmf }, nullptr }//, + // { TYMED_GDI, { hBitmap }, 0 }, + // { TYMED_HGLOBAL, { (HBITMAP)hGlobal }, 0 } + }; + + IDataObject *pods; + CreateDataObject(lc_format, lc_stgmed, 1, &pods); + + // Get the RichEdit container site + // + IOleClientSite *pOleClientSite; + pRichEditOle->GetClientSite(&pOleClientSite); + + // Initialize a Storage Object + // + LPLOCKBYTES lpLockBytes = nullptr; + sc = CreateILockBytesOnHGlobal(nullptr, TRUE, &lpLockBytes); + if (sc != S_OK) + { + pOleClientSite->Release(); + return false; + } + + IStorage *pStorage; + sc = StgCreateDocfileOnILockBytes(lpLockBytes, + STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &pStorage); + if (sc != S_OK) + { + lpLockBytes->Release(); + pOleClientSite->Release(); + pods->Release(); + return false; + } + + // The final ole object which will be inserted in the richedit control + // + IOleObject *pOleObject; + sc = OleCreateStaticFromData(pods, IID_IOleObject, OLERENDER_FORMAT, + (LPFORMATETC)lc_format, pOleClientSite, pStorage, (void **)&pOleObject); + if (sc != S_OK) + { + pStorage->Release(); + lpLockBytes->Release(); + pOleClientSite->Release(); + return false; + } + + // all items are "contained" -- this makes our reference to this object + // weak -- which is needed for links to embedding silent update. + OleSetContainedObject(pOleObject, TRUE); + + // Now Add the object to the RichEdit + // + REOBJECT reobject = { 0 }; + + reobject.cbStruct = sizeof(REOBJECT); + reobject.cp = REO_CP_SELECTION; + reobject.dvaspect = DVASPECT_CONTENT; + reobject.poleobj = pOleObject; + reobject.polesite = pOleClientSite; + reobject.pstg = pStorage; + reobject.dwFlags = REO_BELOWBASELINE; + + sc = pOleObject->GetUserClassID(&reobject.clsid); + if (sc != S_OK) + { + pOleObject->Release(); + pStorage->Release(); + lpLockBytes->Release(); + pOleClientSite->Release(); + return false; + } + + // Insert the bitmap at the current location in the richedit control + // + sc = pRichEditOle->InsertObject(&reobject); + + // Release all unnecessary interfaces + // + pOleObject->Release(); + pStorage->Release(); + lpLockBytes->Release(); + pOleClientSite->Release(); + pods->Release(); + + return sc == S_OK; +} |