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

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>
            国产午夜亚洲精品理论片色戒| 毛片精品免费在线观看| 亚洲欧美日韩直播| 久久精品一区四区| 亚洲激情女人| 99精品福利视频| 久久国产精品一区二区三区四区 | 欲香欲色天天天综合和网| 99www免费人成精品| 亚洲欧洲美洲综合色网| 欧美日韩成人在线播放| 亚洲电影成人| 久久久久久尹人网香蕉| 亚洲影视九九影院在线观看| 欧美高清在线一区| 韩国三级电影久久久久久| 亚洲欧美偷拍卡通变态| 亚洲国产成人久久| 久久夜色撩人精品| 国产综合视频| 欧美一区中文字幕| 亚洲一区二区高清| 精品成人在线视频| 久久影院午夜论| 欧美一级专区| 国产拍揄自揄精品视频麻豆| 午夜精品久久久久久久99水蜜桃| 性感少妇一区| 国产乱码精品一区二区三区忘忧草| 亚洲色图制服丝袜| 一区二区三区高清不卡| 欧美日韩一区二区三区| 一区二区三区国产| 99国产精品久久久久久久成人热| 欧美久久久久久蜜桃| 999亚洲国产精| 欧美一区二区三区在线观看| 亚洲日本欧美| 夜夜精品视频| 亚洲黄色高清| 91久久黄色| 狠狠综合久久av一区二区老牛| 亚洲国产精品一区二区第四页av| 欧美高清在线播放| 久久夜色精品亚洲噜噜国产mv | 亚洲一区免费网站| 亚洲国产色一区| 欧美伊人影院| 亚洲高清视频的网址| 亚洲日本免费| 国产精品一区二区久久久久| 亚洲日韩成人| 亚洲承认在线| 久久久精品日韩欧美| 亚洲黄色在线观看| 久久久久久自在自线| 99国产精品| 欧美大片在线观看一区| 亚洲午夜久久久久久久久电影网| 亚洲一区二区三区欧美| 亚洲夜间福利| 欧美理论在线播放| 亚洲国产精品一区二区三区| 在线成人中文字幕| 久久精品免费播放| 久久久之久亚州精品露出| 国产精品免费电影| 亚洲第一网站| 亚洲人成在线播放网站岛国| 中文欧美日韩| 亚洲国内自拍| 农村妇女精品| 久久久久.com| 国产一区二区无遮挡| 99精品99| 午夜精品久久久久久久蜜桃app| 欧美色综合天天久久综合精品| 久久激情久久| 激情国产一区| 男女激情视频一区| 91久久在线观看| 一区二区三区成人精品| 欧美色大人视频| 亚洲女人小视频在线观看| 亚洲精品国产精品久久清纯直播 | 免费欧美在线视频| 亚洲福利在线观看| 中日韩美女免费视频网站在线观看| 欧美精品91| 欧美黄色影院| 韩国av一区二区| 欧美a级片网站| 亚洲视频一区| 久久久久久久久久码影片| 亚洲国产欧美在线人成| 欧美日韩岛国| 欧美在线三级| 最新国产成人av网站网址麻豆| 亚洲性视频h| 精品av久久707| 欧美三级日韩三级国产三级| 亚洲一区免费| 欧美激情欧美狂野欧美精品| 亚洲一区观看| 欧美视频在线观看免费| 午夜综合激情| 亚洲美女在线一区| 日韩午夜精品视频| 国产一区二区中文| 欧美日韩麻豆| 久久久久久电影| 亚洲图中文字幕| 销魂美女一区二区三区视频在线| 国产精品久久看| 免费在线亚洲欧美| 亚洲欧美日韩在线播放| 久久精品视频在线观看| 亚洲精品一二三区| 国产亚洲毛片在线| 国产精品地址| 午夜精品一区二区三区在线| 欧美激情一区二区三区四区| 欧美一区综合| 亚洲一线二线三线久久久| 伊人成人在线| 国产亚洲亚洲| 国产欧美一区二区三区久久| 欧美另类99xxxxx| 久久亚洲二区| 久久久99久久精品女同性| 亚洲一区欧美激情| 宅男噜噜噜66一区二区| 亚洲国产欧美一区二区三区同亚洲 | 亚洲精品免费看| 在线免费日韩片| 国内精品模特av私拍在线观看| 欧美调教视频| 欧美视频在线免费| 欧美精品日韩一本| 欧美激情按摩| 欧美精品免费在线观看| 欧美国产综合一区二区| 欧美国产亚洲精品久久久8v| 久久精品亚洲| 久久久久在线| 久久综合五月| 亚洲网站在线播放| 亚洲网址在线| 在线亚洲欧美视频| 亚洲免费视频成人| 亚洲综合999| 欧美伊人久久久久久午夜久久久久 | 久久九九国产精品怡红院| 午夜久久tv| 久久精品一区二区| 噜噜噜91成人网| 亚洲午夜精品网| 亚洲男人的天堂在线| 午夜日韩电影| 久久久久亚洲综合| 欧美国产先锋| 国产精品日韩在线观看| 欧美高清hd18日本| 欧美精品粉嫩高潮一区二区| 欧美日韩日日骚| 国产精品久久久久免费a∨大胸| 国产精品实拍| 亚洲成人原创| 正在播放欧美视频| 欧美一区二区三区四区在线观看| 欧美中日韩免费视频| 亚洲一区二区三区在线观看视频| 亚洲午夜羞羞片| 久久久噜噜噜| 亚洲欧洲综合| 亚洲一区一卡| 免费亚洲一区二区| 国产精品美女久久久久久久| 好看的日韩av电影| 99re热精品| 久久人人精品| 日韩一二三在线视频播| 欧美在线播放一区| 欧美美女操人视频| 国产一区二区你懂的| 亚洲精品久久久久| 久久国产精品99国产精| 亚洲欧洲日韩女同| 久久精品中文字幕一区二区三区| 欧美国产在线电影| 韩国福利一区| 亚洲欧美激情四射在线日 | 性欧美精品高清| 欧美肥婆在线| 国产欧美精品在线播放| 亚洲视频 欧洲视频| 欧美~级网站不卡| 91久久久久久久久久久久久| 欧美亚洲在线视频| 欧美三级特黄|