基于Duilib控件库实现的仿qq表情选择框(整理)

时间:2024-03-03 07:30:39

      闲下来,研究下Duilib富文本框的显示图片的功能,通过参考共享demo里的OLE gif,制作相当炫的qq表情选择框,效果如下:

                                     


      但此demo使用的UIRichEdit进行了一些处理,而256版本的Duilib并没有做这个修改,现在将最近用到的富文本显示图片的功能整理一下,除对UIRichEdit添加CRichEditOleCallback类外,还需要用到一个GifSmiley动态库。

      现将实现方式整理如下:

a、改一下Duilib256版本下UIRichEdit.cpp,UIRichEdit.h两个文件,具体如何改,可以下载这两个文件比对一下;

b、下载GifSmiley.dll,这里有源码可以编译一个出来;

c、调用的cpp里加入:

View Code
  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