闲下来,研究下Duilib富文本框的显示图片的功能,通过参考共享demo里的OLE gif,制作相当炫的qq表情选择框,效果如下:
但此demo使用的UIRichEdit进行了一些处理,而256版本的Duilib并没有做这个修改,现在将最近用到的富文本显示图片的功能整理一下,除对UIRichEdit添加CRichEditOleCallback类外,还需要用到一个GifSmiley动态库。
现将实现方式整理如下:
a、改一下Duilib256版本下UIRichEdit.cpp,UIRichEdit.h两个文件,具体如何改,可以下载这两个文件比对一下;
b、下载GifSmiley.dll,这里有源码可以编译一个出来;
c、调用的cpp里加入:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 void CTABComments::InsertGif(CRichEditUI* pRichEdit) 2 { 3 _bstr_t bstrFileName1="c:\\Pic\\0.png"; 4 InsertAniSmiley(pRichEdit,(long)m_pPaintManager->GetPaintWindow(), bstrFileName1, ::GetSysColor(COLOR_WINDOW), 0); 5 _bstr_t bstrFileName2="c:\\Pic\\1.gif"; 6 InsertAniSmiley(pRichEdit,(long)m_pPaintManager->GetPaintWindow(), bstrFileName2, ::GetSysColor(COLOR_WINDOW), 0); 7 _bstr_t bstrFileName3="c:\\Pic\\2.gif"; 8 InsertAniSmiley(pRichEdit,(long)m_pPaintManager->GetPaintWindow(), bstrFileName3, ::GetSysColor(COLOR_WINDOW), 0); 9 _bstr_t bstrFileName4="c:\\Pic\\3.gif"; 10 InsertAniSmiley(pRichEdit,(long)m_pPaintManager->GetPaintWindow(), bstrFileName4, ::GetSysColor(COLOR_WINDOW), 0); 11 } 12 13 bool CTABComments::InsertAniSmiley(CRichEditUI* pRichEdit, long hwndHostWindow, BSTR bstrFileName, OLE_COLOR clr, INT cy) 14 { 15 GifSmiley::IGifSmileyCtrl* lpAnimator; 16 ::CoCreateInstance(GifSmiley::CLSID_CGifSmileyCtrl,NULL,CLSCTX_INPROC,GifSmiley::IID_IGifSmileyCtrl,(LPVOID*)&lpAnimator); 17 18 if (lpAnimator==NULL) 19 { 20 return false; 21 } 22 23 COLORREF backColor = (COLORREF)(clr); 24 HWND hwnd = (HWND)(hwndHostWindow); 25 HRESULT hr; 26 27 28 IRichEditOle *pRichEditOle = pRichEdit->GetRichEditOle(); 29 if (NULL==pRichEditOle) 30 { 31 return false; 32 } 33 34 LPSTORAGE lpStorage=NULL; 35 LPOLEOBJECT lpObject=NULL; 36 LPLOCKBYTES lpLockBytes = NULL; 37 LPOLECLIENTSITE lpClientSite = NULL; 38 BSTR path = NULL; 39 40 //Create lockbytes 41 hr = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes); 42 if (FAILED(hr)) 43 { 44 return false; 45 } 46 //use lockbytes to create storage 47 SCODE sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &lpStorage); 48 if (sc != S_OK) 49 { 50 lpLockBytes->Release(); 51 return false; 52 } 53 // retrieve OLE interface for richedit and Get site 54 pRichEditOle->GetClientSite(&lpClientSite); 55 56 try 57 { 58 //COM operation need BSTR, so get a BSTR 59 path = bstrFileName; 60 61 //Load the gif 62 lpAnimator->LoadFromFileSized(path, cy); 63 64 //Set back color 65 OLE_COLOR oleBackColor=(OLE_COLOR)backColor; 66 lpAnimator->put_BackColor(oleBackColor); 67 68 69 //get the IOleObject 70 hr = lpAnimator->QueryInterface(IID_IOleObject, (void**)&lpObject); 71 if (FAILED(hr)) 72 { 73 return false; 74 } 75 76 //Set it to be inserted 77 OleSetContainedObject(lpObject, TRUE); 78 79 //to insert into richedit, you need a struct of REOBJECT 80 REOBJECT reobject; 81 ZeroMemory(&reobject, sizeof(REOBJECT)); 82 83 reobject.cbStruct = sizeof(REOBJECT); 84 85 CLSID clsid; 86 hr = lpObject->GetUserClassID(&clsid); 87 88 89 //set clsid 90 reobject.clsid = clsid; 91 //can be selected 92 reobject.cp = REO_CP_SELECTION; 93 //content, but not static 94 reobject.dvaspect = DVASPECT_CONTENT; 95 //goes in the same line of text line 96 reobject.dwFlags = REO_BELOWBASELINE; 97 //reobject.dwUser = (DWORD)myObject; 98 99 //the very object 100 reobject.poleobj = lpObject; 101 //client site contain the object 102 reobject.polesite = lpClientSite; 103 //the storage 104 reobject.pstg = lpStorage; 105 106 SIZEL sizel={0}; 107 reobject.sizel = sizel; 108 109 110 LPOLECLIENTSITE lpObjectClientSite = NULL; 111 hr =lpObject->GetClientSite(&lpObjectClientSite); 112 if(FAILED(hr) || lpObjectClientSite==NULL) 113 lpObject->SetClientSite(lpClientSite); 114 115 pRichEditOle->InsertObject(&reobject); 116 //redraw the window to show animation 117 ::RedrawWindow(hwnd,NULL, NULL, RDW_INVALIDATE); 118 119 if (lpClientSite) 120 { 121 lpClientSite->Release(); 122 lpClientSite = NULL; 123 } 124 if (lpObject) 125 { 126 lpObject->Release(); 127 lpObject = NULL; 128 } 129 if (lpStorage) 130 { 131 lpStorage->Release(); 132 lpStorage = NULL; 133 } 134 135 if(lpAnimator) 136 { 137 lpAnimator->Release(); 138 lpAnimator=NULL; 139 } 140 141 } 142 catch( ... ) 143 { 144 if (lpClientSite) 145 { 146 lpClientSite->Release(); 147 lpClientSite = NULL; 148 } 149 if (lpObject) 150 { 151 lpObject->Release(); 152 lpObject = NULL; 153 } 154 if (lpStorage) 155 { 156 lpStorage->Release(); 157 lpStorage = NULL; 158 } 159 160 if(lpAnimator) 161 { 162 lpAnimator->Release(); 163 lpAnimator=NULL; 164 } 165 166 return false; 167 } 168 return true; 169 }
运行一下自己实现的效果:
可以看的出不仅支持gif,还支持png的。
下载地址:UIRichEdit.rar