7、添加必要的成员和方法
7.1 添加成员变量
下面往CGifCtl加入些成员变量:
CComBSTR
m_strFileName;
GdiplusStartupInput
gdiplusStartupInput;
ULONG_PTR
gdiplusToken;
ImageEx*
m_pImg; //图像
效果如图:

7.2构造函数
再在CCifCtl的构造函数中加入以下代码:
GdiplusStartup(&gdiplusToken,
&gdiplusStartupInput, NULL);
m_bWndLess=true;
m_pImg=NULL;
效果如图:

7.3
FinalRelease函数
再往CGifCtl类加入一个FinalRelease函数。
void
FinalRelease()
{
GdiplusShutdown(gdiplusToken);
TimerOff();
}
效果如图:

以上添加的两个函数是用于Gdi+库的初始化。
接头就看看怎么把Gif图片显示出来。
7.4添加LoadFromFile方法
往IGifCtl接口中加入一个方法。
操作如下,选择IGifCtl,右键,选择Add Method,如图:

在Method Name中输入:LoadFromFile
在Parameters中输入:[in] BSTR FileName

点击OK.
实现LoadFromFile方法:
跳到那个方法下:

加入以下代码:
m_strFileName=FileName;
m_pImg
= new ImageEx(m_strFileName);
if
(m_pImg->IsAnimatedGif())
{
long
lFrameTime = m_pImg->GetFrameTime();
TimerOn(lFrameTime);
}
SIZEL
size5,size6;
size5.cx=m_pImg->GetWidth();
size5.cy=m_pImg->GetHeight();
m_rcPos.right=m_pImg->GetWidth()+m_rcPos.left;
m_rcPos.bottom=m_pImg->GetHeight()+m_rcPos.top;
AtlPixelToHiMetric(&size5,&size6);
SetExtent(DVASPECT_CONTENT,&size6);
if(m_spInPlaceSite!=NULL)
m_spInPlaceSite->OnPosRectChange(&m_rcPos);
FireViewChange();
效果如图:

7.5添加_OnTimer方法
再添加一个方法:_OnTimer

在_OnTimer函数中输入以下代码:
if (m_pImg != NULL)
{
m_pImg->ActiveNextFrame(); //显示下一帧
long lFrameTime =
m_pImg->GetFrameTime(); //获得下一帧的显示时间
TimerOn(lFrameTime); //修改计时器的周期为下一帧的显示时间
FireViewChange(); //刷新图片区域
}
效果如图:

7.6 修改OnDraw函数
把OnDraw函数的代码改成:
HRESULT
OnDraw(ATL_DRAWINFO& di)
{
RECT&
rc = *(RECT*)di.prcBounds;
//将剪辑区域设置为di.prcBounds指定的矩形
if
(m_pImg != NULL)
{
Graphics
graphics(di.hdcDraw);
Status
sta = graphics.DrawImage(m_pImg, rc.left,rc.top);
}
return
S_OK;
}
效果如图:

至此,这个控件的代码就写完了,编译,链接,生成控件。
8、测试
下面来测试下刚才写的那个控件。8.1 注册
先把刚写好的控件用regsvr32命令注册一下。

8.2插入控件
测试用到的是vc自带的工具ActiveX Control Test Container。
启动ActiveX Control Test Container软件。
点击工具栏上的New Control按钮

弹出以下对话框

再选择GifCtl,点击OK8.3调用方法
添加成功后,再点击Invoke Methods按钮。

弹出以下对话框,在Parameter中输入一个gif文件的路径,以下是我的gif图片的路径。G:/richedit/2.gif。输入后,点击Invoke。

可以看到控件显示gif图片了。

测试通过。
9、编写程序来调用控件GifOle.dll
9.1 创建一个MFC工程
新建一个MFC
AppWizard工程,在Project
name输入Richedit.
点击OK后,
选择Dialog based选项,点击Finish。
9.2 添加Richedit控件
先把默认的静态控件删掉,
再把工具箱上拖到对话框的面板上。
再调下控件大小,再把按钮的标题修改下,效果如图:
9.3派生CRichedit控件
选择项目,右键,选择New Class.
在弹出的对话框中,Basc
Class中选择CRichEditCtrl,Names中输入CRichEditCtrlEx
添加一个方法,右键,选择Add Member Function.
输入:InsertFace(CString
strPicPath)。
9.4把GifOle.dll加入工程
把GifOle.dll复制到Richedit工程目录下。
在stdafx.h文件中加入以下代码:
#import "GifOle.dll" named_guids
using namespace GIFOLELib;
效果如图:
9.5实现InsertFace函数
1.添加头文件:
#include <Richole.h>
效果如图:
2.在CRicheditEx的构造函数加入以下代码,注册GifOle.dll.
WinExec("regsvr32 /s GifOle.dll",SW_HIDE);
效果如图:
3.往之前的void CRichEditCtrlEx::InsertFace(CString strPicPath)方法加入以下代码:
IStorage* lpStorage = NULL;//存储接口
IOleObject* lpOleObject = NULL;//OLE对象
LPLOCKBYTES lpLockBytes = NULL;//LOCKBYTE
IOleClientSite*
lpOleClientSite = NULL;
IGifCtl* pShowGif = NULL; //控件
CLSID clsid;
REOBJECT reobject;
HRESULT hr;
hr
=
::CoCreateInstance(CLSID_GifCtl,NULL,CLSCTX_INPROC,IID_IGifCtl,(LPVOID*)&pShowGif);
pShowGif->LoadFromFile(strPicPath.AllocSysString());
hr
= pShowGif->QueryInterface(&lpOleObject);//获得数据对象接口
hr
= lpOleObject->GetUserClassID(&clsid);
hr
= ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);//创建LOCKBYTE对象
hr
= ::StgCreateDocfileOnILockBytes(lpLockBytes,//创建复合文档
STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE,
0, &lpStorage);
GetIRichEditOle()->GetClientSite(&lpOleClientSite);
ZeroMemory(&reobject,
sizeof(REOBJECT));//初始化一个对象
reobject.cbStruct
= sizeof(REOBJECT);
reobject.clsid = clsid;
reobject.cp = REO_CP_SELECTION;
reobject.dvaspect
= DVASPECT_CONTENT;
reobject.dwFlags
= REO_BELOWBASELINE;
reobject.poleobj
= lpOleObject;
reobject.polesite
= lpOleClientSite;
reobject.pstg = lpStorage;
hr
= GetIRichEditOle()->InsertObject( &reobject );
OleSetContainedObject(lpOleObject,TRUE);
//
release the interface
if(
pShowGif != NULL )
pShowGif->Release();
if(
lpOleObject != NULL )
lpOleObject->Release();
if(
lpOleClientSite != NULL )
lpOleClientSite->Release();
if(
lpStorage != NULL )
lpStorage->Release();
效果如图:
9.6 使用CRichEditEx类
启动Class Wizard,选择Member Variables选项
点击Add Variable,输入m_richedit
1.在RicheditDlg.文件的开头加入以下的语句:
#include "RichEditCtrlEx.h"
2.在RicheditDlg.h文件中找到下面一句
CRichEditCtrl m_richedit;
把上面那句改成
CRichEditCtrlEx m_richedit;
3.在BOOL CRicheditApp::InitInstance()函数加入以下一句代码:
AfxInitRichEdit();
效果如下图:
9.7调用InserFace函数
双击对话框上的插入图片按钮。添加OnOk函数。
把OnOK函数修改成
void CRicheditDlg::OnOK()
{
//
TODO: Add extra validation here
CFileDialog
dlg(TRUE,NULL,NULL,OFN_READONLY,
"image
file(*.bmp;*.jpeg;*.jpg;*.gif)|*.bmp;*.gif;*.jpeg;*.jpg|All Files
(*.*)|*.*||");
if(dlg.DoModal()==IDOK)
m_richedit.InsertFace(dlg.GetPathName());
}
9.8运行
点击插入图片按钮添加表情
在QQ的安装目录下有个Face2文件夹,插入里面的文件
10、总结
实现QQ表情这个功能的资料比较缺乏,我也在网上找了比较久,根据网上找到的一些相关资料,一点点尝试实现的。
以上所述只是实现QQ的表情功能的第一步,更深入的内容我也在尝试中,欢迎有兴趣的网友跟我一起探讨。
项目工程代码我放在QQ群:44177419,70934898,37950043的群共享上面。需要代码的可以去那下载,也可以直接发邮件来索取。代码有错误的地方,欢迎发邮件指正。
我的联系方式:
QQ:xpmo@qq.com
MSN:msn@msn.com
邮箱:xpmo@qq.com
欢迎转载,不过希望转载时注明出处。
9.1 创建一个MFC工程
新建一个MFC
AppWizard工程,在Project
name输入Richedit.

点击OK后,

选择Dialog based选项,点击Finish。
9.2 添加Richedit控件
先把默认的静态控件删掉,

再把工具箱上拖到对话框的面板上。

再调下控件大小,再把按钮的标题修改下,效果如图:

9.3派生CRichedit控件
选择项目,右键,选择New Class.

在弹出的对话框中,Basc
Class中选择CRichEditCtrl,Names中输入CRichEditCtrlEx

添加一个方法,右键,选择Add Member Function.

输入:InsertFace(CString
strPicPath)。

9.4把GifOle.dll加入工程
把GifOle.dll复制到Richedit工程目录下。
在stdafx.h文件中加入以下代码:
#import "GifOle.dll" named_guids
using namespace GIFOLELib;
效果如图:

9.5实现InsertFace函数
1.添加头文件:
#include <Richole.h>
效果如图:

2.在CRicheditEx的构造函数加入以下代码,注册GifOle.dll.
WinExec("regsvr32 /s GifOle.dll",SW_HIDE);
效果如图:

3.往之前的void CRichEditCtrlEx::InsertFace(CString strPicPath)方法加入以下代码:
IStorage* lpStorage = NULL;//存储接口
IOleObject* lpOleObject = NULL;//OLE对象
LPLOCKBYTES lpLockBytes = NULL;//LOCKBYTE
IOleClientSite*
lpOleClientSite = NULL;
IGifCtl* pShowGif = NULL; //控件
CLSID clsid;
REOBJECT reobject;
HRESULT hr;
hr
=
::CoCreateInstance(CLSID_GifCtl,NULL,CLSCTX_INPROC,IID_IGifCtl,(LPVOID*)&pShowGif);
pShowGif->LoadFromFile(strPicPath.AllocSysString());
hr
= pShowGif->QueryInterface(&lpOleObject);//获得数据对象接口
hr
= lpOleObject->GetUserClassID(&clsid);
hr
= ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);//创建LOCKBYTE对象
hr
= ::StgCreateDocfileOnILockBytes(lpLockBytes,//创建复合文档
STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE,
0, &lpStorage);
GetIRichEditOle()->GetClientSite(&lpOleClientSite);
ZeroMemory(&reobject,
sizeof(REOBJECT));//初始化一个对象
reobject.cbStruct
= sizeof(REOBJECT);
reobject.clsid = clsid;
reobject.cp = REO_CP_SELECTION;
reobject.dvaspect
= DVASPECT_CONTENT;
reobject.dwFlags
= REO_BELOWBASELINE;
reobject.poleobj
= lpOleObject;
reobject.polesite
= lpOleClientSite;
reobject.pstg = lpStorage;
hr
= GetIRichEditOle()->InsertObject( &reobject );
OleSetContainedObject(lpOleObject,TRUE);
//
release the interface
if(
pShowGif != NULL )
pShowGif->Release();
if(
lpOleObject != NULL )
lpOleObject->Release();
if(
lpOleClientSite != NULL )
lpOleClientSite->Release();
if(
lpStorage != NULL )
lpStorage->Release();
效果如图:

9.6 使用CRichEditEx类
启动Class Wizard,选择Member Variables选项

点击Add Variable,输入m_richedit

1.在RicheditDlg.文件的开头加入以下的语句:
#include "RichEditCtrlEx.h"
2.在RicheditDlg.h文件中找到下面一句
CRichEditCtrl m_richedit;
把上面那句改成
CRichEditCtrlEx m_richedit;
3.在BOOL CRicheditApp::InitInstance()函数加入以下一句代码:
AfxInitRichEdit();
效果如下图:

9.7调用InserFace函数
双击对话框上的插入图片按钮。添加OnOk函数。

把OnOK函数修改成
void CRicheditDlg::OnOK()
{
//
TODO: Add extra validation here
CFileDialog
dlg(TRUE,NULL,NULL,OFN_READONLY,
"image
file(*.bmp;*.jpeg;*.jpg;*.gif)|*.bmp;*.gif;*.jpeg;*.jpg|All Files
(*.*)|*.*||");
if(dlg.DoModal()==IDOK)
m_richedit.InsertFace(dlg.GetPathName());
}
9.8运行
点击插入图片按钮添加表情
在QQ的安装目录下有个Face2文件夹,插入里面的文件

10、总结
实现QQ表情这个功能的资料比较缺乏,我也在网上找了比较久,根据网上找到的一些相关资料,一点点尝试实现的。
以上所述只是实现QQ的表情功能的第一步,更深入的内容我也在尝试中,欢迎有兴趣的网友跟我一起探讨。
项目工程代码我放在QQ群:44177419,70934898,37950043的群共享上面。需要代码的可以去那下载,也可以直接发邮件来索取。代码有错误的地方,欢迎发邮件指正。
我的联系方式:
QQ:xpmo@qq.com
MSN:msn@msn.com
邮箱:xpmo@qq.com
欢迎转载,不过希望转载时注明出处。