//Get GifAnimator object //here, I used a smart point, so I do not need to free it hr = m_lpAnimator.CreateInstance(ImageOleLib::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);
//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; }
http://www.codeproject.com/editctrl/HyperEdit.asp
http://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/
http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/
可以知道需要调用哪些函数
给你提供两个可以显示GIF图片的例子:
Simple class for drawing pictures (jpg, tif, gif, etc...)
http://www.codeproject.com/bitmap/cpicture.aspAn Image (GIF, JPEG, BMP, ICO, WMF and EMF) Viewer
http://www.vccode.com/file_show.php?id=876
取得它的iDataobject接口,再用irichole接口插入这个dataobject。
我的实验取得了一点进展,gif倒是显示出来了,但是好像没有及时
重画,只是在richedit中输入东西时,才重画了。
谁能指点一下。
HRESULT hr;
IGif89a *IGif = NULL;
// 初始化COM
hr = CoInitialize(0);
IOleObject *FOle;
// 使用SUCCEEDED 宏并检查我们是否能得到一个接口指针
if(SUCCEEDED(hr))
{
hr = CoCreateInstance( CLSID_Gif89a, NULL, CLSCTX_INPROC_SERVER,
IID_IGif89a, (void**) &IGif);
// 如果成功,则调用AddNumbers方法,否则显示相应的出错信息
if(SUCCEEDED(hr))
{
IGif->QueryInterface(IID_IGif89a, (void**)&FOle);
}
}
IRichEditOle *RichOle;
::SendMessage(m_rich.m_hWnd, EM_GETOLEINTERFACE, 0, int(&RichOle));
ILockBytes *FLockBytes;
CreateILockBytesOnHGlobal(0,1,&FLockBytes);
IStorage *FStorage;
StgCreateDocfileOnILockBytes(FLockBytes,STGM_SHARE_EXCLUSIVE |
STGM_CREATE | STGM_READWRITE,0,&FStorage);
REOBJECT ReObject;
ZeroMemory(&ReObject, sizeof(REOBJECT));
ReObject.cbStruct=sizeof(REOBJECT); CLSID xt;
FOle->GetUserClassID(&xt);
ReObject.clsid = xt;
ReObject.cp=REO_CP_SELECTION;
ReObject.dvaspect=DVASPECT_CONTENT;
ReObject.dwFlags=REO_STATIC | REO_BELOWBASELINE | REO_LINK | REO_OPEN;
ReObject.dwUser=0;
ReObject.poleobj=FOle;
IOleClientSite *FClientSite;
RichOle->GetClientSite(&FClientSite);
ReObject.polesite=FClientSite;
ReObject.pstg=FStorage;
ReObject.sizel.cx=0;
ReObject.sizel.cy=0;
RichOle->InsertObject(&ReObject);
BSTR bstrStatus = ::SysAllocString( L"c:\\2.gif" );
IGif->put_FileName(bstrStatus);
IGif->Play();
不知道这样插入OLE对不对我研究了一下QQ显示GIF的方法,他也是通过插入OLE对象的ACTIVEX控件的名称叫Imageole.dll 提供了一个co类GifAnimator一个接口IGifAnimator,四个方法装了VC的可以用OLE View看到
[email protected]
大方一点嘛,谢谢
我看你的fole好像取得接口不对吧,是不是应该取ioleobject接口啊,试试看我看了,是和IGif一样的,那该怎么取得呢?
[email protected]
周末也许也不去了,所以,呵呵,大概要周一了。
不过和Crazyrebel(隔世情人) 的主要几个步骤基本是一样的,关键
可能有两点,1。你用的显示gif的控件是不是实现了ioldobject和idataobject
接口,我对com不是很熟,觉得一般都应该实现这两个接口,比较稳妥的方法是
先用qq的控件。2。IGif->QueryInterface(IID_IGif89a, (void**)&FOle);
iid是不是用iid_Ioleobject?
我的email:[email protected]
如果用mfc工程的话,在工程中加入那个控件后,wizard会生成一个wrapper类的。
包括相应的idl。
如果直接用我想也可以,直接createinstance不用idl。
不行的啊,在怎么你也要申明个接口指针啊
我的email:[email protected]
腾讯QQ2004Build0830对上个版本的改进: 1、2、
8、 修正了在某些机器上动画表情只显示第一帧的Bug各位有什么想法?
[email protected]
_________________________________________________________看看你的QQ目录下面又没有ImageOle.dll这个文件,看看是否注册了Activex
GifAnimator
腾讯QQ2004Build0830对上个版本的改进: 1、2、
8、 修正了在某些机器上动画表情只显示第一帧的Bug各位有什么想法?
___________________________________________________________我们不应该只是老是用QQ那个吧,自己写一个出来啊
刷新的问题我找到一个比较ugly的解决:
在ontimer里在TriggerFrameChange
后面加上
if (m_bFirstTime = TRUE)
{
m_bFirstTime = FALSE;
m_RichEdit.Invalidate(FALSE);
}各位还有没有更好的办法?
不知道是不是Gif89控件的问题,正在研究............
to hanbig:
首先感谢你的源代码:)
你的ontimer的方法不太实用,因为如果我要插入10个的话,插一个进去岂不是每次richedit都要闪一下:(
if (m_bFirstTime = TRUE)
{
m_bFirstTime = FALSE;
m_RichEdit.Invalidate(FALSE);
} KillTimer(nIDEvent);
只要一次,就kill掉这个timer,其中的gif就可以自动刷新,后加入的gif也可以。
[email protected]
[email protected]
[email protected] thanks
不是已经搞定?
_____________________________________________________________用QQ的控件是可以。我现在自己在写控件,GIF的刷新有问题,用ATL写的COM组件
用Activex测试容器可以正常显示GIF,但是插入RichEdit中却不能动起来,要用鼠标点那个图片,才动,也就是说插入到RichEdit中后不能自动刷新GIF了
最近也在写richedit刚写完加入bitmap,,gif的还没有头绪!!
现在解析也没!
hanbig() 能不能把代码发给我??万分感谢!!!
[email protected]
谢谢!
-----------------------------
希望大家讨论以下:
1,我们用的是qq的dll,如果机子上没装qq怎么办??自己包含??有没有什么版权问题啊??
2 现在只能从一个文件导入个gif?
3 现在只能insert 一个gif啊??怎么加入多个gif支持呢??
4 怎么对有字有gif的字符串解析??希望 hanbig() Crazyrebel(隔世情人) 大家帮忙讨论!
[email protected]
hanbig():
可以也给我一份吗,非常感谢!
[email protected]
Crazyrebel
你们好!能给我发一份代码吗?不胜感激![email protected]
http://blog.csdn.net/dtianx/archive/2004/11/17/184949.aspx
//#include "stdafx.h"
#include "ZJP.h"
#include "MyRichEdit.h"
#include "Richole.h"#import "E:\\Program files\\tencent\\qq\\ImageOle.dll" named_guids#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/////////////////////////////////////////////////////////////////////////////
// CMyRichEditCMyRichEdit::CMyRichEdit()
{
}CMyRichEdit::~CMyRichEdit()
{
}
BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)
//{{AFX_MSG_MAP(CMyRichEdit)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyRichEdit message handlersvoid CMyRichEdit::InsertGraphics(CString strPicPath)
{
LPLOCKBYTES lpLockBytes = NULL;
SCODE sc;
HRESULT hr;
//print to RichEdit' s IClientSite
LPOLECLIENTSITE m_lpClientSite;
//A smart point to IAnimator
ImageOleLib::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 = ::CoInitialize(NULL) ;//( 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(ImageOleLib::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();
}
}
解决问题了,太感谢了!:)
我也想要一份,谢谢!
[email protected]
[email protected]
[email protected]
谢谢您啦