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

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.¢% 閱讀(1380) 評論(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精品久久久久久不卡| 亚洲人成艺术| 亚洲黄一区二区| 国产日韩欧美一区| 宅男噜噜噜66国产日韩在线观看| 韩国av一区二区三区| 亚洲色在线视频| 亚洲四色影视在线观看| 免费亚洲婷婷| 欧美国产大片| 黄色av成人| 欧美在线地址| 久久精品理论片| 国产日本欧美视频| 亚洲小视频在线观看| 中文在线一区| 欧美日韩高清在线播放| 亚洲欧洲免费视频| 9i看片成人免费高清| 欧美bbbxxxxx| 最新日韩精品| 一区二区高清视频| 欧美日韩在线三区| 一本色道综合亚洲| 亚洲一线二线三线久久久| 欧美视频日韩视频在线观看| 亚洲欧洲一区二区天堂久久| 亚洲精品一区二区网址| 欧美不卡视频| 亚洲人久久久| 亚洲无毛电影| 国产精品永久免费观看| 午夜精品国产更新| 久久久亚洲高清| 在线成人www免费观看视频| 久久人人精品| 日韩视频中午一区| 午夜欧美精品久久久久久久| 国产嫩草影院久久久久 | 久久精品国产精品亚洲综合| 国产乱码精品一区二区三区忘忧草| 亚洲天堂成人| 久久精品国产精品亚洲综合| 永久久久久久| 欧美日韩第一区日日骚| 亚洲尤物精选| 麻豆成人小视频| 亚洲精品一区二区三| 国产精品家教| 欧美一区三区三区高中清蜜桃| 久久久久久亚洲精品杨幂换脸 | 国产精品久久久久久影视| 亚洲亚洲精品三区日韩精品在线视频| 欧美一区二区在线看| 影音先锋亚洲电影| 欧美日韩国产高清视频| 午夜激情综合网| 欧美激情按摩在线| 午夜精品亚洲| 亚洲国产精彩中文乱码av在线播放| 欧美电影免费观看大全| 亚洲一卡久久| 亚洲福利国产精品| 久久国产综合精品| 亚洲精品视频在线播放| 国产欧美一区二区三区国产幕精品 | 亚洲精品色婷婷福利天堂| 国产精品久久国产愉拍| 久久久久久有精品国产| 99国产精品国产精品毛片| 久久久亚洲人| 亚洲欧美中文在线视频| 亚洲国产日韩欧美在线99| 国产精品欧美在线| 欧美大色视频| 久久精品99久久香蕉国产色戒| 99国产精品久久久久久久成人热| 美国成人直播| 欧美专区在线| 亚洲一区二区三区高清 | 女主播福利一区| 午夜精品久久久久影视 | 欧美一区二区久久久| 日韩一二三区视频| 亚洲国产精品热久久| 久久伊伊香蕉| 欧美在线地址| 亚洲制服丝袜在线| 99在线|亚洲一区二区| 亚洲高清久久久| 狠狠久久综合婷婷不卡| 国产精品日韩欧美综合 | 欧美看片网站| 欧美不卡在线| 麻豆精品精华液| 久久精品夜色噜噜亚洲a∨| 亚洲影视九九影院在线观看| 亚洲精品午夜| 亚洲国产精品一区二区尤物区| 久久蜜臀精品av| 久久精品二区三区| 欧美综合国产| 久久不射电影网| 亚洲欧美日韩一区二区| 亚洲一区国产精品| 亚洲欧美成人网| 亚洲欧美一区二区三区久久 | 亚洲精品少妇30p| 亚洲国产精品美女| 亚洲国产aⅴ天堂久久| 亚洲福利视频一区| 亚洲国产精品久久精品怡红院 | 亚洲人成人99网站| 亚洲国产日韩综合一区| 亚洲第一福利在线观看| 欧美激情视频在线播放| 亚洲高清在线观看| 91久久精品一区二区别| 亚洲欧洲日产国码二区| 亚洲激情视频网站| 亚洲免费黄色| 亚洲欧美国产精品桃花| 性8sex亚洲区入口| 久久久久久久欧美精品| 欧美成人午夜剧场免费观看| 欧美精品色网| 国产精品视频免费一区| 国产一区二区三区免费不卡| 极品av少妇一区二区| 亚洲人成亚洲人成在线观看图片| 一级日韩一区在线观看| 亚洲免费婷婷| 麻豆乱码国产一区二区三区| 亚洲国产99精品国自产| 亚洲午夜激情| 久久在线观看视频| 欧美三级网址| 狠狠88综合久久久久综合网| 亚洲人成7777| 欧美中文在线观看国产| 亚洲风情在线资源站| 亚洲一级电影| 久久中文字幕一区| 国产精品福利久久久| 尤物九九久久国产精品的分类| 夜夜嗨网站十八久久| 久久福利一区| 亚洲日本一区二区| 久久www成人_看片免费不卡| 女仆av观看一区| 国产女精品视频网站免费 | 亚洲国产成人精品久久| 亚洲欧美乱综合| 亚洲第一福利在线观看| 亚洲欧美日本日韩| 欧美经典一区二区三区| 国产一区二区中文字幕免费看| 亚洲精品视频在线观看免费| 久久久久久久久伊人| 日韩亚洲欧美成人| 免费在线观看精品| 国产一区二区三区在线观看网站| 亚洲美女视频| 免费高清在线一区| 午夜伦欧美伦电影理论片| 欧美日韩一区二区在线观看| 亚洲第一网站| 久久久久久久久久久成人| 亚洲神马久久| 欧美人妖在线观看| 亚洲国产欧美在线人成| 久久久91精品国产一区二区精品| 一区二区激情视频| 欧美人与性动交cc0o| 亚洲国产精品第一区二区三区| 欧美一区国产二区| 在线视频精品一区| 欧美日韩中文另类| 99国产精品私拍| 欧美激情影音先锋| 免费av成人在线| 在线观看不卡av| 久久人人爽国产| 性色av香蕉一区二区| 国产欧美va欧美va香蕉在| 亚洲免费小视频| 亚洲视频视频在线| 国产精品美女久久久久久2018 | 国产精品毛片高清在线完整版| 日韩视频在线一区二区三区| 欧美激情女人20p| 欧美成人中文| 亚洲乱码国产乱码精品精可以看 | 最新国产成人在线观看| 欧美大胆人体视频| 亚洲精品综合精品自拍| 亚洲精品你懂的| 欧美国产日韩精品| 中文精品视频一区二区在线观看| 亚洲精品麻豆|