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

S.l.e!ep.¢%

像打了激速一樣,以四倍的速度運轉(zhuǎn),開心的工作
簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
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) 評論(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久久久久久久久久久久久| 久久精品在线免费观看| 欧美一区二区大片| 亚洲精品久久久久久久久久久久久 | 欧美成人一区在线| 欧美日韩性生活视频| 欧美中文字幕精品| 欧美精品激情blacked18| 久久成人在线| 亚洲激情另类| 久久国产福利| 欧美一区二区在线观看| 欧美激情综合五月色丁香| 日韩亚洲一区二区| 亚洲精品黄网在线观看| 欧美性大战久久久久| 欧美成在线观看| 亚洲天堂av图片| 欧美激情日韩| 欧美亚洲视频一区二区| 欧美激情一区二区三区| 国内精品一区二区三区| 亚洲一区二区高清| 99在线精品视频| 免费成人你懂的| 久久人人爽人人爽爽久久| 国产午夜精品视频免费不卡69堂| 一本综合久久| 亚洲天堂av图片| 亚洲第一区在线观看| 久久精品视频播放| 久久人91精品久久久久久不卡| 亚洲精品国产无天堂网2021| 国产女主播一区二区| 午夜精品成人在线视频| 欧美专区在线观看| 99热在这里有精品免费| 欧美伦理影院| 一区二区三区四区国产精品| 欧美成人精品在线视频| 亚洲免费播放| 国产精品久久久久毛片大屁完整版 | 久久久久久久久久久成人| 日韩视频中文| 在线观看福利一区| 久久伊伊香蕉| 欧美与黑人午夜性猛交久久久| 亚洲精品日韩欧美| 亚洲成人在线视频网站| 国产色产综合产在线视频| 欧美日韩中文字幕在线| 亚洲欧美国产毛片在线| 久久乐国产精品| 性欧美暴力猛交69hd| 国内精品久久久久影院优| 国产精品美女久久久久av超清| 欧美久久久久久久| 蜜臀a∨国产成人精品| 久久精品在线播放| 久久激情五月激情| 久久成人18免费网站| 午夜精品福利视频| 午夜欧美大尺度福利影院在线看 | 亚洲欧美另类综合偷拍| 一本久久青青| 一区二区三区鲁丝不卡| 在线视频免费在线观看一区二区| 久久精品视频免费观看| 亚洲国产一区二区视频| 在线日韩视频| 亚洲国产福利在线| 国产精一区二区三区| 美女精品自拍一二三四| 免费观看在线综合| 在线亚洲免费视频| 亚洲一区区二区| 亚洲综合色丁香婷婷六月图片| 亚洲免费视频成人| 亚洲欧美日韩精品| 欧美影院成人| 亚洲视频www| 亚洲欧美一区二区三区极速播放| 亚洲欧美综合国产精品一区| 午夜欧美理论片| 久久久国产精品一区| 久久综合伊人77777蜜臀| 欧美电影打屁股sp| 久久精品99国产精品酒店日本| 久久久久久国产精品mv| 亚洲欧美日韩精品一区二区| 欧美在线观看一区二区| 麻豆精品网站| 欧美日韩在线播放三区| 国产精品一二三| 欧美日韩在线一区二区三区| 国产精品萝li| 精品成人国产| 国产偷久久久精品专区| 在线不卡中文字幕| 一片黄亚洲嫩模| 久久精品女人天堂| 亚洲福利国产精品| 鲁大师成人一区二区三区| 亚洲福利视频一区二区| 在线亚洲欧美专区二区| 久久精品免费看| 欧美日韩极品在线观看一区| 农村妇女精品| 国产精品视频免费观看www| 一区在线影院| 亚洲影音一区| 亚洲一区二区三区在线播放| 夜夜嗨av色一区二区不卡| 欧美一区二区| 亚洲国产专区| 亚洲毛片av在线| 亚洲黄网站黄| 欧美在线精品一区| 欧美揉bbbbb揉bbbbb| 一区二区三区无毛| 亚洲欧美中文在线视频| 先锋影音国产精品| 亚洲人成在线观看| av成人免费在线| 亚洲一区二区三区四区在线观看| 另类专区欧美制服同性| 国产精品亚洲综合一区在线观看| 亚洲伦伦在线| 你懂的亚洲视频| 校园春色综合网| 欧美午夜电影一区| 日韩西西人体444www| 蜜桃精品一区二区三区| 欧美激情一区二区三区四区| 亚洲欧美日韩中文在线制服| 欧美日韩精品系列| 91久久精品美女| 亚洲视频欧美视频| 亚洲电影免费观看高清完整版| 欧美一级一区| 国产精品亚洲视频| 亚洲尤物精选| 一本久久综合亚洲鲁鲁五月天| 欧美不卡视频| 亚洲激精日韩激精欧美精品| 久久一区二区三区国产精品| 欧美成人免费va影院高清| 久久er精品视频| 国产人成精品一区二区三| 亚洲欧美视频在线| 一本大道久久a久久精二百| 欧美激情导航| 国产欧美一区二区精品秋霞影院| 亚洲一区二区三区免费视频| 亚洲精品九九| 欧美日韩精品国产| 一区二区三区国产盗摄| 久久久视频精品| 久久国产直播| 好看的日韩av电影| 亚洲欧美日韩中文播放| 欧美成人免费在线观看| 久久婷婷成人综合色| 亚洲丁香婷深爱综合| 欧美a级片网| 女仆av观看一区| 亚洲免费观看| 日韩一区二区精品在线观看| 欧美日韩免费一区二区三区视频| 在线视频中文亚洲| 一区二区三区欧美激情| 国产精品亚洲综合一区在线观看 | 亚洲天堂偷拍| 欧美福利网址| 一区二区三区四区五区视频 | 免费视频久久| 欧美夫妇交换俱乐部在线观看| 亚洲精品一区在线观看| 99国内精品| 国产乱肥老妇国产一区二| 久久免费视频在线观看| 久久一区二区三区超碰国产精品| 亚洲黄色影院| 一区二区三区国产精品| 国产日韩亚洲欧美| 欧美成人免费一级人片100| 欧美久久在线| 久久成人久久爱| 麻豆成人综合网| 亚洲欧美日韩精品一区二区 | 久久综合伊人77777蜜臀| 快播亚洲色图| 亚洲尤物视频网| 久久综合九色综合欧美就去吻| 一区二区三区欧美在线观看| 亚洲欧美日韩在线播放| 亚洲大片av| 亚洲午夜视频在线观看| 尤物九九久久国产精品的特点|