Two days ago I saw an article on how to add a dynamic GIF map in the Richeditctrl control, more interesting. Last year, I used the old version of QQ to simulate it, and I only solved the insertion BMP and lexical analysis, and later did not continue.
The article on 9CBS is adopted to implement the ActiveX object provided by the Gifanimator class provided by the Tencent QQ Band IMAGEOLL.DLL to implement this feature. This object exposes an IGIFANIMATOR interface, the specific definition is as follows:
Interface igifanimator: idispatch {
HRESULT LOADFROMFILE ([In] BSTR filename;
HRESULT TRIGGERFRAMECHANGE ([OUT, RETVAL] VARIANT_BOOL * PBCHANGED;
HRESULT GETFILEPATH ([OUT, RETVAL] BSTR * PFILEPATH);
HRESULT SHOWTEXT ([in] bstr text);
}
An example is given in 9CBS, poured into the COM class in the Import mode, and gives it to the Richedit. However, I don't like this way, I have built one yourself.
Below is a class created by creating classes from the type library, relatively simple.
#include
Define_guid (CLSID_GIFANIMATOR,
0x06ada938, 0x0fb0, 0x4bc0, 0xb1,0x9b, 0x
0A
0x38, 0xAb, 0x17, 0xf1,0x82);
Define_guid (IID_IGIFANIMATOR,
0x
0C
1cf2df, 0x
05A
3,0x4fef, 0x
8C
0xD4, 0xF5, 0xcf, 0xc4, 0x35, 0x
5A
, 0x16);
Class CGIFANIMATOR: PUBLIC COLEDISPATCHDRIVER
{
PUBLIC:
CGIFANIMATOR () {} // Call the ColedispatchDriver default constructor
CGIFANIMATOR (LPDISPATCH PDISPATCH): COLEDISPATCHDRIVER (PDISPATCH) {}
CGIFANIMATOR (Const CGIFANIMATOR & DISPATCHSRC): COLEDISPATCHDRIVER (DispatchSrc) {}
// Operation
PUBLIC:
// gifanimator method
PUBLIC:
Void LoadFromfile (LPCTSTR FileName) {
Static Byte PARMS [] = VTS_BSTR;
Invokehelper (0x1, Dispatch_method, VT_EMPTY, NULL, PARMS, FileName);
}
Bool triggerframechange () {
Bool result;
Invokehelper (0x2, Dispatch_Method, Vt_Bool, (void *) & result, null;
Return Result;
}
CString getFilePath () {
CSTRING RESULT;
Invokehelper (0x3, Dispatch_Method, vt_bstr, (void *) & results, null);
Return Result;
}
Void ShowText (lpctstr text) {
Static Byte PARMS [] = VTS_BSTR;
Invokehelper (0x4, Dispatch_method, VT_EMPTY, NULL, PARMS, TEX);
}
}
By encoding, the above four functions are simple to test, each function is as follows: 1, void loadFromfile (LPCTSTR FileName)
Loading the file to the display to the control, the file is image type, not limited to GIF format. Throw an exception while failing.
2, BOOL Triggerframechange ()
Send a message, the dynamic GIF moves. There is a problem in the dialog box, you can activate it by sending a WM_PAINT message to the parent window.
3, cstring getfilepath ()
Returns the name of the loaded file.
4, Void ShowText (LPCTSTR Text)
There was no measurement, but after calling, the dynamic GIF did not move.
The code given below, inserts the control into the RicheDit control.
Bool Cimagericheditctrl :: Insertgifanimator (LPCTSTR LPSZGIFNAME)
{
CGIFANIMATOR Animator;
IStorage * LPStorage = null;
IoleObject * lpoleObject = NULL;
LPLOCKBYTES LPLOCKBYTES = NULL;
IoleClientSite * lpoleclientsite = null;
Iricheditole * LprichEditole = NULL;
CLSID CLSID;
Reobject reobject;
LprichEditole = getiricheditole ();
IF (lprichditole == null) Return False;
Bool Bret = Animator.created ;;;;;;;;;;;;;;;;;;
IF (Bret == false) {
LprichEditole-> Release ();
Return False;
}
Try {
Animator.LoadFromFile (LPSZGIFNAME); / l 异 异 异
HRESULT HR = animator.m_lpdispatch-> queryinterface (& lpoleObject);
IF (hr! = s_ok)
AFXTHROWEEXCEPTION (HR);
HR = lpoleObject-> getuserclassid (& clsid);
IF (hr! = s_ok)
AFXTHROWEEXCEPTION (HR);
HR = :: CreateilockBytesonhglobal (Null, True, & lplockbytes);
IF (hr! = s_ok)
AFXTHROWEEXCEPTION (HR);
ASSERT (LPLOCKBYTES! = NULL);
HR = :: StegcreatedocfileonIlockBytes (LPLOCKBYTES,
STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, & LPSTORAGE
IF (hr! = s_ok)
{
Verify (LPLOCKBYTES-> Release () == 0);
LPLOCKBYTES = NULL;
AFXTHROWEEXCEPTION (HR);
}
LprichEditole-> getClientSite (& LPOLECLIENTSITE); ZeromeMory (& Reobject);
Reobject.cbstruct = sizeof (reobject);
Reobject.clsid = CLSID;
Reobject.cp = reo_cp_selection;
Reobject.dvaspect = dvaspect_content;
Reobject.dwflags = reo_belowbaseline;
Reobject.poleobj = lpoleObject;
Reobject.polesite = lpoleclients;
Reobject.pstg = lpStorage;
HR = lpricheditole-> INSERTOBJECT (& REOBJECT);
IF (hr! = s_ok)
AFXTHROWEEXCEPTION (HR);
OlesetContainedObject (LPoleObject, true);
// Bret = animator.triggerframechange ();
// The role is updated to make the ActiveX control, but the controls in the dialog are invalid.
// If this function is called in OnInitDialog, this message cannot be processed, and it may not be dynamically displayed
SendMessage (wm_paint, 0,0);
}
Catch (ColeException * e)
{
Trace (_T ("cimagericheditctrl :: insertgifanimator () OleException
CODE:% D "), E-> m_sc);
E-> delete ();
Bret = false;
}
// Release the interface
LprichEditole-> Release ();
IF (lpoleObject! = null) lpoleObject-> release ();
IF (LPOLECLIENTSITE! = null) lpoleclientsite-> release ();
IF (LPStorage! = null) lpstorage-> release ();
Return Bret;
}
In this way, by calling insertgifanimator, an image file can be inserted into the RicheDit control, and if it is a dynamic GIF, it can be moved. For chat, the effect is better.
So how is this control? Through analysis, the technical points required to achieve controls are as follows:
1, must be an ActiveX control, which can be generated with an ATL template, EASY.
2, used to insert a lot of control instances, in order to use the system resources as much as possible, you must be WNDEss controls.
3. In order to dynamically display the GIF and TIFF files, the clock must be used (the thread occupies too large).
4. In order to display all image files, GDIPLUS is used here to simplify the operation of the image.
5. In order to support the UNDO operation, dynamic display must be processed after processing UNDO.
In the above operation, relatively difficult is the clock processing and UNDO recovery operations.
After a few days of hard work, I also wrote a control DynamicGIF that supported the animation in the Richedit control. The following is the test result (after inserting 6 128 × 128 dynamic GIF files), and the qq belt's imageole.dll phase Comparison. CPU%
Memory (KB)
Number of handles
Threads
GDI
When the control is not inserted
0%
6104
94
2
59
Dynamicgif
28%
8332
118
3
69
QQ library
44%
8372
118
3
70
Test results: Resource occupation comparison