青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

S.l.e!ep.¢%

像打了激速一樣,以四倍的速度運(yùn)轉(zhuǎn),開心的工作
簡(jiǎn)單、開放、平等的公司文化;尊重個(gè)性、自由與個(gè)人價(jià)值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

EDIT SHOW GIF

Posted on 2010-07-21 15:23 S.l.e!ep.¢% 閱讀(1381) 評(píng)論(0)  編輯 收藏 引用 所屬分類: VC

Introduction

Most of us know that in MSN Messenger, while chatting, we can insert animated emoticons in the chat window. That's very cool. In China, there is another famous messenger called QQ (the former OICQ) that can display GIFs as emoticons. After I read some code about RichEdit and COM, and after many tests on QQ and MSN Messenger, I got the code and put it on my blog on CSDN . :)

Background

First, how does MSN Messenger show animated emoticons? In MSN Messenger, it uses PNG files as emoticons, every PNG image shows a list of frames for a whole animation. In QQ, it uses GIFs as emoticons, so the user can customize the emoticons by changing the image, in fact, in QQ, we can send any image to a friend, and it can set to be an emoticon. If we just need to display static emoticons, you can refer to Insert any HBITMAP (Bitmap) in your RichEdit Control .

Can CRichEditCtrl display a dynamic GIF? Of course not. But CRichEditCtrl can display a COM object, then what can a COM object do? Nearly anything. So we insert a COM object into the CRichEditCtrl instance, then what we can see will be the COM object. Is this what we want to see? No. What we want to see is animated emoticons! So we display the GIF in the COM object. Then what we can see will be the emoticons.

Using the code

First we need a COM object to display a GIF and for it to be inserted in the richedit. This COM object can be developed using ATL. If you do not know how to display a GIF, you can get the Gif89a source code or CPictureEx source code. If you do not care about the size of your application, GDI+ can be your choice. If you want to ask me which of the above I used to display GIF, my answer may be "none". Because I used a DLL in QQ, this DLL is a COM object, named ImageOle.dll. It is inserted and can show GIFs (in this module, it use GDI+ to show GIFs).

Follow these steps to get your own emoticons RichEdit:

First, open your OLE/COM Viewer in Microsoft Visual Studio 6.0 Tools. Use View TypeLib... to open ImageOle.dll (you' d better register it with regsvr32.exe), then you can get the text below:

[
  uuid(0C1CF2DF-05A3-4FEF-8CD4-F5CFC4355A16),
  helpstring("IGifAnimator Interface"),
  dual,
  nonextensible
]
dispinterface IGifAnimator {
    properties:
    methods:
        [id(0x00000001), helpstring("method LoadFromFile")]
        void LoadFromFile([in] BSTR FileName);
        [id(0x00000002), helpstring("method TriggerFrameChange")]
        VARIANT_BOOL TriggerFrameChange();
        [id(0x00000003), helpstring("method GetFilePath")]
        BSTR GetFilePath();
        [id(0x00000004), helpstring("method ShowText")]
        void ShowText([in] BSTR Text);
};

This object implements an interface called IGifAnimator, we can use it to display GIFs. To see the effect, you can run ActiveX Control Test Container to test it. First invoke LoadFromFile, then TriggerFrameChange.

				//use this line to import the dll and genetate tlh and tli file.
				#import "D:\\Program files\\tencent\\qq\\ImageOle.dll" named_guids
		

ImageOle.tlh

				// Created by Microsoft (R) C/C++ Compiler Version 12.00.8168.0 (9de7951a).
				//
				// d:\myproject\msger\debug\ImageOle.tlh
				//
				// C++ source equivalent of Win32 type library
				// D:\\Program files\\tencent\\qq\\ImageOle.dll
				// compiler-generated file created 10/25/04 at 22:00:58 - DO NOT EDIT!
				#pragma once
				#pragma pack(push, 8)
				#include <comdef.h>
				namespace ImageOleLib {

//// Forward references and typedefs//struct/* coclass */ GifAnimator;
struct __declspec(uuid("0c1cf2df-05a3-4fef-8cd4-f5cfc4355a16"))
/* dual interface */ IGifAnimator;

//// Smart pointer typedef declarations//

_COM_SMARTPTR_TYPEDEF(IGifAnimator, __uuidof(IGifAnimator));

//// Type library items//struct __declspec(uuid("06ada938-0fb0-4bc0-b19b-0a38ab17f182"))
GifAnimator;
    // [ default ] interface IGifAnimatorstruct __declspec(uuid("0c1cf2df-05a3-4fef-8cd4-f5cfc4355a16"))
IGifAnimator : IDispatch
{
    //// Wrapper methods for error-handling//

    HRESULT LoadFromFile (
        _bstr_t FileName );
    VARIANT_BOOL TriggerFrameChange ( );
    _bstr_t GetFilePath ( );
    HRESULT ShowText (
        _bstr_t Text );

    //// Raw methods provided by interface//virtual HRESULT __stdcall raw_LoadFromFile (
        BSTR FileName ) = 0;
    virtual HRESULT __stdcall raw_TriggerFrameChange (
        VARIANT_BOOL * pbChanged ) = 0;
    virtual HRESULT __stdcall raw_GetFilePath (
        BSTR * pFilePath ) = 0;
    virtual HRESULT __stdcall raw_ShowText (
        BSTR Text ) = 0;
};

//// Named GUID constants initializations//extern"C"const GUID __declspec(selectany) LIBID_ImageOleLib =
    {0x710993a2,0x4f87,0x41d7,{0xb6,0xfe,0xf5,0xa2,0x03,0x68,0x46,0x5f}};
extern"C"const GUID __declspec(selectany) CLSID_GifAnimator =
    {0x06ada938,0x0fb0,0x4bc0,{0xb1,0x9b,0x0a,0x38,0xab,0x17,0xf1,0x82}};
extern"C"const GUID __declspec(selectany) IID_IGifAnimator =
    {0x0c1cf2df,0x05a3,0x4fef,{0x8c,0xd4,0xf5,0xcf,0xc4,0x35,0x5a,0x16}};

//// Wrapper method implementations//#include "d:\myproject\msger\debug\ImageOle.tli"

} // namespace ImageOleLib#pragma pack(pop)

