作者:小鹏

0、前言
相信大家对QQ的表情不陌生。像这样:

QQ的文本框控件支持各种图片格式的显示和插入。看到QQ这个有趣功能,我也想实现下。不过,实现起来却不是太容易,在我写代码的过程中,我也在网上查找了很久的资料,不过总算让我成功实现了。
要实现这个功能,关键的技术是要实现一个控件,这个控件能够播放GIF。
下面开始详细介绍我的写代码的过程。

1、观察QQ的实现方式
先从QQ是怎么实现的讲起。
QQ的这个控件叫ImageOle.dll.在QQ的安装目录下可以找到这个dll.
用regsvr32这个命令可以注册这个dll.

注册成功后可以用Ole View这个功能查看注册的相关信息。这个工具是VC自带的。

名字叫GifAnimator Class的就是QQ的那个控件。
选择GifAnimator,再右键,选择View Type Information.
可以看到ImageOle控件的类型库的内容。

这些内容就是QQ那控件的接口的方法。
我的目标就是实现一个同样的控件,支持其中一个方法,LoadFromFile.

2、创建一个ATL工程

下面就是我的具体实现的过程。
第一步,新建一个ATL工程。输入名称GifOle

下一步,保留默认选项,Server Type的类型是Dynamic Link Library(DLL).点击Finish.

3、添加一个控件

右键,选择New ATL Object.

在Category中选择Controls,在Objects中选择Full Control。

选择next.

在Short Name中输入CifCtl.
Miscellaneous中,把View Status中Opaque的选择去掉。Opaque是不透明的意思。QQ表情是在透明背景下显示的,所以要把那个选项去掉。

点击确定。

4、加入GDI+类库

下面实现播放Gif的功能。我用的是Gdi+。
在VC6要使用Gdi+的话,得下个库。
GDI+ for VC6.0 SDK下载

地址:
http://www.codeguru.com/code/legacy/gdi/GDIPlus.zip
下载回来后,把里面的头文件和GdiPlus.lib复制到gdiplus的文件夹,再把这个文件夹复制到GifOle工程目录下。
在stdafx.h文件中加入以下代码
#define UNICODE
#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#endif
#include "gdiplus//GdiPlus.h"
using namespace Gdiplus;
#pragma comment(lib,
"gdiplus//gdiplus.lib")
效果如下图:

5、加入ImageEx类

另外,我还有用到一个ImageEx类来显示gif.

这个类的头文件是:
// ImageEx.h: interface for the ImageEx class.
//
//

#if
!defined(AFX_IMAGEEX_H__D639CC73_8200_42E0_9386_617AD4B0A2E9__INCLUDED_)
#define
AFX_IMAGEEX_H__D639CC73_8200_42E0_9386_617AD4B0A2E9__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class ImageEx : public Image
{
public:
ImageEx(const
WCHAR* filename, BOOL useEmbeddedColorManagement = FALSE);
~ImageEx();
public:
BOOL
IsAnimatedGif();    //判断是否是动态GIF文件
   long
GetFrameTime();     //获取当前帧应该显示的时间长度
void
ActiveNextFrame();  //激活下一帧为应该显示的帧
protected:
UINT  m_nFrameCount;     //帧数
UINT  m_nFramePosition;  //当前帧的序号
   PropertyItem*
m_pPropertyItem;   //属性项,仅用来测试是否是动态图片
};

#endif // !defined(AFX_IMAGEEX_H__D639CC73_8200_42E0_9386_617AD4B0A2E9__INCLUDED_)
把以上内容复制到ImageEx.h文件中,入到工程目录下。
实现文件的内容是:
// ImageEx.cpp: implementation of the ImageEx class.
//
//

#include "stdafx.h"
#include "ImageEx.h"

ImageEx::ImageEx(const WCHAR* FileName, BOOL
useEmbeddedColorManagement)
:Image(FileName, useEmbeddedColorManagement)
{
m_nFramePosition =
0;
m_nFrameCount = 0;
m_pPropertyItem =
NULL;

UINT count = 0;
count =
GetFrameDimensionsCount();      //获得维数
GUID* pDimensionIDs
= new GUID[count];  //分配维ID数组

GetFrameDimensionsList(pDimensionIDs,
count);//获得各维的ID
m_nFrameCount =
GetFrameCount(&pDimensionIDs[0]);//获得第一维的帧数

//获得属性项
int nSize =
GetPropertyItemSize(PropertyTagFrameDelay);
m_pPropertyItem =
(PropertyItem*) malloc(nSize);
GetPropertyItem(PropertyTagFrameDelay,
nSize, m_pPropertyItem);  
delete pDimensionIDs;    
}

