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

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>
            99在线精品观看| 亚洲高清不卡av| 亚洲欧美日韩国产精品| 99精品欧美一区二区三区综合在线| 欧美va天堂在线| 99热免费精品| 亚洲午夜精品在线| 国产无一区二区| 欧美国产日韩一区二区| 欧美精品日韩综合在线| 亚洲视频在线观看一区| 制服丝袜亚洲播放| 禁久久精品乱码| 亚洲国产高清一区二区三区| 欧美激情一区二区三区在线视频观看 | 欧美在线精品一区| 久久久久久久欧美精品| 亚洲日本免费| 亚洲欧美国产视频| 亚洲日本免费电影| 午夜免费久久久久| 亚洲精品三级| 欧美一级专区| 亚洲欧洲日夜超级视频| 亚洲一区不卡| 亚洲区一区二区三区| 国产精品99久久久久久人| 黄色一区三区| 一本久久综合亚洲鲁鲁五月天| 国产一区三区三区| 99在线视频精品| 在线国产日韩| 欧美亚洲在线播放| 一区二区三区不卡视频在线观看| 午夜精品视频一区| 亚洲视频图片小说| 免费看成人av| 美女尤物久久精品| 国产精品永久| 一本色道久久加勒比88综合| 91久久精品国产91久久性色| 欧美亚洲在线视频| 亚洲欧美日韩精品久久亚洲区 | 久久免费视频网站| 久久精品成人一区二区三区蜜臀| 欧美日本免费| 亚洲国产福利在线| 在线成人欧美| 久久精品人人| 久久久国产一区二区| 国产精品久久夜| 洋洋av久久久久久久一区| 亚洲激情视频网| 久久久91精品国产| 久久久久91| 国产一区二区三区成人欧美日韩在线观看 | 99在线精品观看| 日韩一级在线| 欧美精品日韩www.p站| 亚洲国产精品成人久久综合一区 | 欧美国产日韩一区二区三区| 美女网站久久| 亚洲国产精品va| 毛片一区二区三区| 亚洲第一黄色网| 亚洲欧洲日夜超级视频| 欧美成人第一页| 亚洲国产日韩欧美| 一本久道久久久| 欧美视频中文在线看 | 亚洲乱码国产乱码精品精98午夜| 亚洲人成网站色ww在线| 欧美日韩国产成人精品| 99re这里只有精品6| 香港久久久电影| 韩国成人精品a∨在线观看| 久久偷看各类wc女厕嘘嘘偷窃| 久久午夜电影| 亚洲国产成人av好男人在线观看| 麻豆精品91| 亚洲精品中文字幕在线观看| 中文在线不卡视频| 国产欧美日韩| 久久综合久久综合久久综合| 亚洲精品永久免费精品| 性感少妇一区| 亚洲国产精品va在线观看黑人 | 亚洲午夜三级在线| 久久夜色撩人精品| 日韩视频在线观看免费| 国产精品九九| 久久婷婷一区| 亚洲视频精品在线| 欧美成人精品激情在线观看| 99精品视频免费观看| 国产伦精品一区二区三区免费迷| 久久久www成人免费无遮挡大片| 欧美成黄导航| 亚洲免费在线视频| 最新热久久免费视频| 欧美偷拍一区二区| 久久精品国产亚洲aⅴ| 亚洲人成人99网站| 欧美亚洲一区二区在线观看| 亚洲国产天堂久久综合| 国产欧美日韩激情| 欧美精品一区二区蜜臀亚洲| 欧美一级久久久| 亚洲免费观看高清完整版在线观看熊 | 欧美日韩一区二区免费视频| 欧美在线3区| 日韩午夜激情av| 久久久青草婷婷精品综合日韩| 日韩一本二本av| 国产在线观看一区| 国产精品美女久久| 欧美激情精品久久久久久久变态 | 久久综合导航| 欧美一二三区精品| 一个色综合av| 亚洲精品久久视频| 欧美成年人网| 久久综合九色综合久99| 欧美一级大片在线观看| 制服诱惑一区二区| 亚洲日本激情| 亚洲国产精品va在线看黑人动漫| 国产精品五月天| 欧美日韩中文字幕精品| 欧美国产精品一区| 久久免费99精品久久久久久| 欧美亚洲三级| 欧美亚洲免费高清在线观看| 亚洲婷婷综合久久一本伊一区| 亚洲精品1区| 亚洲国产美女久久久久| 欧美高潮视频| 欧美激情在线| 欧美激情一二区| 亚洲高清不卡一区| 亚洲国产欧美在线| 亚洲人人精品| 日韩视频在线一区| 一区二区三区鲁丝不卡| 一本色道久久88综合亚洲精品ⅰ| 亚洲另类自拍| 亚洲网站在线| 午夜在线成人av| 久久av老司机精品网站导航| 欧美一区二区大片| 久久久免费av| 欧美va亚洲va日韩∨a综合色| 六月婷婷久久| 欧美精品久久99| 欧美色区777第一页| 国产精品久久久久久影院8一贰佰| 国产精品麻豆va在线播放| 国产麻豆精品久久一二三| 国产亚洲一区二区在线观看 | 一区二区日韩精品| 午夜精品久久久久影视| 午夜精品久久久久久99热| 久久精品免费电影| 欧美丰满少妇xxxbbb| 亚洲精品影视| 欧美一区二区在线观看| 麻豆国产精品一区二区三区| 欧美日本一区二区三区| 国产精品永久免费视频| 亚洲高清免费| 亚洲欧美精品在线观看| 老鸭窝毛片一区二区三区| 亚洲精品国产精品国自产观看| 在线午夜精品自拍| 久久久精品性| 国产精品v亚洲精品v日韩精品| 国产欧美一区二区精品秋霞影院| 一区在线视频| 亚洲男女自偷自拍| 女仆av观看一区| 亚洲一二三区精品| 欧美国产精品中文字幕| 国产伦一区二区三区色一情| 亚洲精品1234| 久久久精品午夜少妇| 日韩一级免费| 老司机久久99久久精品播放免费| 欧美视频你懂的| 亚洲国产午夜| 久久久国产精品亚洲一区 | 久久久久久久久岛国免费| 欧美视频官网| 亚洲区欧美区| 免费观看亚洲视频大全| 亚洲在线成人| 欧美三级电影精品| 一本色道久久精品| 亚洲高清毛片| 久久亚洲精品一区| 国产一区二区三区av电影 |