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

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>
            亚洲人成网站影音先锋播放| 国产日韩欧美日韩| 国产精品99久久99久久久二8 | 亚洲视频碰碰| 女人色偷偷aa久久天堂| 欧美日韩亚洲一区二区| 性欧美超级视频| 欧美日韩国产成人在线免费| 午夜在线精品| 欧美日韩午夜激情| 亚洲国产小视频在线观看| 欧美成人午夜视频| 免费不卡欧美自拍视频| 国产午夜精品一区理论片飘花| 久久久亚洲综合| 国产日韩欧美91| 一本色道88久久加勒比精品 | 欧美与黑人午夜性猛交久久久| 国产一区二区看久久| 99精品视频网| 午夜精品一区二区三区四区| 久久理论片午夜琪琪电影网| 影音欧美亚洲| 亚洲在线观看| 欧美黄色免费网站| 国产精品福利影院| 欧美激情视频一区二区三区不卡| 欧美成人精品高清在线播放| 9久草视频在线视频精品| 国产精品久久久久91| 久久亚洲精品中文字幕冲田杏梨| 99国产精品99久久久久久| 久久久五月婷婷| 亚洲午夜羞羞片| 亚洲三级免费| 国内成人精品2018免费看 | 亚洲电影免费观看高清完整版| 欧美精品七区| 看片网站欧美日韩| 欧美在线视频网站| 亚洲欧美日韩在线| 欧美日韩久久精品| 亚洲欧美日韩在线播放| 久久久精品午夜少妇| 国产精品九九久久久久久久| 亚洲无线视频| 伊人久久噜噜噜躁狠狠躁 | 美日韩精品视频| 久久综合久久综合这里只有精品| 在线成人激情| 国产精品久久久久免费a∨大胸| 欧美在线观看你懂的| 欧美成人精品激情在线观看| 亚洲国产午夜| 国产精品嫩草99a| 久久久久国产精品一区| 99综合在线| 久久国内精品自在自线400部| 亚洲高清不卡av| 欧美性色aⅴ视频一区日韩精品| 亚洲精品一区二区在线观看| 欧美一区二区精美| 亚洲欧洲日产国产网站| 国产精品一区一区| 鲁大师成人一区二区三区| 亚洲性线免费观看视频成熟| 欧美激情亚洲综合一区| 久久久国产视频91| 亚洲欧美在线免费| 欧美精品系列| 亚洲午夜精品视频| 欧美成人一区二区三区片免费| 久久久久在线观看| 欧美影院一区| 久久久中精品2020中文| 亚洲视频福利| 久热精品在线视频| 欧美日本一区二区三区| 先锋影音国产一区| 日韩一级大片在线| 亚洲国产高清一区| 女生裸体视频一区二区三区| 久久久久国内| 欧美成人中文字幕| 亚洲每日在线| 亚洲一区二区三区四区中文| 亚洲大片在线| 亚洲午夜女主播在线直播| 国产精品日韩一区| 亚洲精品国精品久久99热| 国产主播一区二区三区| 亚洲国语精品自产拍在线观看| 日韩视频在线观看免费| 国产精品高清网站| 欧美在线视频观看| 亚洲第一级黄色片| 亚洲欧美日本在线| 在线观看视频欧美| 欧美视频在线看| 久久成人国产| 久久成人免费日本黄色| 欧美另类综合| 欧美亚洲一区三区| 91久久久久| 午夜视频在线观看一区| 精品成人一区| 国产精品久久久99| 蜜臀久久99精品久久久久久9| 中文日韩电影网站| 免费在线一区二区| 午夜精品久久久久久久99水蜜桃| 亚洲国产成人精品女人久久久 | 欧美一级久久| 亚洲人在线视频| 国产欧美日韩视频在线观看| 欧美精品久久99| 久久精品国产精品亚洲综合 | 久久久久久久综合日本| 99精品热视频只有精品10| 国内精品久久久久久久影视蜜臀| 欧美日韩国产综合视频在线观看中文 | 亚洲视频精品在线| 91久久久国产精品| 国内外成人在线| 国产精品中文字幕欧美| 欧美日韩国产美女| 欧美电影在线| 免费观看成人| 久久久久青草大香线综合精品| 亚洲综合二区| 亚洲一区一卡| 亚洲视频成人| 一区二区精品国产| 夜夜爽www精品| 91久久在线播放| 亚洲国产精品一区二区第一页| 久久综合久久综合久久综合| 久久精品国产精品| 久久精品免费看| 久久精品视频在线免费观看| 欧美在线视频全部完| 欧美亚洲视频在线看网址| 久久久国产精品一区二区三区| 91久久精品www人人做人人爽| 18成人免费观看视频| 伊人春色精品| 亚洲黄色有码视频| 亚洲激情一区二区| 99国内精品久久| 亚洲视频网在线直播| 亚洲午夜久久久久久尤物| 亚洲一区二区视频在线观看| 亚洲综合色婷婷| 欧美一区二区视频免费观看| 久久成人免费电影| 女仆av观看一区| 亚洲第一偷拍| 亚洲麻豆国产自偷在线| 在线一区二区视频| 欧美一区二区在线| 免费日韩精品中文字幕视频在线| 欧美激情久久久| 国产精品日韩欧美一区二区三区 | 久久人人爽国产| 欧美91视频| 国产精品极品美女粉嫩高清在线| 国产精品一区二区三区久久久| 国产伦精品一区二区三区四区免费 | 亚洲午夜未删减在线观看| 欧美一级日韩一级| 欧美成年人视频网站| 亚洲精品欧美日韩专区| 亚洲欧美日韩国产一区| 久久一区二区三区四区| 欧美精品电影在线| 国产一区二区久久| 一本一本a久久| 久久夜色精品国产亚洲aⅴ| 最新亚洲电影| 久久福利电影| 欧美日韩三级视频| 黄色国产精品| 这里只有精品视频| 久久蜜桃精品| 一区二区三区欧美在线| 日韩午夜免费| 国产精品国产三级国产普通话三级| 国产午夜精品麻豆| 亚洲视频视频在线| 欧美波霸影院| 亚洲欧美视频| 欧美天天在线| 最新国产成人在线观看| 欧美制服丝袜| 亚洲免费电影在线观看| 久久久一本精品99久久精品66| 国产精品久久9| 一区二区久久| 亚洲高清在线观看| 久久国产日韩|