工具软件   办公软件   操作系统   网络安全   设计在线   程序开发   教程宝典   软件下载   软件论坛
您的位置:软件 > 开发者网络 > 开发工具 > 开发专栏 > VC > 正文
MFC程序员的WTL指南之包容ActiveX
[文章信息]
作者:LITHE
时间:2005-02-22
出处:BLOG
责任编辑:方舟
[文章导读]
在本文中我将介绍ATL对在对话框中使用ActiveX控件的支持
advertisement
热点推荐
· 系统安全卫士SPY Destroy
· 绕过身份验证加对方为好友
· 2月21日软件精选 QQ被盗原因及防范
· Visual Basic上机考试综合应用题选讲
· 所有Win XP系统将自动升级至SP2
[正文]

上一页  1 2 3 4 5 6  下一页

  编写事件处理函数

  好了,等了这么长时间(吹个口哨!),我们可以写事件处理函数了:

void __stdcall CMainDlg::OnDownloadBegin()
{
 // show "Please wait" here...
}

  现在来看一个复杂一点的事件,比如BeforeNavigate2,这个事件的原型是:

void BeforeNavigate2 (
 IDispatch* pDisp, VARIANT* URL, VARIANT* Flags,
 VARIANT* TargetFrameName, VARIANT* PostData,
 VARIANT* Headers, VARIANT_BOOL* Cancel );

  此方法有7个参数,对于VARIANT类型参数可以从MSDN查到它到底传递的是什么类型的数据,我们感兴趣的是URL,是一个BSTR类型的字符串。

  描述BeforeNavigate2事件的_ATL_FUNC_INFO结构是这样的:

_ATL_FUNC_INFO BeforeNavigate2Info =
{ CC_STDCALL, VT_EMPTY, 7,
{ VT_DISPATCH, VT_VARIANT|VT_BYREF, VT_VARIANT|VT_BYREF,
VT_VARIANT|VT_BYREF, VT_VARIANT|VT_BYREF, VT_VARIANT|VT_BYREF,
VT_BOOL|VT_BYREF }
};

  和前面一样,返回值类型是VT_EMPTY表示没有返回值,nParams是7,表示有7个参数。接着是参数类型数组,这些类型前面介绍过了,例如VT_DISPATCH表示IDispatch*。

  事件响应链的入口与前面的例子很相似:

BEGIN_SINK_MAP(CMainDlg)
 SINK_ENTRY_INFO(37, DIID_DWebBrowserEvents2, DISPID_DOWNLOADBEGIN,OnDownloadBegin, &DownloadInfo)
 SINK_ENTRY_INFO(37, DIID_DWebBrowserEvents2, DISPID_BEFORENAVIGATE2,OnBeforeNavigate2, &BeforeNavigate2Info)
END_SINK_MAP()

  事件处理函数是这个样子:

void __stdcall CMainDlg::OnBeforeNavigate2 (
 IDispatch* pDisp, VARIANT* URL, VARIANT* Flags,
 VARIANT* TargetFrameName, VARIANT* PostData,
 VARIANT* Headers, VARIANT_BOOL* Cancel )
 {
  CString sURL = URL->bstrVal;

  // ... log the URL, or whatever you''d like ...
 }

  我打赌你现在是越来越喜欢ClassWizard了,因为当你向MFC的对话框插入一个ActiveX控件时ClassWizard自动为你完成了所有工作。

  将CMainDlg转换成对象需要注意几件事情,首先必须修改全局函数Run(),现在CMainDlg是个COM对象,我们必须使用CComObject创建CMainDlg:

int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
{
 CMessageLoop theLoop;
 _Module.AddMessageLoop(&theLoop);

 CComObject<CMainDlg> dlgMain;

 dlgMain.AddRef();

 if ( dlgMain.Create(NULL) == NULL )
 {
  ATLTRACE(_T("Main dialog creation failed!\n"));
  return 0;
 }

 dlgMain.ShowWindow(nCmdShow);

 int nRet = theLoop.Run();

 _Module.RemoveMessageLoop();
 return nRet;
}

  另一个可替代的方法是不使用CComObject,而使用CComObjectStack类,并删除dlgMain.AddRef()这一行代码,CComObjectStack对IUnknown的三个方法的实现有些微不足道(它们只是简单的从函数返回),因为它们不是必需的--这样的COM对象可以忽略对引用的计数,因为它们仅仅是创建在栈中的临时对象。

  当然这并不是完美的解决方案,CComObjectStack用于短命的临时对象,不幸的是只要调用它的任何一个IUnknown方法都会引发断言错误。因为CMainDlg对象在开始监听事件时会调用AddRef,所以CComObjectStack不适用于这种情况。

  解决这个问题要么坚持使用CComObject,要么从CComObjectStack派生一个CComObjectStack2类,允许对IUnknow方法调用。CComObject的那个不必要的引用计数并无大碍--人们不会注意到它的发生--但是如果你必须节省那个CPU时钟周期的话,你可以使用本章的例子工程代码中的CComObjectStack2类。


上一页  1 2 3 4 5 6  下一页

发表评论推荐给朋友我想参加相关培训打印我对此感兴趣订阅电子杂志
相关内容焦点新闻
  • 用递归算法解决VC中CEdit的一个Bug
  • 木马中如何编程实现远程关机(VC版)
  • VC下利用OpenGL构造自由型曲线曲面
  • MFC程序员的WTL指南之高级界面类
  • Visual C++ MFC 中常用宏的含义
  • 夏普第8代液晶生产动工 下半年将变革策略
  • 手机闲置造成资源浪费 专家呼吁早出台法规
  • IT卖场网站竞争加速 在残酷现实中沉默前行
  • 笔记本市场硝烟再起 家用笔记本年内翻番
  • 信息化时代:谁来保护我们的个人信息?
  • 维权法宝:别让信息化的证据“稍纵即逝”
  • 中国软件三痛之人才篇:外包是“重灾区”
  • 关于我国电子政务建设信息共享策略的反省
  • Advertisement