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

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网站| 亚洲国产欧美在线人成| 老牛影视一区二区三区| 亚洲国产精品久久久久秋霞影院 | 亚洲人精品午夜在线观看| 欧美国产欧美综合| 亚洲一区二区三区乱码aⅴ| 日韩亚洲欧美成人一区| 国产精品午夜av在线| 久久人人爽国产| 欧美另类久久久品| 欧美一区二区日韩一区二区| 久久久www成人免费精品| 亚洲国产精品久久精品怡红院| 亚洲精品国产精品国自产在线| 国产精品盗摄久久久| 久久精品国产成人| 欧美第一黄色网| 午夜亚洲伦理| 免费黄网站欧美| 午夜精品久久久久久久蜜桃app| 欧美在线3区| 99re在线精品| 欧美一级淫片aaaaaaa视频| 日韩视频免费观看高清在线视频| 亚洲调教视频在线观看| 亚洲欧洲日韩女同| 亚洲欧美日韩直播| 99精品欧美一区二区三区综合在线| 亚洲无吗在线| 亚洲人人精品| 久久爱91午夜羞羞| 午夜亚洲一区| 欧美另类极品videosbest最新版本| 久久青草久久| 国产精品免费一区二区三区观看| 欧美高清一区二区| 国产一区二区三区自拍| 亚洲无限av看| 亚洲在线国产日韩欧美| 欧美不卡高清| 免费久久99精品国产| 国产欧美一区二区精品仙草咪 | 日韩性生活视频| 亚洲电影有码| 欧美在线视频观看免费网站| 午夜日韩在线观看| 欧美视频一区二区三区四区| 亚洲福利视频网站| 永久555www成人免费| 欧美一级播放| 欧美伊人久久| 国产欧美一区二区色老头| 99re6热在线精品视频播放速度| 亚洲国产综合在线看不卡| 久久成人国产精品| 久久亚洲图片| 一区二区三区在线视频观看| 久久国产精品久久久久久电车| 香港成人在线视频| 国产精品一区二区三区四区五区 | 夜夜精品视频一区二区| 99在线精品观看| 欧美看片网站| 亚洲视频图片小说| 欧美一区二区免费观在线| 国产欧美精品日韩| 午夜在线观看免费一区| 久久久久国内| 伊人成人在线视频| 可以看av的网站久久看| 亚洲黄色在线| 一区二区三区福利| 国产精品电影观看| 亚洲欧美日产图| 久久综合久久美利坚合众国| 亚洲第一综合天堂另类专| 欧美精品日韩| 亚洲手机在线| 老牛国产精品一区的观看方式| 在线日韩一区二区| 欧美日本簧片| 午夜宅男欧美| 欧美黄色视屏| 亚洲一区三区电影在线观看| 国产麻豆91精品| 久久女同互慰一区二区三区| 亚洲人成人99网站| 亚洲欧美成人网| 影音先锋久久久| 欧美午夜精品久久久久久孕妇 | 欧美午夜片在线观看| 午夜精品999| 亚洲国产精品t66y| 香港成人在线视频| 91久久精品国产91久久| 欧美亚州韩日在线看免费版国语版| 亚洲欧美综合一区| 亚洲国产综合91精品麻豆| 午夜欧美视频| 夜夜嗨av一区二区三区| 国产亚洲欧美另类中文| 欧美精品在线视频观看| 欧美亚洲在线| 一本色道久久综合亚洲精品不| 久久亚洲精品一区二区| 中文日韩欧美| 亚洲激情视频在线播放| 国产日韩欧美不卡| 欧美三区在线视频| 美乳少妇欧美精品| 亚洲欧美在线免费观看| 99re66热这里只有精品3直播| 你懂的视频欧美| 久久精品视频一| 亚洲在线播放电影| 91久久国产自产拍夜夜嗨| 国产一区成人| 国产精品影片在线观看| 欧美日韩mv| 欧美成人一区二区三区片免费| 亚洲欧美乱综合| 在线视频亚洲欧美| 亚洲激情综合| 欧美激情偷拍| 女女同性女同一区二区三区91| 香蕉尹人综合在线观看| 亚洲视频第一页| 日韩午夜免费视频| 亚洲人成啪啪网站| 亚洲国产精品一区二区第四页av| 国内外成人在线| 国产亚洲精品v| 国产色爱av资源综合区| 国产精品香蕉在线观看| 国产精品久久久久久久久久妞妞| 欧美日韩福利| 欧美日韩国产在线播放| 欧美日韩ab| 国产精品久久久久久久久久久久久久| 欧美激情中文字幕一区二区| 欧美精品久久一区二区| 欧美激情国产高清| 欧美日韩喷水| 国产精品福利网| 国产精品一区二区男女羞羞无遮挡| 国产精品久久久久久久app| 国产精品乱码妇女bbbb| 国产精品视频大全| 国产三区二区一区久久| 国外成人网址| 亚洲第一福利社区| 亚洲理伦在线| 亚洲欧美久久久| 久久成人精品电影| 美日韩精品免费观看视频| 欧美激情无毛| 日韩天堂av| 欧美一区二视频| 久久综合九色| 欧美日韩小视频| 国产精品综合| 亚洲高清不卡在线| 中文久久乱码一区二区| 久久久国产亚洲精品| 欧美成熟视频| 亚洲视频视频在线| 久久这里只有| 国产精品久久久久久模特| 国产一区欧美日韩| 日韩一区二区久久| 久久精品国产精品亚洲精品| 亚洲福利视频网站| 午夜精品一区二区在线观看| 久久婷婷色综合| 欧美在线91| 免费成人性网站| 国产精品黄视频| 尤物网精品视频| 亚洲综合99| 亚洲成色777777在线观看影院| 日韩午夜av电影| 久久乐国产精品| 国产精品手机视频| 亚洲欧洲综合| 久久久久久久91| 欧美激情中文不卡| 性18欧美另类| 欧美色欧美亚洲高清在线视频| 韩国av一区二区三区| 亚洲一区二区三区国产| 欧美国产第一页| 久久爱www久久做| 国产精品午夜在线观看| 亚洲一区www| 亚洲黑丝在线| 久久中文字幕导航| 韩国一区电影|