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

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>
            在线看片一区| 日韩视频一区二区三区| 国产视频丨精品|在线观看| 国产精品国产馆在线真实露脸| 欧美韩日精品| 欧美片第一页| 欧美日韩情趣电影| 欧美日韩在线视频一区二区| 欧美日韩国产页| 国产精品久久久久国产精品日日| 国产精品久久久久久久久果冻传媒| 欧美视频在线观看免费| 国产精品久久久久国产精品日日| 国产精品一区二区三区久久久| 国产欧美丝祙| 在线观看三级视频欧美| 亚洲品质自拍| 亚洲小说春色综合另类电影| 亚洲综合日韩在线| 欧美在线免费视屏| 久久综合色88| 亚洲欧洲一区| 一本色道久久综合亚洲精品小说| 亚洲午夜电影在线观看| 欧美一区二区三区的| 久久久久久午夜| 欧美精品aa| 国产精品视频九色porn| 激情成人综合网| 亚洲欧洲视频| 欧美一级理论片| 欧美成年网站| 亚洲视频1区| 久久精品视频网| 欧美日韩国产成人高清视频| 国产精品色网| 亚洲激情网址| 亚洲欧美在线磁力| 欧美成人精品在线播放| 99国产一区| 久久精品国产一区二区三| 欧美福利电影网| 国产精品有限公司| 亚洲精品欧美极品| 欧美一区二区视频网站| 亚洲第一精品影视| 亚洲一区二区三区视频播放| 久久久噜噜噜久久| 欧美午夜a级限制福利片| 韩国三级在线一区| 一卡二卡3卡四卡高清精品视频| 久久久精品动漫| 亚洲精品中文字幕女同| 久久er99精品| 欧美日韩伦理在线| 在线观看精品一区| 欧美亚洲综合久久| 亚洲激情在线激情| 久久精品国产亚洲一区二区三区 | 伊人婷婷久久| 亚洲欧洲99久久| 亚洲激情网址| 久久久噜噜噜| 国产视频一区三区| 亚洲亚洲精品在线观看 | 久久久国产亚洲精品| 国产精品福利影院| 亚洲精品专区| 蜜桃av一区| 欧美一区二区三区的| 国产精品高清免费在线观看| 亚洲黑丝一区二区| 久久久伊人欧美| 亚洲免费网址| 国产精品久久久久aaaa樱花| 亚洲免费观看在线视频| 米奇777在线欧美播放| 欧美在线亚洲综合一区| 国产精品久久久一区麻豆最新章节 | 欧美亚州一区二区三区| 亚洲激情啪啪| 欧美黄色片免费观看| 久久久999精品| 国产一区二区日韩| 久久国产主播精品| 亚洲免费人成在线视频观看| 欧美日韩一区二区三区| 亚洲免费成人av电影| 欧美激情一区二区三区在线| 久久久99精品免费观看不卡| 国内精品久久久久影院 日本资源| 午夜视频一区二区| 一区二区三区免费在线观看| 欧美午夜久久久| 宅男噜噜噜66国产日韩在线观看| 91久久综合亚洲鲁鲁五月天| 欧美成黄导航| 亚洲三级色网| 亚洲剧情一区二区| 欧美日韩成人综合| 在线视频精品| 日韩一级视频免费观看在线| 欧美日韩在线视频首页| 亚洲午夜小视频| 亚洲素人一区二区| 国产精品系列在线播放| 久久成人一区| 久久久久久久久久久一区| 1204国产成人精品视频| 欧美激情精品久久久久久大尺度 | 亚洲精品一级| 欧美日韩在线第一页| 亚洲免费一区二区| 亚洲已满18点击进入久久| 国产欧美一区在线| 久久亚洲综合色一区二区三区| 久久精品夜色噜噜亚洲a∨| 在线观看中文字幕亚洲| 欧美国产在线电影| 欧美老女人xx| 亚洲欧美激情一区| 欧美与欧洲交xxxx免费观看| 一区久久精品| 亚洲国产一区二区三区高清| 欧美另类变人与禽xxxxx| 亚洲永久免费视频| 午夜精品福利视频| 亚洲盗摄视频| 日韩网站在线观看| 国产伦一区二区三区色一情| 麻豆成人av| 欧美三级日韩三级国产三级| 久久精品国产一区二区三区免费看 | 国产精品www色诱视频| 欧美在线免费看| 欧美aⅴ99久久黑人专区| 一区二区三区成人| 午夜精品理论片| 亚洲激情在线观看| 亚洲午夜电影网| 1769国内精品视频在线播放| 亚洲精品一区在线| 国产一区二区三区直播精品电影 | 国产日韩欧美三区| 欧美国产日本韩| 国产精品免费视频观看| 免费永久网站黄欧美| 欧美色播在线播放| 久久久免费观看视频| 欧美日韩国产一区二区| 久久久久久高潮国产精品视| 欧美激情综合亚洲一二区| 欧美在线网站| 欧美精品v日韩精品v韩国精品v | 亚洲青涩在线| 欧美一区二区三区精品电影| 一二三四社区欧美黄| 久久久久久高潮国产精品视| 正在播放亚洲| 麻豆免费精品视频| 欧美尤物一区| 欧美色视频日本高清在线观看| 你懂的网址国产 欧美| 国产精品一区二区视频| 亚洲国内在线| 影音先锋中文字幕一区| 亚洲一区二区三区色| 日韩午夜免费| 久久综合网色—综合色88| 欧美一区成人| 欧美视频在线免费看| 亚洲国产精品t66y| 在线观看av一区| 欧美制服丝袜| 午夜精品久久久久久| 欧美日韩在线播放一区二区| 亚洲高清一二三区| 影音先锋中文字幕一区| 欧美一区二区在线播放| 亚洲欧美另类在线观看| 欧美激情影音先锋| 欧美国产日韩免费| 激情校园亚洲| 久久www免费人成看片高清| 午夜精品久久久久久久蜜桃app| 欧美日韩视频一区二区| 亚洲国产精品悠悠久久琪琪| 亚洲国产99| 久久综合精品一区| 女女同性精品视频| 在线观看视频免费一区二区三区| 欧美一区二区三区免费在线看| 亚洲欧洲av一区二区| 国产精品超碰97尤物18| 99精品欧美一区| 一区二区三区视频在线观看| 欧美日韩国产综合新一区| 亚洲每日更新| 亚洲一区二区三区免费观看| 欧美日韩精品一区二区三区四区|