📄 cb199910nf_f.asp.htm
字号:
<HTML><HEAD><TITLE>Creating Custom Components</TITLE>
<META content="text/html; charset=hz-gb-2312" http-equiv=Content-Type>
</head>
<BODY bgColor=white leftMargin=0 topMargin=0 MARGINWIDTH="0" MARGINHEIGHT="0">
<TABLE border=0 cellPadding=0 cellSpacing=0 width="100%">
<TBODY>
<TR vAlign=top>
<TD width="100%">
<h3><b>From the Palette</b></h3>
<P class=ColumnSubtitle>Component Programming / Packages</P>
<P class=Byline>By Neal Ford</P>
<P class=StoryTitle>Creating Custom Components</P>
<P class=StorySubtitle>Part I: New Defaults for Native Components</P>
<P class=BodyText> </P>
<P class=BodyText>Application development in C++Builder revolves around
its component-based architecture. In other words, most complex
functionality is hidden within components. When you need to access a
database, for example, you do so by using components, rather than calling
functions from a class library. C++Builder's system of creating reusable
code through components seems nothing short of revolutionary to
programmers who need to create encapsulated "black boxes." C++Builder
combines components and objects in a way that makes it easy to create
applications - even if you know nothing about creating components. </P>
<P class=BodyText> </P>
<P class=BodyText>There are two types of C++Builder developers: component
users and component writers. When a developer needs to produce
applications rapidly and the project has few complex requirements, he or
she uses components. At other times, the same developer may want to create
generic solutions to problems by making new, reusable components.
Component-based development creates a whole new era of rapid application
development with C++.</P>
<P class=BodyText> </P>
<P class=BodyText>The creation of custom components in C++Builder is
separated into three broad categories. The first (and easiest) consists of
setting new default properties for built-in components. At the next level
of complexity, C++Builder allows the addition of new properties to expand
the capabilities of an ancestor component. The third, and most complex,
process involves adding properties, methods, and events to an existing
component, or building a component from scratch. This article, the first
in a series on creating custom components, covers the first type of
component; the other types will be covered in future installments. </P>
<P class=BodyText> </P>
<P class=Subheads>Components as Classes</P>
<P class=BodyText>Every time a component is placed on a form, C++Builder
instantiates a new object. For instance, when the user drops a DBNavigator
on a form, C++Builder instantiates a new object (named
<I>DBNavigator1)</I> of the type <I>TDBNavigator</I>. To make a new
component class, inheritance is used to take all the properties and
methods of some base class, selectively override some methods, and add new
properties and methods. Before creating components, however, a container
is required to access them. Such containers in C++Builder are packages.
</P>
<P class=BodyText> </P>
<P class=Subheads>Creating a Package</P>
<P class=BodyText>This section covers the creation of a package to hold
newly created components. If you're already familiar with the package
architecture in C++Builder, feel free to skip this section. </P>
<P class=BodyText> </P>
<P class=BodyText>Packages in C++Builder are containers for components.
They're specially formatted DLLs with a .BPL extension. A package allows
objects to be instantiated from it; this is the main distinguishing
characteristic between a standard DLL and a package. All the components in
C++Builder are already in packages. C++Builder also makes a distinction
between design-time packages (only available while the IDE is running),
and run-time packages (which should be distributed with the application).
The distribution strategies enabled by packages is beyond the scope of
this article, but is well-covered in the documentation and online Help.
</P>
<P class=BodyText> </P>
<P class=BodyText>To create a new package, invoke the File | New gallery
and select Package. This will produce the Package editor with a default
named Package. The dialog box is shown in Figure 1. Just like a new
project, the default names and locations should be modified to improve the
readability and maintainability of the application. Because packages are
DLLs, the same rules apply for how they're located at run time by the
application that must load them. So it makes good sense to create a common
output directory in which to place custom packages. Otherwise, the search
path for DLLs becomes very long and cumbersome, slowing down the entire
system's search for DLLs. </P>
<P class=BodyText> </P>
<P class=Captions><IMG height=158
src="images/CB199910nf_f_image002.gif" width=250
tppabs="http://www.cbuilderzine.com/features/1999/10/CB199910nf_f/CB199910nf_f_image002.gif">
<BR><B>Figure 1: </B>The Package editor.<B> </B></P>
<P class=BodyText> </P>
<P class=BodyText>Once a new package is created and named, new components
can be created and added to it. The first new component created for this
article illustrates how to selectively override the default property
values for a selected component. </P>
<P class=BodyText> </P>
<P class=Subheads>Creating a New Component</P>
<P class=BodyText>Probably the simplest type of component that can be
created in C++Builder is one that has new default values for some of the
properties. Developers often find themselves dropping components on a form
and changing the same properties every time. Wouldn't it be nice if it
were possible (and, more importantly, easy, because anything is possible
in C++Builder with enough effort) to override the defaults? It turns out
to be very easy indeed. </P>
<P class=BodyText> </P>
<P class=BodyText>The Package editor allows the creation of a new
component, or the addition of an existing component. Choosing Add in the
Package editor produces the dialog box shown in Figure 2. This dialog box
allows you to add an existing component, create a new component, or import
an ActiveX control. For this article, the New Component option is
exercised. </P>
<P class=BodyText> </P>
<P class=Captions><IMG height=220
src="images/CB199910nf_f_image004.gif" width=250
tppabs="http://www.cbuilderzine.com/features/1999/10/CB199910nf_f/CB199910nf_f_image004.gif">
<BR><B>Figure 2:</B> The Package editor allows the addition of an existing
component.<B style="mso-bidi-font-weight: normal"></B></P>
<P class=BodyText> </P>
<P class=BodyText>The New Component page is shown in Figure 3. This
component is named <I
style="mso-bidi-font-style: normal">TDefaultedDBNavigator</I>. The <I
style="mso-bidi-font-style: normal">TDBNavigator</I> always appears on the
form when it is dropped with all the buttons visible. It also defaults to
have the ToolTips turned off. This first component example changes these
defaults to show only the four navigation buttons and turn ToolTips on.
It's being added to the Component palette page named Informant (new pages
can be created here by specifying a new name). The unit file name
specifies where the source files will live. </P>
<P class=BodyText> </P>
<P class=Captions><IMG height=220
src="images/CB199910nf_f_image006.gif" width=250
tppabs="http://www.cbuilderzine.com/features/1999/10/CB199910nf_f/CB199910nf_f_image006.gif">
<BR><B>Figure 3: </B>The New Component page. </P>
<P class=BodyText> </P>
<P class=BodyText>C++Builder calls the combination of a header and source
file a "unit." The common convention throughout C++Builder is to use a "T"
as the first letter of a class name. This is left over from C++Builder's
Pascal lineage; by convention, all types in Pascal start with "T" to help
distinguish them from variable names (Pascal isn't case sensitive). </P>
<P class=BodyText> </P>
<P class=BodyText>This wizard creates a skeleton source file for the
component. This default output (both the header and source files) is shown
in Figure 4. </P>
<P class=BodyText> </P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>//
--------------------------------------------------------</SPAN></I></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#ifndef
DefaultedDBNavigatorH</SPAN></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#define
DefaultedDBNavigatorH</SPAN></SPAN></P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>//
--------------------------------------------------------</SPAN></I></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#include
<SysUtils.hpp> </SPAN></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#include
<Controls.hpp> </SPAN></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#include
<Classes.hpp> </SPAN></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#include
<Forms.hpp> </SPAN></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#include
<DBCtrls.hpp> </SPAN></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#include
<ExtCtrls.hpp> </SPAN></SPAN></P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>//
--------------------------------------------------------</SPAN></I></SPAN></P>
<P class=Code><SPAN class=Code><B>class</B> PACKAGE TDefaultedDBNavigator
: <B>public</B> TDBNavigator</SPAN></P>
<P class=Code><SPAN class=Code>{</SPAN></P>
<P class=Code><SPAN class=Code><B> private</B>:</SPAN></P>
<P class=Code><SPAN class=Code><B> protected</B>:</SPAN></P>
<P class=Code><SPAN class=Code><B> public</B>:</SPAN></P>
<P class=Code><SPAN class=Code> <B> __fastcall</B>
TDefaultedDBNavigator(TComponent* Owner);</SPAN></P>
<P class=Code><SPAN
class=Code><B> __published</B>:</SPAN></P>
<P class=Code><SPAN class=Code>};</SPAN></P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>//
--------------------------------------------------------</SPAN></I></SPAN></P>
<P class=Code><SPAN class=Code><SPAN
class=CodeGrn>#endif</SPAN></SPAN></P>
<P class=Code><SPAN class=Code> </SPAN></P>
<P class=Code><SPAN class=Code> </SPAN></P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>//
--------------------------------------------------------</SPAN></I></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#include <vcl.h>
</SPAN></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#pragma
hdrstop</SPAN></SPAN></P>
<P class=Code><SPAN class=Code> </SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#include
"DefaultedDBNavigator.h" </SPAN></SPAN></P>
<P class=Code><SPAN class=Code><SPAN class=CodeGrn>#pragma
package(smart_init) </SPAN></SPAN></P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>//
--------------------------------------------------------</SPAN></I></SPAN></P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>// ValidCtrCheck is
used to assure that the components</SPAN></I></SPAN></P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>// created don't
have any pure virtual functions. </SPAN></I></SPAN></P>
<P class=Code><SPAN class=Code> </SPAN></P>
<P class=Code><SPAN class=Code><B>static</B> <B>inline</B> <B
style="mso-bidi-font-weight: normal">void</B>
ValidCtrCheck(TDefaultedDBNavigator *)</SPAN></P>
<P class=Code><SPAN class=Code>{</SPAN></P>
<P class=Code><SPAN class=Code> <B> new</B>
TDefaultedDBNavigator(NULL);</SPAN></P>
<P class=Code><SPAN class=Code>}</SPAN></P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>//
--------------------------------------------------------</SPAN></I></SPAN></P>
<P class=Code><SPAN class=Code><B>__fastcall</B>
TDefaultedDBNavigator::TDefaultedDBNavigator(</SPAN></P>
<P class=Code><SPAN class=Code> TComponent* Owner) :
TDBNavigator(Owner)</SPAN></P>
<P class=Code><SPAN class=Code>{</SPAN></P>
<P class=Code><SPAN class=Code>}</SPAN></P>
<P class=Code><SPAN class=Code><I><SPAN class=CodeBlue>//
--------------------------------------------------------</SPAN></I></SPAN></P>
<P class=Code><SPAN class=Code><B>namespace</B>
Defaulteddbnavigator</SPAN></P>
<P class=Code><SPAN class=Code>{</SPAN></P>
<P class=Code><SPAN class=Code> <B> void</B> <B>__fastcall</B>
PACKAGE Register()</SPAN></P>
<P class=Code><SPAN class=Code> {</SPAN></P>
<P class=Code><SPAN class=Code> TComponentClass
classes[1] =</SPAN></P>
<P class=Code><SPAN class=Code> {<B
style="mso-bidi-font-weight: normal">__classid</B>(TDefaultedDBNavigator)};</SPAN></P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -