ATL建立ActiveX控件(一)

   代码下载http://download.csdn.net/source/1458175

   在VC中进行控制编程可以用MFCOCX形式,也可以用ATL的活动模板库。MFC所做出来的控件比较大,ATL相对小很较多,这时我们如果是在网页上使用,ATL的优势就会突显出来。

      ATL编写控件比MFC要难一些,所谓的难就是ATL中的编程向导没有MFC中的那么好用。有好多的东东要自己手工去加。所以今天我就把ATL控件建立的过程在此阐述一下,供初学者学习。

建立项目,选择VC++下面的ATL工程

出现下面的设置界面,

 

设置如图所示,

Attributed 属性化编程,是未来的方向,在这里不要选它。

Dynamic_Link Library(DLL) 第一个设置意思是建立一个生成动态链接库的项目,也就是最终输出是一个DLL。这就是我们的控件了。在这里我们先中他。

Excutable(EXE) 可执行文件.EXE的形式存在
Server(EXE) 表示建立一个系统服务组件程序,系统启动后就会加载并执行的程序。

Allow merging of proxy/stub code是允许将代理存根代码合并到项目中,否则就是在另一个工程中,要单独编译。这里对它不再细讲。但是要选上它。

Support MFC 支持MFC,除非有特殊的原因,我们写 ATL 程序,最好不要选择该项。在MFC中的东西,在ATL中基本上也都能找到影子,所以不必担心离开了MFC就不行了。

Support COM+ 1.0 支持事务处理的 COM+ 功能。COM+ ?太深奥了,偶也讲不明白了。
好了,点击Finish 就完成了一个ATL项目的建立。

接下来就是我们为这个项目加上ATL控件类,这个也好加,再看下面的的过程:

点击Project 菜单弹出如下:

 

再点击Add Class…弹出下框:

 

再选中 “ATL Control”点击Open 弹出下框:

 

照上图进行输入,再点击Option选项,窗口变化如下:

 

Control Type:

Standard control 即标准控件,在这里我我就选这个

Composite control 即为复合控件,是以表单的形式进行界面处理。

DHTML control 为HTML显示的控件,如果你要在控件进行HTML显示就要用这一项。

Minimal Control 是最小化控件。如果你想控件在编译后最小就用这个,但是可能会有很多你想用的的文件不能加进来,那么就要你自己处理,这样也给你带来的麻烦。在这里我们就不选了。

Aggregation:  聚合的意思, 我们写的组件,将来是否允许被别人聚合(3)使用。只能创建为聚合,有点类似 C++ 中的纯虚类,你要是总工程师,只负责设计但不亲自写代码的话,才选择它。所以我们用 Yes.

Threading Model: COM 中的线程,我认为是最讨厌,最复杂的部分。所以我也是一直云里雾里的,现在吗......大家都先选"单元"(Apartment),它是么意思?简单地说:这样从其他线程中调用组件函数的时候,这些调用会排队进行。所以我们暂时可以不用考虑同步的问题。

Interface: 双重(Dual),这个呀太重要了,我们现在要实现的一切在很大成度上就靠它了。 我们编译型语言都是在编译时就导入了类型库,这样在执行时它就能找到相应的接口函数,但是解释型语言要想调用组件,就成大问题了,它怎么才能找到相应的接口呢,所以这时组件就要实现自动化,其实就是要实现IDispatch 接口。所以在此我们一定要选Dual.这里我们可以看到控件类的基类里会有一个IDispatchImpl.

Connect point:是否支持连接点接口(事件、回调)。这个一定要选上,对于控件内部发生的事件,要想通知调用者,那么有两种方式,一种是回调,实现方法在此不讲了,另一种就是连接点的方式,它相当于是一个虚函数,在调用处实现一下就可以了,使用在后面再讲。

再点击一下Appearance 选项,出现下面界面:

   

照上面进行设置。

Opaque 是指要生一个不透明的控件,如果你想要确保在控件边界之后不显示任何的包容器,选择"opaque"检查框。

solid background 实心背景这是控件传给它的包容器的状态信息。选上吧。

Normalize DC 规格化DC 选择此选项使得你的控件在被调用来绘制自己时创建一个规格化的设备上下文。这标准化了控件的外观,但是效率降低了。此选项生成的代码覆盖了OnDrawAdvanced方法(而不是常规的OnDraw方法)。

Insertable可插入的,选择此选项使得你的控件显示在象Microsoft Excel Word 这样的应用的“Insert Object”对话框中。你的控件就能够被插入到任何支持嵌入对象的应用中了。选择此选项在注册表项中增加了Insertable键。

Windowed only仅为窗口化的,选择此选项迫使你的控件窗口化,即使在支持无窗口对象的包容器中。如果你不选择此选项,你的控件将会自动的适应包容器:在支持无窗口对象的包容器中是无窗口的,在不支持无窗口对象的包容器中是有窗口的。这将使CComControlBase::m_bWindowOnly标志设置为TRUEATL使用此标志来决定在控件激活过程中是否要查询包容器的IOleInPlaceSiteWindowless接口。

Invisible at run time 这个一定不要选,选上了那可能OVER了,此选项使你的控件在运行时不可见。你可以使用不可见控件在后台完成某些操作,例如周期性的激发事件。

Acts like button仿按钮,此选项使你的控件象一个按钮那样工作。此时,控件将在包容器周围属性DisplayAsDefault的基础上显示为缺省的按钮。如果控件的位置标记为缺省按钮,控件将显示为一个较厚的框架。选择此选项在它加入到注册表中后使得控件翻转OLEMISC_ACTSLIKEBUTTON 位。

