没有找到合适的产品?
联系客服协助选型:023-68661681
提供3000多款全球软件/控件产品
针对软件研发的各个阶段提供专业培训与技术咨询
根据客户需求提供定制化的软件开发服务
全球知名设计软件,显著提升设计质量
打造以经营为中心,实现生产过程透明化管理
帮助企业合理产能分配,提高资源利用率
快速打造数字化生产线,实现全流程追溯
生产过程精准追溯,满足企业合规要求
以六西格玛为理论基础,实现产品质量全数字化管理
通过大屏电子看板,实现车间透明化管理
对设备进行全生命周期管理,提高设备综合利用率
实现设备数据的实时采集与监控
利用数字化技术提升油气勘探的效率和成功率
钻井计划优化、实时监控和风险评估
提供业务洞察与决策支持实现数据驱动决策
翻译|其它|编辑:郝浩|2006-04-29 16:29:00.000|阅读 2257 次
概述:
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
简单的测试
由控件向导生成的TButtonX代码,不需要任何改动,直接编译就会产生一个TButtonX ActiveX控件,我们现在测试一下,点Register Active
Server菜单,注册这个控件,然后在开启Visual Basic开发环境,加入刚才注册的控件,发现它确实是按照我们的设计工作的,注意:如果你在开始创建这个控件的时候,选择了生成About对话框的选项,那么还有一个About属性用于显示关于对话框。
那么这个关于对话框又是怎么回事?代码为我们展示这点:
void ShowButtonXAbout(void)
{
TButtonXAbout* Form;
Form = new TButtonXAbout(NULL);
try
{
Form->ShowModal();
}
catch(...)
{
Form->Free();
return;
}
Form->Free();
}
在TButtonImpl的AboutBox函数中调用了上面的函数来显示对话框,不过有一点作者也不太清楚,就是:
Form->Free();
本来按照Borland的说法,在BCB中不推荐使用Free来释放内存,而应该使用delete这个关键字,但这里为什么这样使用?不过作者做了测试,使用delete也是可以的,没有发现什么问题,所以作者猜测,这里可能是Borland没有更新那个代码向导以适应BCB的开发(可能本来是为Delphi设计的,而Borland只是简单的做了一下Delphi到BCB的转换)。
最后需要说明的是AboutBox函数的DISPID必须是-552,这样ActiveX会把这个函数作为About来对待,其实DISPID的设置还是有强制性,很多标准属性必须是特定的DISPID,这些DISPID都是负值,有兴趣的朋友可以看看MSDN或者COM原理的书籍。
重用 继承?
上面的TButtonX控件简单的通过继承VCL的TButton的实现了一个按钮的AcitiveX控件,如果是其他的VCL能不能同样这样简单的继承就可以方便的生成ActiveX控件呢?在问答前,我们先做一个试验,把刚才这个TButtonX放在Visual
Basic开发环境中,然后使用Spy++这样工具(这里作者使用作者自己开发的MySpy,可以到http://siney.yeah.net下载)看看他的类名:
HRESULT OnDraw(ATL_DRAWINFO& di)
{
try
{
if (m_VclCtl)
m_VclCtl->PaintTo(di.hdcDraw, di.prcBounds->left, di.prcBounds->top);
}
catch (Exception& e)
{
return (static_cast<T*>(this))->Error(e.Message.c_str());
}
return S_OK;
}
前面说这是BCB实现ActiveX机制的关键类TVclControlImpl所具有的代码,用于把控件画在ActiveX宿主窗体上,而这个方法就是来源于TWinControl,所以ActiveX控件的必须继承自这个类(当然如果是自己实现了,就另当别论),这样,很容易想到的是像TLabel这样的VCL控件是无法实现为ActiveX控件的。
那么是不是从TWinControl继承的VCL元件都可以被封装为ActiveX呢?这也不一定,如果你已经把相应的的unit添加进入工程或者已经把它安装了,则这个VCL元件可能不会出现在那个DropDown
列表里,还有就是这个类没有用RegisterNonActiveX函数注册,这个函数专门用来设置那些类不能被封装为ActiveX,这个函数很复杂:
extern PACKAGE void __fastcall RegisterNonActiveX(System::TMetaClass*,
const * ComponentClasses,
const int ComponentClasses_Size,
TActiveXRegType AxRegType);
具体的使用方法可以参考帮助。在CSDN上和Borland新闻组作者也看到过网友询问“为什么我的控件不能出现在AcitveX的生成向导里”,希望下次看过这篇文章的朋友下次可以解决这个问题。
再完善一些
再回到刚才Visual Basic的开发环境,我们来看看到底那些属性和方法被表露了:
而同样的TButton在BCB中却具有非常多的属性,为什么呢?开始作者认为所有的VCL元件都是表露这些基本的属性和方法,但后来作者又做了一个试验,就是简单的封装了TEdit后发现他表露其他的更多属性和方法,参考了一下帮助文档,发现原来有如下规则:
如果VCL的属性或方法不符合上述规则,我们就需要自己实现相应ActiveX代码来表露他们;相反如果符合上述规定,而你又不想表露给最终用户,你可以在Type
Library Editor中删除它们,刷新代码后再删除单元文件中相应的生成代码。
这里需要强调的是:在BCB中设计ActiveX控件在很大程度上是先设计对应的VCL后再封装为ActiveX,而不是像VC那样直接开发ActiveX(其实BCB也可以像VC那样开发ActiveX,毕竟都是使用ATL嘛),这样设计不管是从难易程度还是调试都是非常轻松的。
知道了原理,我们现在要做的是在这个半成品的TButtonX中加入新的事件和属性页,使它看起来更像一个专业的ActiveX控件,对于属性和方法,因为编写这些代码非常简单,为了节省篇幅,这里就不实际添加属性和方法了。
从TButton封装得到的AcitiveX缺少了一个重要的事件,OnMouseMove,下面我们就写代码来表露这个事件,根据我们上面讲述的原理,完成这部分很容易,首先就是在Type
Library Editor里的事件支持接口添加相应方法,如图:
刷新后IDE自动产生相应代码,在Impl单元文件中,加入VCL的OnMouseMove消息处理的转移代码,如下黑体部分:
class ATL_NO_VTABLE TButtonXImpl:
VCLCONTROL_IMPL(TButtonXImpl, ButtonX, TButton, IButtonX, DIID_IButtonXEvents)
{
void __fastcall ClickEvent(TObject *Sender);
void __fastcall KeyPressEvent(TObject *Sender, char &Key);
void __fastcall MouseMoveEvent(TObject *Sender, TShiftState Shift, int
X,
int Y);
public:
void InitializeControl()
{
m_VclCtl->OnClick = ClickEvent;
m_VclCtl->OnKeyPress = KeyPressEvent;
m_VclCtl->OnMouseMove = MouseMoveEvent;
}
这里的m_VclCtl其实就是TButton,他是通过模板参数替换的,所以通过上面的代码TButton的OnMouseMove消息的处理过程转向了MouseMoveEvent,现在我们最后的工作就是编写MouseMoveEvent这个函数处理OnMouseMove消息:
void __fastcall TButtonXImpl::MouseMoveEvent(TObject
*Sender,
TShiftState Shift, int X, int Y)
{
int ss=0;
if(Shift.Contains(ssLeft))
ss=1;
else if(Shift.Contains(ssRight))
ss=2;
Fire_OnMouseMove(ss,X,Y);
}
忽略Sender参数后,再次转发消息流,Fire_OnMouseMove这个函数是由IDE自动产生的,我们直接调用就可以了,它的代码如下:
template <class T> void
TEvents_ButtonX<T>::Fire_OnMouseMove(int Button, int X, int Y)
{
T * pT = (T*)this;
pT->Lock();
IUnknown ** pp = m_vec.begin();
while (pp < m_vec.end())
{
if (*pp != NULL)
{
m_EventIntfObj.Attach(*pp);
m_EventIntfObj.OnMouseMove(Button, X, Y);
m_EventIntfObj.Attach(0);
}
pp++;
}
pT->Unlock();
}
可以看到这部分代码与缺省的Fire_OnClick是一致的,这样添加OnMouseMove事件支持的代码就完成了。
接下来是添加一个属性页,由于VCL的封装,使得开发设计属性页变得非常简单,首先生成一个新的Property Page,这样BCB会为我们产生一个Form,这个Form与普通的Win32开发中Form的最大区别在于它继承自TPropertyPage,所以它有一些独有的方法是我们在设计需要注意的,为了简单起见,属性页里只简单地更改、反馈Caption属性,在实际开发中复杂的属性页是类似的。
属性页与ActiveX交互就是通过2个函数来进行的,而这两个函数都是来自于TPropertyPage类,在缺省生成的Property Page Form里已经加入了这个两个函数的缺省代码,我们要做就是完成这2个函数:
UpdatePropertyPage(void),在打开属性页时,系统会调用这个函数,你可以在这个函数里添加代码用以反映ActiveX的属性在属性页里的显示。
UpdateObject(void),在应用属性时,系统会调用这个函数,你可以把属性页中改变的数据应用到实际的ActiveX控件中。
按照BCB的帮助这两个函数实现起来非常简单,比如UpdateObject(void),就只需要如下代码:
void __fastcall TPropertyPage1::UpdateObject(void)
{
OleObject.OlePropertySet<WideString>("EditMask", WideString(InputMast->Text).Copy());
}
就可以把ActiveX控件的属性更改为属性页中设置的数据,但在作者的计算机上(BCB6+sp4),上面的代码怎么都无法通过编译,无奈之下,作者只好使用原始的方法,代码如下:
void __fastcall TpageNormal::UpdatePropertyPage(void)
{
// Update your controls from OleObjects
IDispatch* ctrl=OleObject;
CComPtr<IButtonX> btnctrl;
ctrl->QueryInterface<IButtonX>(&btnctrl);
edtcaption->Text=String(btnctrl->get_Caption());
}
//---------------------------------------------------------------------------
void __fastcall TpageNormal::UpdateObject(void)
{
// Update OleObjects from your controls
IDispatch* ctrl=OleObject;
CComPtr<IButtonX> btnctrl;
ctrl->QueryInterface<IButtonX>(&btnctrl);
btnctrl->set_Caption(WideString(edtcaption->Text));
}
对于没有ATL、COM知识的读者上面的代码可能比较难懂,建议找些相关书籍熟悉一下。
通过上面的代码,ActiveX控件和属性页之间就可以完美的交互了,最后在ButtonImpl.h文件中加入如下宏映:
BEGIN_PROPERTY_MAP(TButtonXImpl)
PROP_PAGE(CLSID_pageNormal)
END_PROPERTY_MAP()
关于这些宏的说明和原理因篇幅关系这里就不讨论了,BCB的帮助和源码注释里都写的很清楚,感兴趣的朋友可以自己研究一下。至于上面的CLSID_pageNormal是生成属性页时,IDE自动为改属性页生成的ClassID。
这样一个比较完善的ActiveX控件就写完了,是不是非常简单,详细代码可以到CSDN网站下载。
写在最后
由于篇幅关系,本来很多内容可以展开详细讨论,但作者都省略了,本文就当抛砖引玉,感兴趣的读者可以再深入研究。作者想再次强调的是,不管开发ActiveX控件还是Active
Form,最好的方法都是封装(或者转换)为ActiveX,而不是一切从头来,比如你有一个工程,想以ActiveForm的形式用在Web上,那么最好的方法是拿出单独的Form然后转换为ActiveForm,这不需要多复杂的代码,这也是Borland新闻组上专家给的建议。
由于编写ActiveX控件的调试复杂性,所以保证代码质量非常重要,除此之外就是善于利用一些工具来帮助调试,比如Visual Basic、ActiveX
Control Test Container等工具,如果有机会作者会写一些实际开发中可能遇到的调试问题和经验。
参考文献:
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com
面对“数字中国”建设和中国制造2025战略实施的机遇期,中车信息公司紧跟时代的步伐,以“集约化、专业化、标准化、精益化、一体化、平台化”为工作目标,大力推进信息服务、工业软件等核心产品及业务的发展。在慧都3D解决方案的实施下,清软英泰建成了多模型来源的综合轻量化显示平台、实现文件不失真的百倍压缩比、针对模型中的大模型文件,在展示平台上进行流畅展示,提升工作效率,优化了使用体验。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
服务电话
重庆/ 023-68661681
华东/ 13452821722
华南/ 18100878085
华北/ 17347785263
客户支持
技术支持咨询服务
服务热线:400-700-1020
邮箱:sales@evget.com
关注我们
地址 : 重庆市九龙坡区火炬大道69号6幢
慧都科技 版权所有 Copyright 2003-
2025 渝ICP备12000582号-13 渝公网安备
50010702500608号