ImageEx::~ImageEx()
{
free(m_pPropertyItem);
m_pPropertyItem =
NULL;
}

BOOL ImageEx::IsAnimatedGif()
{
return m_nFrameCount
> 1;
}

long ImageEx::GetFrameTime()
{
long lPause =
((long*) m_pPropertyItem->value)[m_nFramePosition] * 10;
return lPause;
}

void ImageEx::ActiveNextFrame()
{
if (IsAnimatedGif()
== FALSE)
    return;

GUID  pageGuid = FrameDimensionTime;
SelectActiveFrame(&pageGuid,
m_nFramePosition++);

if
(m_nFramePosition == m_nFrameCount)
    m_nFramePosition
= 0;
}
把以上内容复制到ImageEx.cpp文件中,复制到项目工程目录下。
再把这两个文件添加到工程。再在GifCtl.h的文件的开头加下以下语句:
#include "ImageEx.h"
效果如下图:

6、加入定时器类

另外,为了让gif表情动起来,还需要一个定时器类来定时刷新,实现动的效果。
// CTimer
template <class Derived, class T, const IID* piid>
class CTimer
{
public:

CTimer()
{
    m_bTimerOn =
FALSE;
}

HRESULT
TimerOn(DWORD dwTimerInterval)
{
    Derived*
pDerived = ((Derived*)this);
    
    m_dwTimerInterval
= dwTimerInterval;
    if (m_bTimerOn)
// already on, just change interval
       return S_OK;
    
    m_bTimerOn =
TRUE;
    m_dwTimerInterval
= dwTimerInterval;
    m_pStream =
NULL;
    
    HRESULT hRes;
    
    hRes =
CoMarshalInterThreadInterfaceInStream(*piid, (T*)pDerived, &m_pStream);
    
    // Create
thread and pass the thread proc the this ptr
    m_hThread =
CreateThread(NULL, 0, &_Apartment, (void*)this, 0, &m_dwThreadID);
    
    return S_OK;
}

void TimerOff()
{
    if (m_bTimerOn)
    {
       m_bTimerOn =
FALSE;
       AtlWaitWithMessageLoop(m_hThread);
    }
}

// Implementation
private:
static DWORD WINAPI
_Apartment(void* pv)
{
    CTimer<Derived,
T, piid>* pThis = (CTimer<Derived, T, piid>*) pv;
    pThis->Apartment();
    return 0;
}

DWORD Apartment()
{
    CoInitialize(NULL);
    HRESULT hRes;
    
    m_spT.Release();
    
    if (m_pStream)
       hRes =
CoGetInterfaceAndReleaseStream(m_pStream, *piid, (void**)&m_spT);
    
    while(m_bTimerOn)
    {
       Sleep(m_dwTimerInterval);
       if
(!m_bTimerOn)
           break;
      
       m_spT->_OnTimer();
    }
    m_spT.Release();
    
    CoUninitialize();
    return 0;
}

// Attributes
public:
DWORD
m_dwTimerInterval;

// Implementation
private:
HANDLE m_hThread;
DWORD m_dwThreadID;
LPSTREAM m_pStream;
CComPtr<T>
m_spT;
BOOL m_bTimerOn;
};
把以上代码同样复制到#include "ImageEx.h"语句的下面
效果如下图:

再把这个定时器加入到CGifCtl控件中
在CGifCtl类开头加入以下代码
public CTimer<CGifCtl, IGifCtl, &IID_IGifCtl>,
如图:

