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

S.l.e!ep.¢%

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

EDIT SHOW GIF

Posted on 2010-07-21 15:23 S.l.e!ep.¢% 閱讀(1365) 評論(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>
            狠狠综合久久av一区二区小说| 久久久综合视频| 欧美日韩在线免费观看| av成人动漫| 一本色道久久99精品综合| 国产精品成人午夜| 欧美专区亚洲专区| 久久久久国产精品厨房| 亚洲国产婷婷综合在线精品 | 国产模特精品视频久久久久 | 99re成人精品视频| 夜夜爽av福利精品导航 | 欧美精品一区二区在线观看| 亚洲天堂成人在线视频| 亚洲一区二区毛片| 一区二区三区中文在线观看| 欧美福利视频一区| 欧美先锋影音| 免费成人av在线看| 欧美日韩成人综合天天影院| 欧美一区二区日韩| 久久人人爽人人爽爽久久| 亚洲欧美久久| 激情欧美一区二区三区| 亚洲精品国产精品国自产观看浪潮 | 欧美一区二区三区久久精品茉莉花| 伊人成综合网伊人222| 亚洲毛片一区二区| 伊人久久av导航| 在线视频精品一区| 激情亚洲成人| 日韩亚洲欧美综合| 在线播放中文字幕一区| 国产精品99久久99久久久二8| 亚洲大片在线| 先锋影院在线亚洲| 中日韩在线视频| 美女图片一区二区| 久久久五月婷婷| 欧美亚男人的天堂| 亚洲国产毛片完整版| 国产一区二区三区丝袜| 99这里只有精品| 日韩视频免费大全中文字幕| 久久精品成人欧美大片古装| 午夜精品视频在线| 欧美日韩精品综合| 亚洲国产精品一区| 亚洲国产91| 久久综合色综合88| 久久伊人精品天天| 国产亚洲电影| 亚洲一区制服诱惑| 亚洲欧美大片| 国产精品久久久久久久免费软件 | 久久综合色影院| 国产一区二区三区高清播放| 亚洲一区二区成人| 亚洲欧美不卡| 国产精品久线观看视频| av成人福利| 亚洲一区免费| 欧美丝袜第一区| 一区二区高清在线| 亚洲影院在线| 国产精品一二三视频| 亚洲一区二三| 欧美一区二区私人影院日本| 国产精品一区二区在线观看不卡| 国产精品99久久久久久久久| 亚洲欧美国产精品专区久久| 国产精品劲爆视频| 亚洲免费视频一区二区| 久久国产88| 一区在线播放| 免费毛片一区二区三区久久久| 欧美大成色www永久网站婷| 亚洲国产精品成人综合色在线婷婷 | 免费在线看成人av| 亚洲国产精品尤物yw在线观看| 你懂的视频一区二区| 亚洲人成网站在线播| 亚洲永久精品国产| 国产午夜一区二区三区| 久久中文字幕导航| 亚洲日韩欧美视频| 亚洲欧美综合国产精品一区| 国产一区二区三区的电影| 久久尤物视频| 一本色道久久综合狠狠躁篇怎么玩| 亚洲在线一区二区| 国产一区二区三区在线观看网站| 麻豆国产精品一区二区三区| 一区电影在线观看| 久久精品一二三区| 亚洲精品自在久久| 国产日韩欧美夫妻视频在线观看| 久热re这里精品视频在线6| 99国产精品99久久久久久| 久久国产精品久久国产精品| 亚洲高清一区二| 国产精品色午夜在线观看| 久久婷婷成人综合色| 一区二区精品在线观看| 久久尤物电影视频在线观看| 一本色道精品久久一区二区三区| 国产欧美精品在线| 欧美精品激情在线观看| 小黄鸭精品aⅴ导航网站入口| 亚洲电影免费在线| 久久精品一区| 午夜激情亚洲| 一区二区精品在线| 激情欧美亚洲| 国产免费亚洲高清| 欧美日韩免费高清| 久色婷婷小香蕉久久| 亚洲综合精品四区| 亚洲精品少妇| 欧美激情在线观看| 久久这里只有| 久久精品国产亚洲高清剧情介绍| 亚洲小少妇裸体bbw| 亚洲国产精品黑人久久久| 国产日韩欧美高清免费| 国产精品啊啊啊| 欧美日韩国产一中文字不卡| 久热国产精品| 久久婷婷综合激情| 欧美一区影院| 欧美一级大片在线观看| 亚洲视频欧美在线| 一区二区三区高清不卡| 亚洲精品在线电影| 亚洲欧洲久久| 亚洲精品乱码| 亚洲精品国产精品国自产在线| 亚洲成人在线视频播放| 欧美风情在线观看| 女女同性女同一区二区三区91| 久久午夜精品| 欧美成人精品福利| 欧美sm重口味系列视频在线观看| 久久综合中文字幕| 久久久精品五月天| 久久香蕉精品| 欧美成人首页| 亚洲国产一区二区三区高清| 亚洲精美视频| 一本大道久久精品懂色aⅴ| 一本色道久久88亚洲综合88| 中文国产一区| 欧美在线观看你懂的| 久久精品国产一区二区三区| 久久这里只有| 欧美日韩999| 国产精品久久久999| 国产精品亚洲综合久久| 国产精品五月天| 久久综合五月天婷婷伊人| 中文欧美在线视频| 国产精品女主播在线观看| 欧美精品成人91久久久久久久| 另类av一区二区| 欧美国产欧美综合 | 欧美成人伊人久久综合网| 亚洲第一区色| 在线视频欧美一区| 欧美制服丝袜| 欧美激情精品久久久六区热门| 欧美日韩影院| 狠狠狠色丁香婷婷综合久久五月| 亚洲茄子视频| 性色一区二区三区| 欧美搞黄网站| 亚洲综合色丁香婷婷六月图片| 久久免费一区| 国产精品国产三级国产 | 欧美色图麻豆| 在线观看日韩精品| 亚洲主播在线播放| 玖玖综合伊人| 亚洲一区二区三区乱码aⅴ蜜桃女| 久久精品国产视频| 欧美视频在线不卡| 在线精品亚洲| 欧美在线观看网址综合| 亚洲国产色一区| 欧美一区二区三区精品电影| 欧美日韩国产成人在线91| 国语自产精品视频在线看抢先版结局 | 欧美视频二区| 亚洲国产老妈| 久久精品亚洲热| 夜夜嗨一区二区三区| 麻豆精品精品国产自在97香蕉| 国产精品一区二区你懂的| 亚洲精品乱码久久久久久蜜桃91 | 亚洲视频狠狠| 亚洲国产精品悠悠久久琪琪|