ImageOle.tli

				// Created by Microsoft (R) C/C++ Compiler Version 12.00.8168.0 (79a657ba).
				//
				// ImageOle.tli
				//
				// Wrapper implementations for Win32 type library
				// D:\\Program Files\\Tencent\\qq\\ImageOle.dll
				// compiler-generated file created 10/11/04 at 18:24:40 - DO NOT EDIT!
				#pragma once
				//
				// interface IGifAnimator wrapper method implementations
				//
				inline HRESULT IGifAnimator::LoadFromFile ( _bstr_t FileName ) {
    HRESULT _hr = raw_LoadFromFile(FileName);
    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
    return _hr;
}

inline VARIANT_BOOL IGifAnimator::TriggerFrameChange ( ) {
    VARIANT_BOOL _result;
    HRESULT _hr = raw_TriggerFrameChange(&_result);
    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
    return _result;
}

inline _bstr_t IGifAnimator::GetFilePath ( ) {
    BSTR _result;
    HRESULT _hr = raw_GetFilePath(&_result);
    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
    return _bstr_t(_result, false);
}

inline HRESULT IGifAnimator::ShowText ( _bstr_t Text ) {
    HRESULT _hr = raw_ShowText(Text);
    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
    return _hr;
}

How can we use it? Here is the code:

    LPLOCKBYTES lpLockBytes = NULL;
    SCODE sc;
    HRESULT hr;
    //print to RichEdit' s IClientSite
    LPOLECLIENTSITE m_lpClientSite;
    //A smart point to IAnimator
    IGifAnimatorPtr    m_lpAnimator;
    //ptr 2 storage    
    LPSTORAGE m_lpStorage;
    //the object 2 b insert 2
    LPOLEOBJECT    m_lpObject;

    //Create lockbytes
    sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
    if (sc != S_OK)
        AfxThrowOleException(sc);
    ASSERT(lpLockBytes != NULL);
    
    //use lockbytes to create storage
    sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
        STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &m_lpStorage);
    if (sc != S_OK)
    {
        VERIFY(lpLockBytes->Release() == 0);
        lpLockBytes = NULL;
        AfxThrowOleException(sc);
    }
    ASSERT(m_lpStorage != NULL);
    
    //get the ClientSite of the very RichEditCtrl
    GetIRichEditOle()->GetClientSite(&m_lpClientSite);
    ASSERT(m_lpClientSite != NULL);

    try
    {
        //Initlize COM interface
        hr = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
        if( FAILED(hr) )
            _com_issue_error(hr);
        
        //Get GifAnimator object//here, I used a smart point, so I do not need to free it
        hr = m_lpAnimator.CreateInstance(CLSID_GifAnimator);    
        if( FAILED(hr) )
                _com_issue_error(hr);
        //COM operation need BSTR, so get a BSTR
        BSTR path = strPicPath.AllocSysString();

        //Load the gif
        hr = m_lpAnimator->LoadFromFile(path);
        if( FAILED(hr) )
            _com_issue_error(hr);
            
        TRACE0( m_lpAnimator->GetFilePath() );
        
        //get the IOleObject
        hr = m_lpAnimator.QueryInterface(IID_IOleObject, (void**)&m_lpObject);
        if( FAILED(hr) )
            _com_issue_error(hr);
        
        //Set it 2 b inserted
        OleSetContainedObject(m_lpObject, TRUE);
        
        //2 insert in 2 richedit, you need a struct of REOBJECT
        REOBJECT reobject;
        ZeroMemory(&reobject, sizeof(REOBJECT));

        reobject.cbStruct = sizeof(REOBJECT);    
        CLSID clsid;
        sc = m_lpObject->GetUserClassID(&clsid);
        if (sc != S_OK)
            AfxThrowOleException(sc);
        //set clsid
        reobject.clsid = clsid;
        //can be selected
        reobject.cp = REO_CP_SELECTION;
        //content, but not static
        reobject.dvaspect = DVASPECT_CONTENT;
        //goes in the same line of text line
        reobject.dwFlags = REO_BELOWBASELINE; //REO_RESIZABLE |
        reobject.dwUser = 0;
        //the very object
        reobject.poleobj = m_lpObject;
        //client site contain the object
        reobject.polesite = m_lpClientSite;
        //the storage 
        reobject.pstg = m_lpStorage;
        
        SIZEL sizel;
        sizel.cx = sizel.cy = 0;
        reobject.sizel = sizel;
        HWND hWndRT = this->m_hWnd;
        
        //Sel all text//        ::SendMessage(hWndRT, EM_SETSEL, 0, -1);//        DWORD dwStart, dwEnd;//        ::SendMessage(hWndRT, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);//        ::SendMessage(hWndRT, EM_SETSEL, dwEnd+1, dwEnd+1);//Insert after the line of text
        GetIRichEditOle()->InsertObject(&reobject);
        ::SendMessage(hWndRT, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0);
        VARIANT_BOOL ret;
        //do frame changing
        ret = m_lpAnimator->TriggerFrameChange();
        //show it
        m_lpObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_lpClientSite, 0, 
                                                             m_hWnd, NULL);
        m_lpObject->DoVerb(OLEIVERB_SHOW, NULL, m_lpClientSite, 0, m_hWnd, 
                                                                       NULL);
        
        //redraw the window to show animation
        RedrawWindow();

        if (m_lpClientSite)
        {
            m_lpClientSite->Release();
            m_lpClientSite = NULL;
        }
        if (m_lpObject)
        {
            m_lpObject->Release();
            m_lpObject = NULL;
        }
        if (m_lpStorage)
        {
            m_lpStorage->Release();
            m_lpStorage = NULL;
        }
        
        SysFreeString(path);
    }
    catch( _com_error e )
    {
        AfxMessageBox(e.ErrorMessage());
        ::CoUninitialize();    
    }

