很久没用WTL了,WTL都升级到8.0了,这两天做了个小例子,WTL调用Flash控件。
目标:使用WTL创建对话框的工程,调用Flash控件播放Flash,并响应Flash控件的事件。
环境:WindowsXP, VC++ 2005, WTL8.0, Flash9
1. 首先用WTL Wizard创建对话框工程,如图:
![WTL8.0 调用 ActiveX 控件 - (调用 Flash 控件,响应 Flash 控件的事件)_第1张图片](http://img.e-com-net.com/image/info8/cedbbc229d9c4602998eee4b2c89ae02.jpg)
注意要选中 Enable ActiveX Control Hosting,我习惯于 Generate .CPP Files 这样可以使H文件和CPP文件分开。
工程创建好后,Wizard会为我们在 tWinMain 函数中添加 AtlAxWinInit() 函数,如下:
![](http://img.e-com-net.com/image/info8/a851f6ebab08498cbe1d2f2c2b23a0c9.gif)
![](http://img.e-com-net.com/image/info8/a851f6ebab08498cbe1d2f2c2b23a0c9.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/2c9100fab8554b7caad7b3144808b323.gif)
2. 接着在编辑对话框资源,单击右键添加ActiveX控件,这里选择 ShockwaveFlash 1.0控件。如图:
![WTL8.0 调用 ActiveX 控件 - (调用 Flash 控件,响应 Flash 控件的事件)_第2张图片](http://img.e-com-net.com/image/info8/88cce14b65c64f0f860532e822f285fb.jpg)
![WTL8.0 调用 ActiveX 控件 - (调用 Flash 控件,响应 Flash 控件的事件)_第3张图片](http://img.e-com-net.com/image/info8/7ce0bbb3e15b45f8979b5e1531980b57.jpg)
添加好以后,我们需要为这个控件定义一个变量,以便使用控件的方法。我们在CMainDlg类里手工增加ActiveX控件的窗口变量:CAxWindow m_wndFlashPlayer。我们还需要增加ActiveX控件对象的COM接口 CComPtr
#
import
"
c:/windows/system32/flash9c.ocx
"
raw_interfaces_only, raw_native_types, no_namespace, named_guids
raw_interfaces_only 表示以原始接口方式调用Flash类型库里的方法。
no_namespace 表示没有名字空间。
named_guids 表示生成命名的guid变量,如 DIID__IShockwaveFlashEvents等变量。
3. 在对话框的初始化函数 OnInitDialog 里将ActiveX控件与变量绑定,如下:
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
// HRESULT hResult = m_wndFlashPlayer.QueryControl(__uuidof(IShockwaveFlash), reinterpret_cast
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
接着装载一个Flash Movie,调用下面的方法,装载一个swf文件,并让它处于停止状态:
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
这时候,我们可以在对话框上增加一个按钮,在Click事件里添加播放的代码,如下:
![](http://img.e-com-net.com/image/info8/a851f6ebab08498cbe1d2f2c2b23a0c9.gif)
![](http://img.e-com-net.com/image/info8/a851f6ebab08498cbe1d2f2c2b23a0c9.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/2c9100fab8554b7caad7b3144808b323.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
4. 下面我们关注如何响应Flash的事件,我们以FSCommand事件为例。
首先编辑对话框资源,右键单击前面添加的Flash控件,选择Add Event Handler,如图:
![WTL8.0 调用 ActiveX 控件 - (调用 Flash 控件,响应 Flash 控件的事件)_第4张图片](http://img.e-com-net.com/image/info8/83b045a0075a4cb5a42b9527109ffa2d.jpg)
我们选择添加FSCommand事件的响应处理,响应函数为OnFSCommand,响应的处理放在CMainDlg类中,如图:
![WTL8.0 调用 ActiveX 控件 - (调用 Flash 控件,响应 Flash 控件的事件)_第5张图片](http://img.e-com-net.com/image/info8/f4f07253d848468382907b1652b183cd.jpg)
添加好后,Wizard会为我们生成事件响应的代码,主要在CMainDlg类中,我们看代码:
//
MainDlg.h : interface of the CMainDlg class
//
//////////////////////////////////////////////////////////////////////////// /
#pragma once
class CMainDlg : public CAxDialogImpl < CMainDlg > , public CUpdateUI < CMainDlg > ,
public CMessageFilter, public CIdleHandler,
public IDispEventImpl
{
public :
enum { IDD = IDD_MAINDLG };
virtual BOOL PreTranslateMessage(MSG * pMsg);
virtual BOOL OnIdle();
BEGIN_UPDATE_UI_MAP(CMainDlg)
END_UPDATE_UI_MAP()
BEGIN_MSG_MAP(CMainDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
COMMAND_ID_HANDLER(IDOK, OnOK)
COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
END_MSG_MAP()
// Handler prototypes (uncomment arguments if needed):
// 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*/)
LRESULT OnInitDialog(UINT /* uMsg */ , WPARAM /* wParam */ , LPARAM /* lParam */ , BOOL & /* bHandled */ );
LRESULT OnDestroy(UINT /* uMsg */ , WPARAM /* wParam */ , LPARAM /* lParam */ , BOOL & /* bHandled */ );
LRESULT OnAppAbout(WORD /* wNotifyCode */ , WORD /* wID */ , HWND /* hWndCtl */ , BOOL & /* bHandled */ );
LRESULT OnOK(WORD /* wNotifyCode */ , WORD wID, HWND /* hWndCtl */ , BOOL & /* bHandled */ );
LRESULT OnCancel(WORD /* wNotifyCode */ , WORD wID, HWND /* hWndCtl */ , BOOL & /* bHandled */ );
void CloseDialog( int nVal);
public :
CAxWindow m_wndFlashPlayer;
CComPtr < IShockwaveFlash > m_FlashPtr;
BEGIN_SINK_MAP(CMainDlg)
SINK_ENTRY(IDC_SHOCKWAVEFLASH1, 150, OnFSCommand)
END_SINK_MAP()
void __stdcall OnFSCommand(BSTR command, BSTR args);
};
//
//////////////////////////////////////////////////////////////////////////// /
#pragma once
class CMainDlg : public CAxDialogImpl < CMainDlg > , public CUpdateUI < CMainDlg > ,
public CMessageFilter, public CIdleHandler,
public IDispEventImpl
public :
enum { IDD = IDD_MAINDLG };
virtual BOOL PreTranslateMessage(MSG * pMsg);
virtual BOOL OnIdle();
BEGIN_UPDATE_UI_MAP(CMainDlg)
END_UPDATE_UI_MAP()
BEGIN_MSG_MAP(CMainDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
COMMAND_ID_HANDLER(IDOK, OnOK)
COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
END_MSG_MAP()
// Handler prototypes (uncomment arguments if needed):
// 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*/)
LRESULT OnInitDialog(UINT /* uMsg */ , WPARAM /* wParam */ , LPARAM /* lParam */ , BOOL & /* bHandled */ );
LRESULT OnDestroy(UINT /* uMsg */ , WPARAM /* wParam */ , LPARAM /* lParam */ , BOOL & /* bHandled */ );
LRESULT OnAppAbout(WORD /* wNotifyCode */ , WORD /* wID */ , HWND /* hWndCtl */ , BOOL & /* bHandled */ );
LRESULT OnOK(WORD /* wNotifyCode */ , WORD wID, HWND /* hWndCtl */ , BOOL & /* bHandled */ );
LRESULT OnCancel(WORD /* wNotifyCode */ , WORD wID, HWND /* hWndCtl */ , BOOL & /* bHandled */ );
void CloseDialog( int nVal);
public :
CAxWindow m_wndFlashPlayer;
CComPtr < IShockwaveFlash > m_FlashPtr;
BEGIN_SINK_MAP(CMainDlg)
SINK_ENTRY(IDC_SHOCKWAVEFLASH1, 150, OnFSCommand)
END_SINK_MAP()
void __stdcall OnFSCommand(BSTR command, BSTR args);
};
红色部分的代码是Wizard为我们生成的,注意如下几点:
(1)CMainDlg增加了父类 IDispEventImpl
(2)增加了BEGIN_SINK_MAP(事件接受器映射),SINK_ENTRY(IDC_SHOCKWAVEFLASH1, 150, OnFSCommand)是事件接收的进入点,IDC_SHOKEWAVEFLASH1是控件的资源ID,通常这里定义的是事件源的ID,需要和继承的IDispEventImpl模版的第一个参数一致,表示同一个事件源。150 是Flash控件的FSCommand事件的ID,这是固定的,在Flash控件的idl文件已经写死了,我们可以用 OleView 工具察看 Flash 的事件接口里的方法 FSCommand 的ID, 0x96 即为 150。OnFSCommand是我们前面数据的事件响应的函数名,Wizard也为我们生成了函数的声明和框架,void __stdcall OnFSCommand(BSTR command, BSTR args)。
是否这样就可以了吗?答案是否定的,虽然程序编译没有问题,但事件的响应没有触发,我们忘了 DispEventAdvice 了。在 CMainDlg 的初始化函数 OnInitDialog 里加入:DispEventAdvice,如下:
LRESULT CMainDlg::OnInitDialog(UINT
/*
uMsg
*/
, WPARAM
/*
wParam
*/
, LPARAM
/*
lParam
*/
, BOOL
&
/*
bHandled
*/
)
{
// center the dialog on the screen
CenterWindow();
// set icons
HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME),
IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
SetIcon(hIcon, TRUE);
HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME),
IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
SetIcon(hIconSmall, FALSE);
// register object for message filtering and idle updates
CMessageLoop * pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop -> AddMessageFilter( this );
pLoop -> AddIdleHandler( this );
UIAddChildWindowContainer(m_hWnd);
m_wndFlashPlayer = GetDlgItem(IDC_SHOCKWAVEFLASH1);
// HRESULT hResult = m_wndFlashPlayer.QueryControl(__uuidof(IShockwaveFlash), reinterpret_cast(&m_FlashPtr));
HRESULT hResult = m_wndFlashPlayer.QueryControl( & m_FlashPtr);
ATLASSERT(hResult == S_OK);
// AtlAdviseSinkMap(this, true);
DispEventAdvise(m_FlashPtr);
hResult = m_FlashPtr -> put_Movie(_bstr_t( " f:\\flashC.swf " ));
ATLASSERT(hResult == S_OK);
hResult = m_FlashPtr -> Stop();
ATLASSERT(hResult == S_OK);
return TRUE;
}
{
// center the dialog on the screen
CenterWindow();
// set icons
HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME),
IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
SetIcon(hIcon, TRUE);
HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME),
IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
SetIcon(hIconSmall, FALSE);
// register object for message filtering and idle updates
CMessageLoop * pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop -> AddMessageFilter( this );
pLoop -> AddIdleHandler( this );
UIAddChildWindowContainer(m_hWnd);
m_wndFlashPlayer = GetDlgItem(IDC_SHOCKWAVEFLASH1);
// HRESULT hResult = m_wndFlashPlayer.QueryControl(__uuidof(IShockwaveFlash), reinterpret_cast
HRESULT hResult = m_wndFlashPlayer.QueryControl( & m_FlashPtr);
ATLASSERT(hResult == S_OK);
// AtlAdviseSinkMap(this, true);
DispEventAdvise(m_FlashPtr);
hResult = m_FlashPtr -> put_Movie(_bstr_t( " f:\\flashC.swf " ));
ATLASSERT(hResult == S_OK);
hResult = m_FlashPtr -> Stop();
ATLASSERT(hResult == S_OK);
return TRUE;
}
注释掉的代码 AtlAdviseSinkMap(this, true)也是可以用的。
到此,我们的目标算是实现了。
WTL8.0对 ActiveX的调用可算是比较简单的,回顾一下之前的做法,特别是接受事件的代码,相对还是比较不同的。不过原理都一样。
之前,事件接受的类要继承 IDispEventImpl
如下:
//
MainDlg.h : interface of the CMainDlg class
//
//////////////////////////////////////////////////////////////////////////// /
#pragma once
#define SOURCEID 1
class CMainDlg;
typedef IDispEventImpl CFlashEventSink;
class CMainDlg :
public CAxDialogImpl < CMainDlg > ,
public CUpdateUI < CMainDlg > ,
public CMessageFilter, public CIdleHandler,
public CComObjectRoot,
public CFlashEventSink
{
public :
enum { IDD = IDD_MAINDLG };
virtual BOOL PreTranslateMessage(MSG * pMsg);
virtual BOOL OnIdle();
BEGIN_UPDATE_UI_MAP(CMainDlg)
END_UPDATE_UI_MAP()
BEGIN_MSG_MAP(CMainDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
COMMAND_ID_HANDLER(IDOK, OnOK)
COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
COMMAND_HANDLER(IDC_BUTTON1, BN_CLICKED, OnBnClickedButton1)
END_MSG_MAP()
// Handler prototypes (uncomment arguments if needed):
// 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*/)
LRESULT OnInitDialog(UINT /* uMsg */ , WPARAM /* wParam */ , LPARAM /* lParam */ , BOOL & /* bHandled */ );
LRESULT OnDestroy(UINT /* uMsg */ , WPARAM /* wParam */ , LPARAM /* lParam */ , BOOL & /* bHandled */ );
LRESULT OnAppAbout(WORD /* wNotifyCode */ , WORD /* wID */ , HWND /* hWndCtl */ , BOOL & /* bHandled */ );
LRESULT OnOK(WORD /* wNotifyCode */ , WORD wID, HWND /* hWndCtl */ , BOOL & /* bHandled */ );
LRESULT OnCancel(WORD /* wNotifyCode */ , WORD wID, HWND /* hWndCtl */ , BOOL & /* bHandled */ );
void CloseDialog( int nVal);
LRESULT OnBnClickedButton1(WORD /* wNotifyCode */ , WORD /* wID */ , HWND /* hWndCtl */ , BOOL & /* bHandled */ );
public :
CAxWindow m_wndFlashPlayer;
CComPtr < IShockwaveFlash > m_FlashPtr;
BEGIN_SINK_MAP(CMainDlg)
SINK_ENTRY_EX(SOURCEID, DIID__IShockwaveFlashEvents, 150, OnFSCommand)
END_SINK_MAP()
void __stdcall OnFSCommand(BSTR command, BSTR args);
};
//
//////////////////////////////////////////////////////////////////////////// /
#pragma once
#define SOURCEID 1
class CMainDlg;
typedef IDispEventImpl
class CMainDlg :
public CAxDialogImpl < CMainDlg > ,
public CUpdateUI < CMainDlg > ,
public CMessageFilter, public CIdleHandler,
public CComObjectRoot,
public CFlashEventSink
{
public :
enum { IDD = IDD_MAINDLG };
virtual BOOL PreTranslateMessage(MSG * pMsg);
virtual BOOL OnIdle();
BEGIN_UPDATE_UI_MAP(CMainDlg)
END_UPDATE_UI_MAP()
BEGIN_MSG_MAP(CMainDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
COMMAND_ID_HANDLER(IDOK, OnOK)
COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
COMMAND_HANDLER(IDC_BUTTON1, BN_CLICKED, OnBnClickedButton1)
END_MSG_MAP()
// Handler prototypes (uncomment arguments if needed):
// 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*/)
LRESULT OnInitDialog(UINT /* uMsg */ , WPARAM /* wParam */ , LPARAM /* lParam */ , BOOL & /* bHandled */ );
LRESULT OnDestroy(UINT /* uMsg */ , WPARAM /* wParam */ , LPARAM /* lParam */ , BOOL & /* bHandled */ );
LRESULT OnAppAbout(WORD /* wNotifyCode */ , WORD /* wID */ , HWND /* hWndCtl */ , BOOL & /* bHandled */ );
LRESULT OnOK(WORD /* wNotifyCode */ , WORD wID, HWND /* hWndCtl */ , BOOL & /* bHandled */ );
LRESULT OnCancel(WORD /* wNotifyCode */ , WORD wID, HWND /* hWndCtl */ , BOOL & /* bHandled */ );
void CloseDialog( int nVal);
LRESULT OnBnClickedButton1(WORD /* wNotifyCode */ , WORD /* wID */ , HWND /* hWndCtl */ , BOOL & /* bHandled */ );
public :
CAxWindow m_wndFlashPlayer;
CComPtr < IShockwaveFlash > m_FlashPtr;
BEGIN_SINK_MAP(CMainDlg)
SINK_ENTRY_EX(SOURCEID, DIID__IShockwaveFlashEvents, 150, OnFSCommand)
END_SINK_MAP()
void __stdcall OnFSCommand(BSTR command, BSTR args);
};
在ATL3.0时,还需要增加COM的映射宏。
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
更早些的方法,SINK_MAP 使用 SINK_ENTRY_INFO 的方式映射事件接受函数
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
其中 FSCommandInfo 的定义如下:
__declspec(selectany) _ATL_FUNC_INFO FSCommandInfo
=
{ CC_STDCALL, VT_EMPTY, 2 , { VT_BSTR, VT_BSTR } };
{ CC_STDCALL, VT_EMPTY, 2 , { VT_BSTR, VT_BSTR } };
这样 CMainDlg 需要这样派生:
class
CMainDlg :
public
CAxDialogImpl
<
CMainDlg
>
,
public
CUpdateUI
<
CMainDlg
>
,
public CMessageFilter, public CIdleHandler,
public CComObjectRootEx < CComSingleThreadModel > ,
public CComCoClass < CMainDlg > ,
public IDispEventSimpleImpl < SOURCEID, CMainDlg, & DIID__IShockwaveFlashEvents >
public CMessageFilter, public CIdleHandler,
public CComObjectRootEx < CComSingleThreadModel > ,
public CComCoClass < CMainDlg > ,
public IDispEventSimpleImpl < SOURCEID, CMainDlg, & DIID__IShockwaveFlashEvents >
最后说说事件的订阅的方法:
有这么几种:
1. 写一个Sink类,继承 IDispEventImpl,如下:
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
![](http://img.e-com-net.com/image/info8/a851f6ebab08498cbe1d2f2c2b23a0c9.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/631f42b035dc4497b25c141371b40678.gif)
![](http://img.e-com-net.com/image/info8/2c9100fab8554b7caad7b3144808b323.gif)
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
事件的订阅可以使用如下代码:
ITestOBJPtr m_TestOBJPtr;
HRESULT hResult = m_TestOBJPtr.CreateInstance( " TestCOM.TestOBJ " );
CTestSink * m_pSink = NULL;
m_pSink = new CComObject < CTestSink > ;
m_pSink -> AddRef();
m_pSink -> DispEventAdvise(m_TestOBJPtr);
// hResult = AtlAdvise(m_TestOBJPtr, (IUnknown *)m_pSink, DIID__ITestOBJEvents, &m_dwCookie);
HRESULT hResult = m_TestOBJPtr.CreateInstance( " TestCOM.TestOBJ " );
CTestSink * m_pSink = NULL;
m_pSink = new CComObject < CTestSink > ;
m_pSink -> AddRef();
m_pSink -> DispEventAdvise(m_TestOBJPtr);
// hResult = AtlAdvise(m_TestOBJPtr, (IUnknown *)m_pSink, DIID__ITestOBJEvents, &m_dwCookie);
上面注释的代码也是可以使用的。在最开始的例子里,还有比较简单的事件订阅的方法:
![](http://img.e-com-net.com/image/info8/7da3525d42b249f380f90d23d1eaafba.gif)
最后记住在合适的时候取消事件订阅:DispEventUnadvise 或者 AtlUnadvise 或者 AtlAdviseSinkMap(this, false)。
以上简单总结了 WTL 使用 ActiveX 控件的相关方法,欢迎拍砖,:-P