实现QQ表情功能(1)相关推荐

  1. 实现QQ表情功能(2)

    7.添加必要的成员和方法 7.1 添加成员变量 下面往CGifCtl加入些成员变量:    CComBSTR m_strFileName;    GdiplusStartupInput gdiplus ...

  2. 向EditView插入qq表情,并可删除表情或文字

    2019独角兽企业重金招聘Python工程师标准>>> 参考了一下别人实现的插入qq表情功能,在此基础上加了删除功能 代码如下: package com.push.notif;imp ...

  3. 测试用例集-11.QQ表情收藏功能测试用例

    ------·今天距2020年55天·------ 这是ITester软件测试小栈第74次推文 大家好 我是coco小锦鲤 我又双叒叕 yòu shuāng ruò zhuó 出现了 有时候聊天到不到 ...

  4. 微信公众帐号开发教程第9篇-QQ表情的发送与接收

    我想大家对QQ表情一定不会陌生,一个个小头像极大丰富了聊天的乐趣,使得聊天不再是简单的文字叙述,还能够配上喜.怒.哀.乐等表达人物心情的小图片.本文重点要介绍的内容就是如何在微信公众平台使用QQ表情, ...

  5. [033] 微信公众帐号开发教程第9篇-QQ表情的发送与接收

    我想大家对QQ表情一定不会陌生,一个个小头像极大丰富了聊天的乐趣,使得聊天不再是简单的文字叙述,还能够配上喜.怒.哀.乐等表达人物心情的小图片.本文重点要介绍的内容就是如何在微信公众平台使用QQ表情, ...

  6. 思量QQ本地会员v3.8官方2013版【免费使用部分QQ会员功能】

    思量QQ本地会员(2013版) v3.8官方版 授权方式:免费软件 界面语言:简体中文 软件大小:1024KB 所属专题:网络软件 运行环境:Win2K,WinXP,Win2003,Vista,Win ...

  7. Android 支持表情功能

    概述 1.原理和实现思路 2.表情图片显示 3.表情面板 4.表情的输入框插入和删除 5.表情添加脚本 Android中表情功能,一般都不是用ImageView去设置图片实现的, 表情一般会嵌套在文本 ...

  8. Android 表情功能的完整处理方案

    概述 1.原理和实现思路 2.表情图片显示 3.表情面板 4.表情的输入框插入和删除 5.表情添加脚本 Android中表情功能,一般都不是用ImageView去设置图片实现的, 表情一般会嵌套在文本 ...

  9. WordPress文章中插入qq表情

    看见一些博客中使用了QQ表情,这个效果还是很不错的,可以让文章看起来更爽,那么这个是怎么实现的呢? 下面我就来说说方法. 工具:QQ表情包,下载地址:http://yunpan.cn/cLw6UhwB ...

最新文章

  1. androidx FloatingActionButton 中间加载的图片显示黑色
  2. 设计模式之Pimpl模式
  3. Unity3D项目实战笔记(10):Unity3D编译IPA的PostEvents–节约时间利器
  4. SAP 采购订单进项税VOFM 例程增强
  5. gravity 时序图绘制,改
  6. python 与或非_Python的阶乘求和
  7. Django里面的sql查询语句
  8. html5两条直线,Html5新特性用canvas标签画多条直线附效果截图
  9. plc 上位机编译算法_基于西门子PLC的Socket通信深度剖析
  10. mysql left join测试
  11. 恐龙机器人钢索恐龙形态_恐龙有的四脚行走有的两脚行走,有的会飞有的会游,差别咋这么大...
  12. 用户手册(User Manual)书写规范
  13. 基于51单片机三路温湿度语音LCD1602液晶显示报警
  14. IE-LAB网络实验室:VPLS技术介绍
  15. SPA项目搭建及嵌套路由
  16. Windows句柄数的限制
  17. 关于Context的理解(转)
  18. Lamp 服务器环境安装
  19. 嵌入式设备显示屏相关概念汇总
  20. 谢少荣到计算机学院,我校校友谢少荣应邀回母校交流并受聘顾问教授

热门文章

  1. 用二分法编写猜数字游戏(含:猜电脑随机数,和用户自己想的数字)python
  2. 微信小程序支付退款功能
  3. java8获取以秒单位的时间戳
  4. 强化学习keras-rl2的安装注意点
  5. 超鸿蒙是什么意思,帝垣的组词_拼音_意思_近反义词(造句)
  6. 解决Node Sass could not find a binding for your current environment: Windows 64-bit with Node.js 14.x
  7. Slax本土化:移动硬盘上的Linux中文套件(转)
  8. 【CS231n】十五、深度学习的高效算法和硬件设计_一只神秘的大金毛_新浪博客...
  9. GOM引擎单机架设配置教程
  10. 下载ez_setup