Acts like label仿标签,选择此选项使得你的控件取代包容器的内部标签。这使得控件在它加入到注册表中后标记OLEMISC_ACTSLIKELABEL

好了,一切OK了,可以了Finish了。

一个控件完成了,是不是很简单呀。让我们来看一下我们控件是什么样子的。先看一下我们代码下面是不是生成了一个PlayerCtrl.htm的文件,这个就是我们控件在HTML中的调用,我们在项目属性中进行设置一下,看下面的配置框:

 

如图我们在Command中设置为IE,意思是我们用IE进行控件调试,在Command arguments中输入PlayerCtrl.htm的文件路径,确定,O了,我们F5一下,出来什么了,看到了吗?肯定是没有看到,哈哈,为什么呢?前面们我记得选中了Windowed only一项,按说生成代码中应该把CComControlBase::m_bWindowOnly标志设置为TRUE,可是向导没有这样做,真是气死人了,555要命了,我们还是自己来加吧,也简单,在CPlayerCtrl类的构造函数中给m_bWindowOnly付下值就可以了,代码是

     CPlayerCtrl()

     {

         m_bWindowOnly = true;

}

再运行,看到了没有,还没有,因为你得让IE不要阻止控件,可是还是看不到,是不是弹出一个对话框了呀,寻问你是否允许控件,点确定,如果还弹一个就再点确定。真够烦的这些框框。

这是因为我们的没有给控件加上安全描述,所以IE要提示,如果你IE安全级别高的话,可能控件就不能用了,这个暂时不处理后面再讲,还是点先确定吧,是不是IE显出个什么带“ATL 7.0 test page for object PlayerCtrl”的框框来呀,这个就是我们的控件了。控件的基本结构编写已经完成,HOHO ^_^

虽然完成了,但是还没有什么功能。还需要我们一步步的加入执行代码。在我上篇文章中描述了播放器控制窗口的实现,下面我们把它移植过来。

首先我们为控件加一个窗口,在ATL工程里窗口的添加和MFCWTL中是不一样的,只能用一种新的方法添加,否则添加的窗口将会不能使用。首先点击”Project”菜单,再点击“Add Class…”菜单项,会弹下面窗口,

我们选择ATL项目下的“ATL Dialog,单击确定,在弹出的窗口中输入CommandWnd,单击确定。

OK 我们的命令控制窗口加好了,但是要注意修改一下窗口的属性,

Border”设为 None 意思是没有没有边框

Style” 设为 Child 意思是设为子窗口

Visible”设为 TRUE 意思是可视的

照同样的办法加一个CViewWnd窗口这将是一个视频窗口。属性也是一样的。

把我们原实现的控制窗口中的内容一点点的添过来。那么我们怎么样把这个窗口显示在控件中呢。

首先把“PlayerCtrl.h”中的OnDraw()函数中的内容注释掉,这里就是我们在IE中看的东东,其实对我们来这是没有什么用的。给控件类中加入两个变量:

CCommandWnd * m_lpCommandWnd;

CViewWnd    * m_lpVideoWnd;

加上OnCreate()及OnSize()函数。如下:

LRESULT CPlayerCtrl::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)

{

     RECT rc = {0};

     this->GetWindowRect(&rc);

     ATLASSERT( m_lpCommandWnd == NULL );

     // 创建新的视频/控制/命令窗口...

     m_lpVideoWnd = new CViewWnd();

     if( !::IsWindow(m_lpVideoWnd->m_hWnd) ) {

         ATLASSERT( m_lpVideoWnd != NULL );

         m_lpVideoWnd->Create(this->m_hWnd, rc);

     }

     m_lpCommandWnd = new CCommandWnd();

     if( !::IsWindow(m_lpCommandWnd->m_hWnd) ) {

         ATLASSERT( m_lpCommandWnd != NULL );

         m_lpCommandWnd->Create(this->m_hWnd, rc);

     }

     return 0;

}

 

LRESULT CPlayerCtrl::OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)

{

     int cx = LOWORD(lParam);

     int cy = HIWORD(lParam);

     int nCmdWndHeight  = 57;

     // 计算视频窗口位置...

     RECT rcVideo  = {0};

     rcVideo.left  = 0;

     rcVideo.top        = 0;

     rcVideo.right = cx ;

     rcVideo.bottom     = cy - nCmdWndHeight;

     if( m_lpVideoWnd != NULL && ::IsWindow(m_lpVideoWnd->m_hWnd) ) {

         m_lpVideoWnd->MoveWindow(&rcVideo);

         m_lpVideoWnd->ShowWindow(SW_SHOW);

     }

     // 计算命令栏窗口位置...

     RECT rcCommand     = {0};

     rcCommand.left     = 0;

     rcCommand.top = rcVideo.bottom;

     rcCommand.right    = cx ;

     rcCommand.bottom = rcCommand.top + nCmdWndHeight;

     if( m_lpCommandWnd != NULL && ::IsWindow(m_lpCommandWnd->m_hWnd) ) {

         m_lpCommandWnd->MoveWindow(&rcCommand);

         m_lpCommandWnd->ShowWindow(SW_SHOW);

     }

     return 0;

}

至此我们的控件界面部分已经完成,可以编译调试了,看看是不是出来了,就是下面的这个:

呵呵,是不是还像一个播放器的样子呀,就是这样了,其实它少一个状态栏,你可以自己再加一个就是会更好看了。

今天这个就先说到这儿了,要知后事如何,请听下回分解!

 

猜你喜欢

转载自blog.csdn.net/wanghaisheng/article/details/4317198