After that, your CEditCtrl can show animated GIFs.

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久婷婷国产综合尤物精品| 黄色日韩网站| 国产精品实拍| 国产欧美日韩视频一区二区三区 | 麻豆成人综合网| 亚洲国产一区在线| 在线一区视频| 久久国产毛片| 一本一本久久| 欧美激情精品久久久久久变态| 国产麻豆精品久久一二三| 在线成人中文字幕| 久久国产欧美| 久久一日本道色综合久久| 国产欧美日韩91| 卡通动漫国产精品| 欧美激情一二三区| 亚洲国产日韩综合一区| 久久国产一区二区| 老司机精品视频一区二区三区| 国产裸体写真av一区二区| 久久综合狠狠综合久久综青草| 久久久综合激的五月天| 国产农村妇女精品| 美乳少妇欧美精品| 久久嫩草精品久久久久| 一本色道久久综合亚洲精品婷婷 | 久久高清一区| 国产人成一区二区三区影院| 免费久久久一本精品久久区| 欧美成人免费全部| 亚洲精品国产精品乱码不99 | 亚洲第一精品在线| 久久精品一区二区三区不卡牛牛| 国产精品丝袜91| 欧美成人中文| 嫩草成人www欧美| 亚洲国产另类精品专区| 夜夜嗨av一区二区三区网页| 欧美女同视频| 亚洲在线一区| 亚洲图中文字幕| 国产欧美视频一区二区| 亚洲国产一区二区三区高清| 国产精品揄拍500视频| 亚洲欧洲在线免费| 欧美日韩精品一区二区三区四区 | 亚洲一区精彩视频| 久久男人av资源网站| 先锋影院在线亚洲| 亚洲一二三区在线| 亚洲精品一区在线| 亚洲最新在线| 亚洲美女视频| 欧美1区3d| 欧美va天堂| 欧美日韩一区二区三区高清| 欧美亚洲免费高清在线观看| 欧美精品一区二区高清在线观看| 美女视频黄免费的久久| 国产欧美一区二区三区视频| 亚洲在线网站| 亚洲人体一区| 午夜视频精品| 亚洲三级性片| 欧美不卡视频一区| 欧美大片免费| 亚洲精品日产精品乱码不卡| 免费91麻豆精品国产自产在线观看| 99热精品在线观看| 欧美与欧洲交xxxx免费观看| 亚洲精选视频在线| 牛牛影视久久网| 亚洲黄色成人久久久| 亚洲三级视频| 欧美日韩综合视频网址| 久久综合久久综合久久综合| 狠狠色丁香久久婷婷综合丁香| 欧美一区二区日韩| 亚洲一区二区日本| 美女999久久久精品视频| 免播放器亚洲一区| 亚洲精选一区| 国产精品久久久久久久免费软件| 牛夜精品久久久久久久99黑人| 一区二区三区在线观看国产| 亚洲一区二区精品视频| 午夜欧美不卡精品aaaaa| 欧美激情第9页| 在线视频日韩精品| 日韩视频在线观看| 欧美视频在线观看一区| 午夜精品视频在线观看| 六十路精品视频| 夜久久久久久| 国产日韩一区在线| 亚洲小说区图片区| 久热精品在线视频| 日韩一区二区精品视频| 国产精品手机在线| 免费观看在线综合色| 一区二区日韩精品| 久热精品视频在线观看| 一本久久a久久免费精品不卡| 国产精品久久久久久久app| 亚洲精品国产系列| 亚洲精品永久免费| 国产女主播一区二区三区| 久久天堂精品| 亚洲一区影院| 亚洲国产欧美在线| 久久精品国产欧美亚洲人人爽| 亚洲片区在线| 国产综合香蕉五月婷在线| 欧美中文字幕在线播放| 亚洲精品中文字幕女同| 一区二区三区欧美成人| 国产在线视频欧美| 欧美视频中文字幕在线| 久久五月天婷婷| 亚洲性视频h| 亚洲精品小视频| 蜜臀va亚洲va欧美va天堂| 亚洲免费视频观看| 国产三区精品| 欧美性片在线观看| 午夜性色一区二区三区免费视频| 亚洲国产精品一区制服丝袜| 久久久青草青青国产亚洲免观| 国产亚洲一区在线播放| 久久亚洲春色中文字幕久久久| 国产精品99久久久久久久女警 | 亚洲高清不卡av| 久热精品视频在线观看| 久久大综合网| 在线观看欧美成人| 国产色综合久久| 国产精品视频一| 国产精品制服诱惑| 国产精品视频99| 国产九九精品| 国产欧美欧洲在线观看| 国产精品美女久久| 国产精品中文字幕在线观看| 国产精品成人一区二区| 欧美三级网址| 国产精品久久久久久妇女6080| 欧美日韩亚洲国产精品| 欧美日韩综合不卡| 国产精品国产三级国产普通话蜜臀| 欧美日韩高清在线| 国产精品mm| 国产日韩一区二区三区在线播放 | 欧美大片在线观看| 欧美91精品| 欧美日韩久久不卡| 欧美体内she精视频| 国产精品久久九九| 国产亚洲精品久久久久婷婷瑜伽| 国产伦精品一区二区三区| 国产美女在线精品免费观看| 国产精品午夜国产小视频| 国产精品亚洲视频| 精东粉嫩av免费一区二区三区| 亚洲二区在线视频| 国产精品一区二区久久国产| 国产三级欧美三级日产三级99| 国内成+人亚洲| 亚洲高清在线播放| 日韩天堂在线观看| 亚洲欧美文学| 蜜桃av一区二区在线观看| 欧美激情国产日韩| 蜜桃av一区二区三区| 亚洲国产一区二区在线| 亚洲午夜视频| 久久婷婷久久一区二区三区| 欧美成人免费全部| 国产欧美一区二区三区另类精品 | 欧美丝袜一区二区| 国产亚洲精品久久久久婷婷瑜伽| 亚洲国产色一区| 亚洲愉拍自拍另类高清精品| 久久久久久9999| 欧美亚洲综合网| 欧美成人三级在线| 亚洲一区国产| 欧美顶级艳妇交换群宴| 国产酒店精品激情| 亚洲免费观看高清完整版在线观看熊| 亚洲一区二区三区四区视频| 久久综合电影| 亚洲欧美一区二区原创| 午夜视频久久久久久| 欧美成人蜜桃| 在线看国产日韩| 亚洲欧洲另类| 久久亚洲美女| 亚洲午夜高清视频| 欧美人妖另类|