本文给出一个基于gdi+的gif ActiveX控件的主要实现源码。本控件虽然冠名为gif,实际上可以用于显示多种格式的图像文件,bmp,jpeg,gif等等。由于时间关系,不多说明,同时只给出主要代码。
1. CTimeWnd
TimeWnd.h
------------------------------------------
#ifndef X_TIMEWND__H
#define X_TIMEWND__H
#include <atlbase.h>
#include <atlwin.h>
#include <map>
class CGifCtrl ;
class CTimeWnd : public CWindowImpl<CTimeWnd>
{
public:
static CWndClassInfo& GetWndClassInfo()
{
static CWndClassInfo wc =
{
{ sizeof(WNDCLASSEX), CS_VREDRAW|CS_DBLCLKS,
StartWindowProc, 0, 0, 0,
NULL,
0,
(HBRUSH)CreateSolidBrush(::GetSysColor(COLOR_BTNFACE)),
0,
NULL,
0 },
NULL, NULL, IDC_ARROW, TRUE, 0, ""
};
return wc;
}
BEGIN_MSG_MAP(CTimeWnd)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
MESSAGE_HANDLER(WM_CLOSE, OnClose)
END_MSG_MAP()
CTimeWnd():m_cur_timerid(0)
{
}
~CTimeWnd()
{
}
LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
PostMessage(WM_QUIT);
return 0;
}
void set_timer(CGifCtrl *pGif , DWORD nIDEvent);
void kill_timer(CGifCtrl *pGif);
void unregister_timer(CGifCtrl *pGif);
private:
DWORD m_cur_timerid ;
std::map<DWORD,CGifCtrl *> m_timer_map ;
};
extern CTimeWnd gTimerWnd ;
#endif//X_EMOTION_DISPLAY__H
TimeWnd.cpp
----------------------------------------
#include <stdafx.h>
#include "TimerWnd.h"
#include "GifCtrl.h"
CTimeWnd gTimerWnd ;
void CTimeWnd::set_timer(CGifCtrl *pGif , DWORD nIDEvent)
{
if(pGif->get_timerId() == 0xFFFFFFFF)
{
pGif->set_timerId(this->m_cur_timerid++);
m_timer_map[pGif->get_timerId()] = pGif;
}
SetTimer(pGif->get_timerId(),nIDEvent,NULL);
}
void CTimeWnd::kill_timer(CGifCtrl *pGif)
{
if(pGif->get_timerId() != 0xFFFFFFFF)
{
KillTimer(pGif->get_timerId());
}
}
void CTimeWnd::unregister_timer(CGifCtrl *pGif)
{
if(pGif->get_timerId() != 0xFFFFFFFF)
{
KillTimer(pGif->get_timerId());
m_timer_map.erase(pGif->get_timerId());
}
}
LRESULT CTimeWnd::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
std::map<DWORD,CGifCtrl *>::const_iterator it = m_timer_map.find(wParam);
if(it != m_timer_map.end())
{
((*it).second)->UpdateFrame();
}
return 0 ;
}
2. gif主代码
gifCtrl.h
------------------------------
// GifCtrl.h : CGifCtrl 的声明
#pragma once
#include "resource.h" // 主符号
#include <atlctl.h>
#include <gdiplus.h>
#include <comutil.h>
#include "TimerWnd.h"
using namespace Gdiplus;
// IGifCtrl
[
object,
uuid(3BAF90B3-AE30-4876-8379-00A06F9FA346),
dual,
helpstring("IGifCtrl 接口"),
pointer_default(unique)
]
__interface IGifCtrl : public IDispatch
{
[propget, id(1), helpstring("属性 Image")] HRESULT Image([out, retval] BSTR* pVal);
[propput, id(1), helpstring("属性 Image")] HRESULT Image([in] BSTR newVal);
};
// CGifCtrl
[
coclass,
threading("apartment"),
vi_progid("gif.GifCtrl"),
progid("gif.GifCtrl.1"),
version(1.0),
uuid("EA036A36-3808-4528-9C97-AC2D579AE4A6"),
helpstring("GifCtrl Class"),
support_error_info(IGifCtrl),
registration_script("control.rgs")
]
class ATL_NO_VTABLE CGifCtrl :
public IGifCtrl,
public IPersistStreamInitImpl<CGifCtrl>,
public IOleControlImpl<CGifCtrl>,
public IOleObjectImpl<CGifCtrl>,
public IOleInPlaceActiveObjectImpl<CGifCtrl>,
public IViewObjectExImpl<CGifCtrl>,
public IOleInPlaceObjectWindowlessImpl<CGifCtrl>,
public IPersistStorageImpl<CGifCtrl>,
public ISpecifyPropertyPagesImpl<CGifCtrl>,
public IQuickActivateImpl<CGifCtrl>,
public IDataObjectImpl<CGifCtrl>,
public IProvideClassInfo2Impl<&__uuidof(CGifCtrl), NULL>,
public CComControl<CGifCtrl>
{
Image *m_image ;
_bstr_t m_imageFile ;
int m_nFrameCount ;
int m_nFramePosition;
PropertyItem* m_pPropertyItem;
public:
CGifCtrl():m_image(NULL),m_pPropertyItem(NULL),m_nFrameCount(0),m_nFramePosition(0),m_timerid(0xFFFFFFFF)
{
}
~CGifCtrl()
{
}
DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
OLEMISC_CANTLINKINSIDE |
OLEMISC_INSIDEOUT |
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST
)
BEGIN_PROP_MAP(CGifCtrl)
PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
// 示例项
// PROP_ENTRY("Property Description", dispid, clsid)
// PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()
BEGIN_MSG_MAP(CGifCtrl)
CHAIN_MSG_MAP(CComControl<CGifCtrl>)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
// 处理程序原型:
// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
// IViewObjectEx
DECLARE_VIEW_STATUS(0)
// IGifCtrl
public:
HRESULT OnDraw(ATL_DRAWINFO& di)
{
RECT& rc = *(RECT*)di.prcBounds;
// 将剪辑区域设置为 di.prcBounds 指定的矩形
HRGN hRgnOld = NULL;
if (GetClipRgn(di.hdcDraw, hRgnOld) != 1)
hRgnOld = NULL;
bool bSelectOldRgn = false;
HRGN hRgnNew = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
if (hRgnNew != NULL)
{
bSelectOldRgn = (SelectClipRgn(di.hdcDraw, hRgnNew) != ERROR);
}
if(m_image)
{
Graphics graphics(di.hdcDraw); // Create a GDI+ graphics object
graphics.DrawImage(m_image, di.prcBounds->left, di.prcBounds->top, m_image->GetWidth(), m_image->GetHeight());
}
if (bSelectOldRgn)
SelectClipRgn(di.hdcDraw, hRgnOld);
if(hRgnNew)
DeleteObject(hRgnNew);
return S_OK;
}
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
STDMETHOD(GetExtent)(DWORD dwAspect , SIZEL *psizel)
{
if(m_image)
{
SIZEL szlPixels;
szlPixels.cx = m_image->GetWidth();
szlPixels.cy = m_image->GetHeight();
AtlPixelToHiMetric(&szlPixels, psizel);
}
else
{
psizel->cx = 1000 ;
psizel->cy = 1000;
}
return S_OK;
}
STDMETHOD(DoVerb)(LONG iVerb, LPMSG pMsg , IOleClientSite* pActiveSite, LONG lindex ,
HWND hwndParent, LPCRECT lprcPosRect)
{
return S_OK;
}
STDMETHOD(Close)(DWORD dwSaveOption)
{
gTimerWnd.unregister_timer(this);
return IOleObjectImpl<CGifCtrl>::Close(dwSaveOption);
}
void FinalRelease()
{
}
STDMETHOD(get_Image)(BSTR* pVal);
STDMETHOD(put_Image)(BSTR newVal);
DWORD get_timerId()
{
return m_timerid ;
}
void set_timerId(DWORD id)
{
m_timerid = id ;
}
void UpdateFrame();
private:
DWORD m_timerid ;
};
~CGdiPlus()
{
GdiplusShutdown(gdiplusToken);
}
};
CGdiPlus gdiplus ;