📄 cb199912at_f.asp.htm
字号:
<HTML>
<HEAD>
<TITLE>Exposing ActiveX Properties</TITLE>
</HEAD>
<BODY>
<TABLE border=0 width="100%" cellpadding=0 cellspacing=0>
<TR valign=top>
<TD width="100%">
<p class=ColumnTitle><font size="2">CBuilder
at Work</font> </p>
<p class=ColumnSubtitle><font size="2">ActiveX
/ Properties / ATL / C++Builder 4</font></p>
<p class=BodyText> </p>
<p class=Byline><font size="2">By Alain
"Lino" Tadros</font></p>
<p class=BodyText> </p>
<p class=StoryTitle><font size="2"><b>Exposing
ActiveX Properties</b></font></p>
<p class=StorySubtitle><font size="2">Making
ActiveForm Properties Available in other IDEs</font></p>
<p class=BodyText> </p>
<p class=BodyText> In July
1995, I had the pleasure of writing the first ActiveX control using Delphi, and
I talked about it publicly at the Borland Developer Conference in Anaheim, CA.
It was a <i>TButton</i> that clicks - wow! -
and it took 5,400 lines of code just to make it work and "click" in other
containers, such as Visual Basic. </p>
<p class=BodyText> </p>
<p class=BodyText> Then I
joined the Delphi development team and helped create the DAX framework for
developing ActiveX servers, including controls. This wasn't easy considering
the lack of documentation on interface and container requirements. It was a
trial-and-error effort on our part until we got it to work correctly
everywhere. </p>
<p class=BodyText> </p>
<p class=Subheads>RAD for C++</p>
<p class=BodyText> Because
of the tremendous success of the first release of Delphi, the C++ team at
Borland began to see the value of RAD development tools and started working on
an architecture for a product that would allow RAD development in C++. That
product was code named "SCIFI," which evolved into the C++Builder you know
today. </p>
<p class=BodyText> </p>
<p class=BodyText> One of
the challenges in developing C++Builder was selecting which ActiveX framework
to use. Should we implement the DAX framework from Delphi into C++Builder? Or
base it on another framework like MFC or ATL? That wasn't a hard decision: ATL
was the answer. </p>
<p class=BodyText> </p>
<p class=Subheads>The ATL
Framework</p>
<p class=BodyText> ATL
(Active Template Library) is an ActiveX framework from Microsoft, which is
superior to MFC's ActiveX framework. For many reasons it made more sense to use
ATL rather than re-implement the DAX framework in Delphi: </p>
<p class=BodyText> 1)
C++
programmers are accustomed to the way ATL works. It uses templates. </p>
<p class=BodyText> 2)
There's
no need to make major changes and insertions into the compiler, as we had to
with Delphi. </p>
<p class=BodyText> 3)
ATL
was written by Microsoft and works well around all the problems of their own
containers. </p>
<p class=BodyText> </p>
<p class=Subheads>Q&A</p>
<p class=BodyText> Through
the years, I've seen and heard many questions regarding ActiveX development
through newsgroups, conferences, technical sessions, etc. I hope I can shed
some light on some of the critical ones in this article. </p>
<p class=BodyText> </p>
<p class=BodyText> The most
frustrating question is: "After a clean installation of C++Builder 4, a
generated ActiveX control will not work in any container except C++Builder
itself. Why?" </p>
<p class=BodyText> </p>
<p class=BodyText> Well,
the C++Builder development team decided to select the Use dynamic RTL option as the default for projects
generated by C++Builder. It's set on the Linker page of the Project Options
dialog box (see Figure 1). </p>
<p class=BodyText> </p>
<p class=BodyText> </p>
<p class=Captions><img width=333 height=314
src="images/cb199912at_f_image002.jpg" tppabs="http://www.cbuilderzine.com/features/1999/12/cb199912at_f/cb199912at_f_image002.jpg" align=left> <br clear=all>
<b>Figure 1: </b>The
Project Options dialog box. </p>
<p class=BodyText> </p>
<p class=BodyText> As a
result, an ActiveX control generated with C++Builder won't work in containers,
such as Visual Basic, Visual C++, Internet Explorer, Delphi, etc., because it
requires cp3245mt.dll. If you want your ActiveX control or ActiveForm to work
right away in any container, without external dependency, uncheck the Use dynamic RTL option. </p>
<p class=BodyText> </p>
<p class=BodyText> The most
common question is: "After creating an ActiveForm in C++Builder, then dropping
it on third-party development tools, I don't see any properties of the controls
on the ActiveForm in the Object Inspector. How can I publish these properties,
so that I can get to them?" </p>
<p class=BodyText> </p>
<p class=BodyText> To
demonstrate how to do this, let's first generate an ActiveForm that includes
DataSource, Table, DBGrid, and DBNavigator components, and link them to a
database table (see Figure 2). At this point, you're ready to compile and
create an OCX file that can be dropped onto a container. This will allow you to
modify the properties of the ActiveX control from its Object Inspector. The
properties accessible from the Object Inspector at this point are for the
ActiveForm itself, and do not include the properties of the controls placed on
the ActiveForm. For instance, you'll find a <i>Color</i>
property that, when modified, will change the color of the ActiveForm. </p>
<p class=BodyText> </p>
<p class=Captions><img width=333 height=193
src="images/cb199912at_f_image004.jpg" tppabs="http://www.cbuilderzine.com/features/1999/12/cb199912at_f/cb199912at_f_image004.jpg" align=left> <br clear=all>
<b>Figure 2:</b>
The example ActiveForm. </p>
<p class=BodyText> </p>
<p class=BodyText> However,
what if you wanted another <i>Color</i>
property where you can set the color of the DBGrid at the ActiveForm level -
from, say, Visual Basic or Internet Explorer? </p>
<p class=BodyText> </p>
<p class=BodyText> In the
Type Library editor, highlight the main interface, Informant in our example, and add a property named <i>GridColor</i>. Change the type of the property from LONG to OLE_COLOR.
(LONG will work, but containers with built-in editors for <i>Color</i> properties won't be able to display that editor, and users
will have to know the numeric representation of the color they wish to set.)
Then, when you refresh the Type Library editor, C++Builder will automatically
generate the stub for the "get" and "set" methods of the <i>GridColor</i> property (see Figure 3). </p>
<p class=BodyText> </p>
<p class=Code><span class=Code>STDMETHODIMP
TInformantImpl::get_GridColor(::OLE_COLOR* Value) </span></p>
<p class=Code><span class=Code>{</span></p>
<p class=Code><span class=Code> <b> try</b></span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> } </span></p>
<p class=Code><span class=Code> <b> catch</b>(Exception
&e) </span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> <b> return</b>
Error(e.Message.c_str(), IID_IInformant); </span></p>
<p class=Code><span class=Code> } </span></p>
<p class=Code><span class=Code> <b> return</b>
S_OK; </span></p>
<p class=Code><span class=Code>};</span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code>STDMETHODIMP
TInformantImpl::set_GridColor(::OLE_COLOR Value) </span></p>
<p class=Code><span class=Code>{</span></p>
<p class=Code><span class=Code> <b> try</b></span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> } </span></p>
<p class=Code><span class=Code> <b> catch</b>(Exception
&e) </span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> <b> return</b>
Error(e.Message.c_str(), IID_IInformant); </span></p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -