Вставляем HBITMAP (Bitmap) в элемент управления RichEditАвтор: Hani Atassi.
Требования: VC6 SP5, Win2000 SP2 Существует множество примеров, объясняющих как вставить файл bitmap в RichEdit. Но недостаток этих примеров в том, что они непригодны в случае, если изображение находится в виде ресурса либо в виде дескриптора (HBITMAP). Статья основывается на примере MSDN "HOWTO: Insert a Bitmap Into an RTF Document Using the RichEdit Control", и использует интерфейс IDataObject. В статье MSDN используется OLE API (OleCreateFromFile), которая использует имя файла в виде строки. Так же существует множество способов создания объекта OLE (IOleObject). Все эти OLE API начинаются с префикса OleCreate. Одну из них я использовал в данном примере (OleCreateStaticFromData), которая позволяет нам создавать объект Ole, который в свою очередь содержит только представление без каких либо ссылок на данные. Естевственно, что данные могут быть в виде значения HBITMAP, которое может быть представлением картинки. Думаю не стоит объяснять - как создать OleObject (IOleObject). Этот процесс хорошо описан в MSDN. Однако, один составляющих OLE объектов требует некоторого пояснения. В данном случае наша HBITMAP будет храниться в IDataObject. Существует два метода получения нашего HBITMAP из объекта. Первый использует COleDataSource, который включён в интерфейс IDataObject. Второй метод - это добавить свою собственную обработку данного процесса в IDataObject. Второй метод хорош тем, что нет необходимости использовать MFC в приложении. Первый метод использует следующий код: STGMEDIUM stgm; stgm.tymed = TYMED_GDI; // Хранилище среднее = дескриптор HBITMAP stgm.hBitmap = hBitmap; stgm.pUnkForRelease = NULL; // Используем ReleaseStgMedium COleDataSource *pDataSource = new COleDataSource; pDataSource->CacheData(CF_BITMAP, &stgm); LPDATAOBJECT lpDataObject = (LPDATAOBJECT)pDataSource->GetInterface(&IID_IDataObject); Используя возвращаемое lpDataObject а так же другие объекты, Вы можете добавить объект в RichEdit. Далее показан второй метод: class CImageDataObject : IDataObject
{
public:
// Это статическая функция передающая указатель на IRochEditOle
// и дескриптор bitmap.
// После добавления данной функции, изображение будет добавлено
// в текущую позицию RichEdit
//
static void InsertBitmap(IRichEditOle* pRichEditOle,
HBITMAP hBitmap);
private:
ULONG m_ulRefCnt;
BOOL m_bRelease;
// Данные, которые будут помещены в richedit
//
STGMEDIUM m_stgmed;
FORMATETC m_fromat;
public:
CImageDataObject() : m_ulRefCnt(0) {
m_bRelease = FALSE;
}
~CImageDataObject() {
if (m_bRelease)
::ReleaseStgMedium(&m_stgmed);
}
// Методы интерфейса IUnknown
//
STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
{
if (iid == IID_IUnknown || iid == IID_IDataObject)
{
*ppvObject = this;
AddRef();
return S_OK;
}
else
return E_NOINTERFACE;
}
STDMETHOD_(ULONG, AddRef)(void)
{
m_ulRefCnt++;
return m_ulRefCnt;
}
STDMETHOD_(ULONG, Release)(void)
{
if (--m_ulRefCnt == 0)
{
delete this;
}
return m_ulRefCnt;
}
// Методы интерфейса IDataObject
//
STDMETHOD(GetData)(FORMATETC *pformatetcIn,
STGMEDIUM *pmedium) {
HANDLE hDst;
hDst = ::OleDuplicateData(m_stgmed.hBitmap,
CF_BITMAP, NULL);
if (hDst == NULL)
{
return E_HANDLE;
}
pmedium->tymed = TYMED_GDI;
pmedium->hBitmap = (HBITMAP)hDst;
pmedium->pUnkForRelease = NULL;
return S_OK;
}
STDMETHOD(GetDataHere)(FORMATETC* pformatetc,
STGMEDIUM* pmedium ) {
return E_NOTIMPL;
}
STDMETHOD(QueryGetData)(FORMATETC* pformatetc ) {
return E_NOTIMPL;
}
STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* pformatectIn ,
FORMATETC* pformatetcOut ) {
return E_NOTIMPL;
}
STDMETHOD(SetData)(FORMATETC* pformatetc ,
STGMEDIUM* pmedium ,
BOOL fRelease ) {
m_fromat = *pformatetc;
m_stgmed = *pmedium;
return S_OK;
}
STDMETHOD(EnumFormatEtc)(DWORD dwDirection ,
IEnumFORMATETC** ppenumFormatEtc ) {
return E_NOTIMPL;
}
STDMETHOD(DAdvise)(FORMATETC *pformatetc,
DWORD advf,
IAdviseSink *pAdvSink,
DWORD *pdwConnection) {
return E_NOTIMPL;
}
STDMETHOD(DUnadvise)(DWORD dwConnection) {
return E_NOTIMPL;
}
STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise) {
return E_NOTIMPL;
}
// Другие вспомогательные функции
//
void SetBitmap(HBITMAP hBitmap);
IOleObject *GetOleObject(IOleClientSite *pOleClientSite,
IStorage *pStorage);
};
Приведённая реализация IDataObject специально расчитана на хранение дескриптора HBITMAP. Чтобы вставить картинку в RichEdit, достаточно вызвать функцию CImageDataObject::InsertBitmap. Функция имеет два параметра: IRichEditOle* pRichEditOle : Указатель на интерфейс IRichEditOle для элемента управления RichEdit. Вы можете использовать метод GetRichEditOle() в MFC классе CRichEditCtrl для получения этого указателя или следующий код: ::SendMessage((HWND)m_ctlRichText.GetHwnd(), EM_GETOLEINTERFACE, 0, (LPARAM)&m_pRichEditOle); HBITMAP hBitmap : дескриптор изображения. Класс отвечает за закрытие и освобождение ресурсов, занимаемы дескриптором, поэтому не закрывайте его самостоятельно. DownloadsDownload demo project - 55 Kb
|