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

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>
            久久黄色网页| 亚洲电影免费观看高清完整版在线| 亚洲日本激情| 国产精品国产精品| 亚洲制服欧美中文字幕中文字幕| 在线中文字幕一区| 国产欧美在线| 麻豆国产精品一区二区三区| 免费在线成人| 亚洲综合不卡| 久久国内精品自在自线400部| 亚洲国产成人精品久久| 亚洲精品一区二区三区不| 国产精品乱码一区二三区小蝌蚪| 久久精品国产一区二区三| 久久久综合香蕉尹人综合网| 亚洲精品国产视频| 亚洲伊人伊色伊影伊综合网 | 亚洲国产精品va| 欧美性猛交一区二区三区精品| 欧美一区二区性| 欧美国产日韩亚洲一区| 久久精品国产v日韩v亚洲 | 免费在线亚洲| 午夜国产精品视频| 免费观看久久久4p| 欧美在线视频全部完| 男女av一区三区二区色多| 香蕉成人久久| 你懂的国产精品| 久久成年人视频| 欧美日韩一区二区三区免费看| 久久久精品视频成人| 欧美色图天堂网| 美女日韩欧美| 国产精品永久| 一本色道婷婷久久欧美| 亚洲国产高清高潮精品美女| 亚洲一区二区三区四区视频| 亚洲精品综合精品自拍| 久久成人一区| 欧美一级视频精品观看| 欧美日韩精品一区| 欧美激情综合色| 好看的日韩av电影| 欧美一级专区免费大片| 亚洲一区三区视频在线观看| 欧美不卡一区| 欧美激情综合| 91久久国产综合久久蜜月精品 | 久久精品网址| 久久久久国产一区二区三区| 国产精品观看| 亚洲五月婷婷| 亚洲免费一区二区| 国产精品magnet| 日韩系列在线| 亚洲神马久久| 欧美日韩在线一区| 99成人在线| 亚洲影音一区| 国产精品视频久久| 亚洲综合色激情五月| 性欧美大战久久久久久久免费观看| 欧美日韩亚洲一区二区三区| 99v久久综合狠狠综合久久| 在线亚洲精品| 国产精品高精视频免费| 亚洲一区免费| 久久久久久久999精品视频| 国产三级精品在线不卡| 欧美综合国产| 欧美成人精品一区| 亚洲精选久久| 欧美色中文字幕| 中文亚洲视频在线| 欧美在线高清视频| 精品成人在线观看| 久久综合久久综合这里只有精品| 欧美丰满少妇xxxbbb| 在线一区亚洲| 国产欧美日韩一区二区三区在线观看| 亚洲天堂成人在线视频| 久久久久久久97| 亚洲激情综合| 欧美视频官网| 久久精品成人一区二区三区| 蜜桃精品久久久久久久免费影院| 亚洲人成人一区二区在线观看| 欧美精品在线视频观看| 亚洲一区二区黄| 欧美成人黑人xx视频免费观看| 亚洲美女在线一区| 国产精品男gay被猛男狂揉视频| 欧美一级成年大片在线观看| 欧美激情久久久久久| 亚洲免费在线观看| 亚洲国产精品123| 欧美日韩精品一区二区| 久久精品欧美日韩| 亚洲老司机av| 美女久久一区| 性高湖久久久久久久久| 91久久久精品| 国产一区二区久久久| 欧美精品在欧美一区二区少妇| 欧美一区二区三区日韩| 亚洲美女诱惑| 欧美成人黑人xx视频免费观看| 性xx色xx综合久久久xx| 亚洲精品一二三| 国产真实久久| 国产精品视频yy9099| 欧美国产精品| 久久久久免费视频| 亚洲综合精品四区| 亚洲九九九在线观看| 你懂的国产精品永久在线| 亚洲欧美日韩网| 一区二区三区 在线观看视频| 在线观看精品| 国内不卡一区二区三区| 国产精品久久久久毛片大屁完整版 | 亚洲一级片在线看| 日韩视频中文| 亚洲黄色有码视频| 尤物yw午夜国产精品视频| 国产精品一区二区三区四区五区 | 欧美日韩ab| 欧美精品成人一区二区在线观看 | 久久黄色小说| 午夜精彩国产免费不卡不顿大片| a4yy欧美一区二区三区| 亚洲人成在线免费观看| 亚洲二区免费| 亚洲国产99精品国自产| 欧美激情国产日韩| 欧美高清影院| 亚洲国产va精品久久久不卡综合| 欧美成熟视频| 亚洲国产mv| 亚洲美女色禁图| 亚洲另类一区二区| 欧美午夜性色大片在线观看| 欧美美女操人视频| 欧美日韩无遮挡| 欧美网站在线| 国产伦精品免费视频| 国产日韩欧美综合精品| 国产一区二区中文字幕免费看| 国产日韩免费| 激情六月婷婷综合| 亚洲高清精品中出| 亚洲精品一区二区三区福利| 日韩亚洲国产精品| 亚洲欧美怡红院| 久久精品国产69国产精品亚洲 | 日韩亚洲一区在线播放| 在线亚洲国产精品网站| 午夜精品久久久| 久久久久久久久久久一区| 欧美凹凸一区二区三区视频| 亚洲欧洲另类国产综合| 一区二区免费在线视频| 亚洲欧美日韩在线不卡| 久久蜜桃香蕉精品一区二区三区| 欧美va亚洲va日韩∨a综合色| 欧美日韩亚洲国产精品| 国产欧美日韩亚洲精品| 亚洲成人在线网站| 一区二区三区久久久| 欧美有码在线视频| 欧美激情精品久久久久久蜜臀| 亚洲精品日韩久久| 性久久久久久| 欧美另类视频| 激情欧美丁香| 亚洲一二三区精品| 免费在线看一区| 亚洲视频在线播放| 免费h精品视频在线播放| 国产精品你懂的| 亚洲精品黄网在线观看| 蜜桃av噜噜一区| 欧美性猛交视频| 亚洲国产一区二区三区在线播| 亚洲欧美国产高清va在线播| 欧美多人爱爱视频网站| 亚洲一区欧美一区| 欧美欧美天天天天操| 韩国久久久久| 小辣椒精品导航| 亚洲另类春色国产| 免费成人性网站| 狠狠色综合网站久久久久久久| 亚洲欧美第一页| 日韩视频免费观看| 美女诱惑一区| 黄色一区二区在线| 欧美在线免费观看视频|