|
| Best way to import ActiveX control / typelib into existing project? |
 |
18 Jan 2008 21:33:29 -0700 |
After much trial and error and wrestling with sparse documentation and
mysteriously disabled buttons and text boxes in the IDE (which seems
to be the norm here in C++ Builder 2007 world, although hopefully it's not), I
may have finally
managed to learn how to use ActiveX controls in my projects. So far,
this is the cleanest way I came up with to do it, it seems to make
sense and it works well enough:
1) File -> Close All.
2) File -> New -> Package.
3) Tools -> Import Component.
4) Select desired type lib or ActiveX control. Step through wizard,
type appropriate design tab category, ADD UNIT TO CURRENT PROJECT, and
go. Repeat as necessary.
5) Build project. Right-click BPL node in project manager, click
Install.
6) From now on the package is installed, and also appears in the Tools
-> Install Packages list. Not quite sure why building a BPL project
suddenly takes it upon itself to install the package in the IDE for
all projects, the connection seems mysterious to me but in the end
it's what I want anyway so I guess it's all good.
The reason for step #1 is that File -> New -> Package just adds a
package to any existing project that's open, but I just want to make a
simple BPL package wrapper for an ActiveX control that I can use
later, so make sure a new project is started. So this all produces a
BPL package that you may even be able to give to your friends, but I
have no idea how BPL packages work or how to redistribute them, as
I've only been wrestling with C++ Builder for about 3 days now, so
don't take my word for it.
In some cases you may not be able to install the packages because of
component name conflicts. In my case I could not add the Microsoft
Windows Common Controls 2 SP6 type library because the TUpDown wrapper
classname was already registered by some other component package.
Unfortunately, although it would be very convenient, the import wizard doesn't
let you pick and choose which
ActiveX controls to make wrappers for (or redefine their names). However, you
can still easily work around
this by using the Refactor tool to rename any conflicting classes in
the generated wrapper code before building the package (like rename
TUpDown to TUpDown2 or whatever) -- just find an occurrence of TUpDown
(e.g.) somewhere in the right context, click on it, and the Refactor
tool should be enabled.
This almost works perfectly except for the minor issue of it asking me
where package headers are every time I use the components in another
project. I don't know why this information isn't stored in the BPL,
and why it's asking me this. It's not like I changed it from when it
was built. This is irritating but in the end it's not a show stopper,
just browse to the header file and it will work out (how can I make
this not happen, though)?
Is the above method the best way to add an ActiveX control for use in
all projects? Note that I'm looking into C++ Builder as an alternative to MS
VC++ and VB -- but something I've gotten used to in VB is going to the ActiveX
component browser, checking the box next to the one you want, and voila it's in
your project. So it seems strange to me that in C++ Builder I'd have to create
this weird new BPL project, not even type any code on my own, and build it and
save it to add ActiveX controls to the design toolbox -- this seems like
something that would be more appropriate as a Project Option somewhere or
something. So I'm wondering if I'm adding ActiveX components correctly or if I'm
taking some weird unnecessary roundabout way of doing it.
Now my real question: Let's say I have a *specific* project that I want
to use an ActiveX control in, but I don't want to affect the component
collection for other projects. How do I do this? I had a normal VCL
Forms Application and when I used the Import ActiveX control tool, it
did indeed add the wrapper source files to my project -- but it didn't
add the components to the design toolbox. I don't know why. Another
thing I tried was adding a New Package to my existing VCL Forms
Application, and importing the ActiveX control wrapper files into
there. But that's the same as just making a new package from scratch
-- it installs the ActiveX control for all packages.
How can I use an ActiveX control in just my one project? Is there some
sort of "Use ActiveX Control" tool that just adds it to the toolbox
for this project, no questions asked, and everything works out?
Also, and this is not quite related, but in many programs that provide GUI's for
editing ActiveX control
properties (like VB), certain properties are displayed with drop down lists of
named choices. I think the names of the choices are stored in the
type library in the OCX file (for example I can import MS Common
Controls 2 into VB, and the "Orientation" property displays
meaningful
names like Horizontal and Vertical for its values). In C++ Builder, I am never
presented with
meaningful property names for enumerated property values for imported ActiveX
controls -- instead I
just have to type integers in. This is just a minor thing, but is this
a shortcoming of C++ Builder or is it a problem with the design of the
ActiveX control in question? All imported controls seem to do this,
even when they don't have this issue in other programs. Also even
Microsoft's own controls have this behavior, and I do place at least a
little bit of faith in Microsoft to develop their own core ActiveX
controls to take advantage of as much of ActiveX as possible. It
doesn't make a difference whether I import the OCX as an ActiveX
control or as a Type Library in the wizard. Mostly I'm just wondering, it's nice
to have pretty names for values so you don't have to trace through obscure
header files and documentation to find the actual integer values for certain
properties.
Thanks,
|
| Post Reply
|
| Re: Best way to import ActiveX control / typelib into existing project? |
 |
