Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 августа!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



Давно заметил, что всё-таки языки С/C++ это не самый лучший вариант программирования под Windows. Сейчас появилась масса более современных и удобных языков, например тот же Python - кроссплатформенный язык, очень легок в изучение. Я его изучил буквально за несколько дней по этому курсу - ссылка. Автор постарался, там видеоуроки на удивление легкие и понятные.

Вставляем 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 : дескриптор изображения. Класс отвечает за закрытие и освобождение ресурсов, занимаемы дескриптором, поэтому не закрывайте его самостоятельно.

Downloads

Download demo project - 55 Kb
Download source - 3 Kb



<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS