7、添加必要的成员和方法
7.1 添加成员变量
下面往CGifCtl加入些成员变量:
CComBSTR
m_strFileName;
GdiplusStartupInput
gdiplusStartupInput;
ULONG_PTR
gdiplusToken;
ImageEx*
m_pImg; //图像
效果如图:
![](https://i-blog.csdnimg.cn/blog_migrate/d719e04a6a84c06d9c1717f6982474a0.gif)
7.2构造函数
再在CCifCtl的构造函数中加入以下代码:
GdiplusStartup(&gdiplusToken,
&gdiplusStartupInput, NULL);
m_bWndLess=true;
m_pImg=NULL;
效果如图:
![](https://i-blog.csdnimg.cn/blog_migrate/31c670ff880b2f8c53ad35831c6b8b03.gif)
7.3
FinalRelease函数
再往CGifCtl类加入一个FinalRelease函数。
void
FinalRelease()
{
GdiplusShutdown(gdiplusToken);
TimerOff();
}
效果如图:
![](https://i-blog.csdnimg.cn/blog_migrate/f2937d41c7d2d6926f3d98833ac4fbc4.gif)
以上添加的两个函数是用于Gdi+库的初始化。
接头就看看怎么把Gif图片显示出来。
7.4添加LoadFromFile方法
往IGifCtl接口中加入一个方法。
操作如下,选择IGifCtl,右键,选择Add Method,如图:
![](https://i-blog.csdnimg.cn/blog_migrate/d708ec6f03defb219d9a5eabba40c9dd.gif)
在Method Name中输入:LoadFromFile
在Parameters中输入:[in] BSTR FileName
![](https://i-blog.csdnimg.cn/blog_migrate/416e7ae09ad198fe2b472dca6dea45cb.gif)
点击OK.
实现LoadFromFile方法:
跳到那个方法下:
![](https://i-blog.csdnimg.cn/blog_migrate/13a5176e526b59401e5b292946763d07.gif)
加入以下代码:
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();
效果如图:
![](https://i-blog.csdnimg.cn/blog_migrate/a9838b9b90e8e815ad16a1efdc0f174a.gif)
7.5添加_OnTimer方法
再添加一个方法:_OnTimer
![](https://i-blog.csdnimg.cn/blog_migrate/649d73ce0204c67b12e354372ae4194e.gif)
在_OnTimer函数中输入以下代码:
if (m_pImg != NULL)
{
m_pImg->ActiveNextFrame(); //显示下一帧
long lFrameTime =
m_pImg->GetFrameTime(); //获得下一帧的显示时间
TimerOn(lFrameTime); //修改计时器的周期为下一帧的显示时间
FireViewChange(); //刷新图片区域
}
效果如图:
![](https://i-blog.csdnimg.cn/blog_migrate/c795210c516a3a15c89be7a9f2ec20a9.gif)
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;
}
效果如图:
![](https://i-blog.csdnimg.cn/blog_migrate/d3670905e2bc3ee57fc47613d62ce73b.gif)
至此,这个控件的代码就写完了,编译,链接,生成控件。
8、测试
下面来测试下刚才写的那个控件。8.1 注册
先把刚写好的控件用regsvr32命令注册一下。
![](https://i-blog.csdnimg.cn/blog_migrate/0b6cf7dbf95ab3a73f9fe4bd4fc1ec4f.gif)
8.2插入控件
测试用到的是vc自带的工具ActiveX Control Test Container。
启动ActiveX Control Test Container软件。
点击工具栏上的New Control按钮
![](https://i-blog.csdnimg.cn/blog_migrate/02562a8ba23b4eeefb3ca72ac0545c4a.gif)
弹出以下对话框
![](https://i-blog.csdnimg.cn/blog_migrate/ecbf038834c8be9144bc1b1eac181d80.gif)
再选择GifCtl,点击OK8.3调用方法
添加成功后,再点击Invoke Methods按钮。
![](https://i-blog.csdnimg.cn/blog_migrate/b70d11d9996237b40f856c81746feeee.gif)
弹出以下对话框,在Parameter中输入一个gif文件的路径,以下是我的gif图片的路径。G:/richedit/2.gif。输入后,点击Invoke。
![](https://i-blog.csdnimg.cn/blog_migrate/1d7bf5651642a49f07ff48aced1ae94b.gif)
可以看到控件显示gif图片了。
![](https://i-blog.csdnimg.cn/blog_migrate/6a8cc12257292ec73308733b66e8bcc9.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.
![](https://i-blog.csdnimg.cn/blog_migrate/06a4e7cad23d7211d12f307d8c4529c8.gif)
点击OK后,
![](https://i-blog.csdnimg.cn/blog_migrate/f12e4c27c4a79248b8c535d6d1d494db.gif)
选择Dialog based选项,点击Finish。
9.2 添加Richedit控件
先把默认的静态控件删掉,
![](https://i-blog.csdnimg.cn/blog_migrate/1b0a5467121c3bf226b46a6f8d283b1b.gif)
再把工具箱上拖到对话框的面板上。
![](https://i-blog.csdnimg.cn/blog_migrate/3994e2d5d10dceb03198593bb85208c4.gif)
再调下控件大小,再把按钮的标题修改下,效果如图:
![](https://i-blog.csdnimg.cn/blog_migrate/eb05de04ef59c044c33f294868fee094.gif)
9.3派生CRichedit控件
选择项目,右键,选择New Class.
![](https://i-blog.csdnimg.cn/blog_migrate/2cfafa486fa87593e15124017d4174c6.gif)
在弹出的对话框中,Basc
Class中选择CRichEditCtrl,Names中输入CRichEditCtrlEx
![](https://i-blog.csdnimg.cn/blog_migrate/1d254e4e8ab64193988c48d482f6ad56.gif)
添加一个方法,右键,选择Add Member Function.
![](https://i-blog.csdnimg.cn/blog_migrate/097fa994523ebea1c2c5ebe2c82d6cca.gif)
输入:InsertFace(CString
strPicPath)。
![](https://i-blog.csdnimg.cn/blog_migrate/01208e522d8a2459971aa95b4b21f571.gif)
9.4把GifOle.dll加入工程
把GifOle.dll复制到Richedit工程目录下。
在stdafx.h文件中加入以下代码:
#import "GifOle.dll" named_guids
using namespace GIFOLELib;
效果如图:
![](https://i-blog.csdnimg.cn/blog_migrate/137eb3ed9c383c13258ec8cacaef09bc.gif)
9.5实现InsertFace函数
1.添加头文件:
#include <Richole.h>
效果如图:
![](https://i-blog.csdnimg.cn/blog_migrate/0085d54b728477784ad3fb1436bd5a2b.gif)
2.在CRicheditEx的构造函数加入以下代码,注册GifOle.dll.
WinExec("regsvr32 /s GifOle.dll",SW_HIDE);
效果如图:
![](https://i-blog.csdnimg.cn/blog_migrate/f69e5e9f79d5c068739f0dd1766a26d1.gif)
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();
效果如图:
![](https://i-blog.csdnimg.cn/blog_migrate/c6e7aa4167d51f06039c38d0ff847d3d.gif)
9.6 使用CRichEditEx类
启动Class Wizard,选择Member Variables选项
![](https://i-blog.csdnimg.cn/blog_migrate/a1c3fd0c9cd4b5cc7028d4ff21d6ee91.gif)
点击Add Variable,输入m_richedit
![](https://i-blog.csdnimg.cn/blog_migrate/c55f9bd845397c38e3f89334b03f1265.gif)
1.在RicheditDlg.文件的开头加入以下的语句:
#include "RichEditCtrlEx.h"
2.在RicheditDlg.h文件中找到下面一句
CRichEditCtrl m_richedit;
把上面那句改成
CRichEditCtrlEx m_richedit;
3.在BOOL CRicheditApp::InitInstance()函数加入以下一句代码:
AfxInitRichEdit();
效果如下图:
![](https://i-blog.csdnimg.cn/blog_migrate/26acf1afb1306419c79c15c1d3d6f647.gif)
9.7调用InserFace函数
双击对话框上的插入图片按钮。添加OnOk函数。
![](https://i-blog.csdnimg.cn/blog_migrate/4a2cea97e898e9ad45f28ff81bd559e6.gif)
把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文件夹,插入里面的文件
![](https://i-blog.csdnimg.cn/blog_migrate/95063c11cb6cf86068e4e8cad94b2770.gif)
10、总结
实现QQ表情这个功能的资料比较缺乏,我也在网上找了比较久,根据网上找到的一些相关资料,一点点尝试实现的。
以上所述只是实现QQ的表情功能的第一步,更深入的内容我也在尝试中,欢迎有兴趣的网友跟我一起探讨。
项目工程代码我放在QQ群:44177419,70934898,37950043的群共享上面。需要代码的可以去那下载,也可以直接发邮件来索取。代码有错误的地方,欢迎发邮件指正。
我的联系方式:
QQ:xpmo@qq.com
MSN:msn@msn.com
邮箱:xpmo@qq.com
欢迎转载,不过希望转载时注明出处。