Sat, 19 Jan 2008 08:21:12 -080 |
"Jason Cipriani" <jason.cipriani@gmail.com> wrote in message
news:47918ba9$1@newsgroups.borland.com...
> After much trial and error and wrestling with sparse documentation
Yes, earlier versions of the IDE had great documentation. When Borland
switched to the new help system (with BDS2006) the documentation team
started from scratch in most areas. RAD2007 has much more content than
BDS2006 did but there are still plenty of gaps. In some cases the
documentation is actually there but you just have to know how to navigate to
it.
> mysteriously disabled buttons and text boxes in the IDE
For example? I'm not sure what you mean here.
> [snip]
BPL (Borland Package Library) files are special DLLs for Borland (now
CodeGear) products. Packages can contain runtime and/or design-time code.
A design-time package contains registration information to add components to
the "Component Palette".
> Not quite sure why building a BPL project
> suddenly takes it upon itself to install the package in the IDE for
> all projects
It has been a wish of mine (and many others here over the years) that
Borland/CodeGear would come up with a system where a package could be
selectively added to a project/project group at design-time. Instead, the
way it currently works is that all design-time packages are available to
every project. A package must be individually *excluded* for every project
if you really don't want to see the components of that package in the
palette.
If you don't need an ActiveX control to be present at design-time then you
don't need to add one to a package. You can add it directly to your
application project, if desired. However, if you do need the ActiveX
control available at design-then your only option is to do as you have done
and add it to a new or existing design-time package (or a
runtime/design-time pair ... but that's another topic for another day).
> In some cases you may not be able to install the packages because of
> component name conflicts.
[snip]
> Unfortunately, although it would be very convenient, the import wizard
> doesn't let you pick and choose which
> ActiveX controls to make wrappers for (or redefine their names).
Multiple types exist in each ActiveX library. Many types are dependent on
other types existing. If you desire customization then I believe you should
perform that customization after importing and before installing the
package.
> This almost works perfectly except for the minor issue of it asking me
> where package headers are every time I use the components in another
> project.
This means the location that you placed the ActiveX unit files is not in the
include search path. You should pick a standard location to place all of
your custom units that will exist in the palette and then make sure that
path is in the global include path and the generated library is in the
global library path (Tools | Options | Environment Options | C++ Options |
Paths and Directories). You can place your units in different directories
but ultimately that path must be known to the IDE or else you will
continually get the "missing files" error.
> I don't know why this information isn't stored in the BPL,
A BPL is a redistributable package. It doesn't contain all information
about a project. It might be nice if CodeGear were to create another file
type that references the BPL, BPI, LIB, and H/HPP files but that is not
currently how the system works. The system works by using the lookup paths.
This also means that unit and package names must be unique.
> Now my real question: Let's say I have a *specific* project that I want
> to use an ActiveX control in, but I don't want to affect the component
> collection for other projects. How do I do this?
I believe I answered that question above but I'll paraphrase. If you need
it available visually then the only current option is to add it globally.
BTW, the CodeGear term for what you know to be "toolbox" is
"component
palette" or "palette" for short.
> Also, and this is not quite related, but in many programs that provide
> GUI's for editing ActiveX control properties (like VB), certain
> properties are displayed with drop down lists of
[snip]
My memory says that this used to work in the past (I could be wrong though).
I haven't played with ActiveX much yet in RAD2007.
Clayton
|
| Post Reply
|
| Re: Best way to import ActiveX control / typelib into existing project? |
 |
19 Jan 2008 18:04:12 -0700 |
Thanks for the reply, Clayton. That cleared a lot of things up. I have a couple
minor issues, still, and some comments.
>For example? I'm not sure what you mean here.
Well, truthfully, I'm not sure what I was frustrated with when I wrote this but
I have a hunch it was nothing real. I was probably talking about the
"Refactoring" menu item or the class names text box in the import
wizard or something equally silly.
>BPL (Borland Package Library) files are special DLLs for Borland (now
>CodeGear) products.
So, do I need to redistribute the BPL files with my application? What confuses
me is: Microsoft's dependency viewer shows that the executable does indeed
reference the BPL libraries. This tells me I need to redistribute the BPL's just
like any other dynamic library. However, I compiled a simple VCL Forms
Application (not using any custom packages) and ran it on another machine as a
test. It ran just fine and I did not need to redistribute any files at all, and
I am 99.999% positive that the test machine didn't have any other Borland stuff
or BPL files on it.
If I do indeed need to redistribute the BPL's, is there a statically linked
equivalent of a BPL that I can use (both for the standard CodeGear BPL's and
also for my own custom ActiveX wrapper packages)? If there isn't, is there a
handy packaging wizard or something that I can use to make shipping applications
with the required files as painless as possible?
> Packages can contain runtime and/or design-time code.
>A design-time package contains registration information to add components to
>the "Component Palette".
This is what had me confused about why I had to enter the header location. I had
originally been thinking of BPL's being more like Frameworks on OSX or
something, where they had both runtime and designtime code and were completely
self-contained. But since they're just DLLs in disguise, it make sense to me
now.
I guess it also makes sense why you have to make package wrappers for ActiveX
controls rather than just adding them to projects -- you need to have the
wrappers so that they conform to the same interface that all the other VCL stuff
does. Still, it would be nice if Builder had direct support for ActiveX controls
in the designer (so you could use them at design time without having extra
packages) and then simply added the generated wrapper code to your project when
you used the control (and automatically generated some initialization code to
apply the properties you had set in the designer) -- that way it's available
both in the designer, and with the nice wrapper API, and wouldn't require any
special packages or anything.
>Multiple types exist in each ActiveX library. Many types are dependent on
>other types existing. If you desire customization then I believe you should
>perform that customization after importing and before installing the
>package.
I agree, although in the case of importing ActiveX controls, the customization
here always consists of exactly the same process: Attempt install, check which
wrapper class names are duplicates, refactor wrapper class names to something
else. Since it's always the same and the Refactoring tool is part of the IDE, it
seems like it would be reasonable to have a step in the wizard that let you
automate this process: map default wrapper class names to new wrapper class
names then automatically run the refactoring tool post-import (it was the
wrapper class name like TUpDown that caused the conflict, not the type names in
the ActiveX control itself). Of course, on the other hand, importing ActiveX
controls and dealing with name conflicts doesn't really seem all that common,
and it's easy enough to deal with anyway.
---
All right, so, just a few minor questions:
1) If I use a BPL package that contains wrappers for more than one ActiveX
control (in more than one OCX file), and I only use a few of the controls in
that package, are references to the other unused OCX files discarded? E.g.,
let's say I wanted to make a huge BPL package containing wrappers for every
single ActiveX control I have on my system. Can I redistribute that with
applications without having to redistribute every OCX that I have on my system
(most being unused by any given project) as well?
2) Just to make sure; if you want an ActiveX control available at design time,
you have to generate and install a BPL with a wrapper. If you only want the
control available at runtime, then it's fine to just use the Import ActiveX tool
to import the unit into the current project and not deal with the Package stuff
at all. In both cases you end up with a nice convenient wrapper around the
ActiveX control. Right?
3) Does C++ Builder care that BPL files actually have a .bpl extension? I have
not had a chance to test this yet, but can I set the output filename for a
package project to anything I want and have it all work as normal?
Thanks again,
Jason
|
| Post Reply
|
| Re: Best way to import ActiveX control / typelib into existing project? |
 |
Sun, 20 Jan 2008 10:24:33 -080 |
"Jason Cipriani" <jason.cipriani@gmail.com> wrote in message
news:4792ac1c$1@newsgroups.borland.com...
>>For example? I'm not sure what you mean here.
>
> Well, truthfully, I'm not sure what I was frustrated with when I wrote
> this but I have a hunch it was nothing real. I was probably talking about
> the "Refactoring" menu item or the class names text box in the
import
> wizard or something equally silly.
Refactoring is an area that needs improvement for us C++ guys. Delphi has a
dozen refactoring options where the C++ side only has "rename". In
future
versions of the IDE we expect to get more here.
> So, do I need to redistribute the BPL files with my application?
There are two main options. The first is to redistribute all BPLs with your
application. With this option you can use dependency walker (or similar
tool) to see which BPL files your application requires.
The second option is to make the application standalone. By doing this it
will only require OS DLLs. There are two settings that must be changed in
your application's project options (at "Project | Options") in order
to
achieve this. The first setting is under "Linker | Linking" and is
named
"Dynamic RTL". Uncheck this to statically link the run-time library
(memory
allocation, etc). The second setting is under "Packages". Uncheck
"Build
with runtime packages" to statically link the package code into your
application. Note, once making these changes you may have to add some more
paths to your project's "library" search path. Paths to .RES and .DFM
used
by packages must be added. You may also need to hand edit your
application's project file (.cbproj) to make sure the correct .LIB files
have been added. This is an area where Borland/CodeGear still needs to
improve the process.
One more note about packages. The BPL file is the binary file (a DLL).
There are two other important files that get generated for a package
project. BPI is the import library used when building *with* runtime
packages. LIB is the library used when building *without* runtime packages.
You may notice these extensions in the project file or in the IDE at various
times.
> It ran just fine and I did not need to redistribute any files at all,
> and I am 99.999% positive that the test machine didn't have any other
> Borland stuff or BPL files on it.
I'm not sure what went on in your test. If the application was a VCL forms
application that was built requiring runtime packages then it must have
found the files somewhere on the other system.
> If I do indeed need to redistribute the BPL's, is there a statically
> linked equivalent of a BPL that I can use (both for the standard CodeGear
> BPL's and also for my own custom ActiveX wrapper packages)?
Aside from what I mentioned at the top of this post there is an alternative
to option 1. There is a way to statically link certain packages while
dynamically linking others. Your ActiveX library will most likely require
RTL, VCL, and maybe a few others. In your application make sure those
packages are in the "Runtime packages" list. However, you can remove
your
ActiveX package from this list (and make sure its .LIB file is in the
<AllPackageLibs> section of the .cbproj file). This will statically link
the ActiveX package while dynamically linking everything else.
> If there isn't, is there a handy packaging wizard or something that I can
> use to make shipping applications with the required files as painless as
> possible?
There are third-party products that can do this. Though, I just use
Dependency Walker.
> 1) If I use a BPL package that contains wrappers for more than one ActiveX
> control (in more than one OCX file), and I only use a few of the controls
> in that package, are references to the other unused OCX files discarded?
I believe the nature of COM is that the EXE or DLL server isn't loaded until
the component is first used/created. If that's the case then you should be
fine. However, I'm not 100% sure of this.
> 2) Just to make sure; if you want an ActiveX control available at design
> time, you have to generate and install a BPL with a wrapper. If you only
> want the control available at runtime, then it's fine to just use the
> Import ActiveX tool to import the unit into the current project and not
> deal with the Package stuff at all. In both cases you end up with a nice
> convenient wrapper around the ActiveX control. Right?
Yes, if the "create component wrappers" check box is checked.
> 3) Does C++ Builder care that BPL files actually have a .bpl extension? I
> have not had a chance to test this yet, but can I set the output filename
> for a package project to anything I want and have it all work as normal?
Through the normal package loading system the name of the BPL cannot be
changed from how it was compiled. The name of the BPL file is stored in the
BPI file for the package. There is an option in the package project file
named <OutputExt> that you can play with to see if you can generate a
different extension for the BPL. I've never played with that setting.
If you load packages manually (check out LoadPackage in the help) then you
can name the BPL whatever you want.
Clayton
|
| Post Reply
|
| Re: Best way to import ActiveX control / typelib into existing project? |
 |
Sun, 20 Jan 2008 11:14:19 -050 |
WRT code renaming, I've change my opinion a little -- a recent bad
experience attempting to use the shell list view ActiveX control rather than
the built in one (see recent post on
borland.public.cppbuilder.vcl.components.using) was the breaking point. So
far nearly every ActiveX library I've imported has had some sort of class
naming conflict. If somebody at CodeGear reads this, perhaps they will be so
kind as to add an "Ax" or something to the beginning of wrapper class
names
for ActiveX controls, at the very least. This way TAxListView or TAxToolbar
or TAxWhatever isn't going to conflict with other class names already
registered. This seems like a very reasonable thing to do. It's a big
namespace, and conflicts seem very likely. Having unique names for imported
wrapper classes would eliminate / greatly reduce the need to refactor things
every time a control is imported.
Jason
|
| Post Reply
|
|
|