By far the most powerful way to share
code among different displays in ProcessBooks and
different ProcessBooks in general, is to build
an add in. Let's take a look at a quick
add in here. First of all I am going to go into the
add in manager which is part of ProcessBook. As
you can see, we have a selection of add ins here. These are those
add ins that have been registered with Windows on this machine.
This is the one we are going to be doing. I can load
or unload it from here or load it permanently on start up.
And the way this particular
add in works is when you launch
a display, if you double click on
a place where you find
no objects,
you see this little calendar appears.
Now this is going to work no matter what you have got up on
your screen. I will go ahead and launch another display.
And we are seeing the same effect.
So this is an example of how we can
make use the add in
technology that we have built into ProcessBook.
In order to do this, you are going to need a copy of Visual
Basic 6. That's kind of hard to come by these days
because as you may already know, Microsoft
does not sell VB6 anymore. However
if you get the Visual Studio release from
Microsoft or Visual Studio .NET,
you can request the Visual Basic 6 media. There is a wizard
that comes in VB6 that is the most convenient
way to build this add in. And that is what we are going to be demonstrating
in a few minutes. I am going to start to build this
add in by using the wizard in Visual Basic.
So this is going to be Microsoft
Visual Basic.
And the type of project that we are
going to build is an add in. So I will go ahead and choose
add in. And when you choose
add in, you will notice
when we look at the Project Explorer here, you will
notice you get
a form.
This is the design
Doing this will make this a little bit easier
to fit here. Now this is
some graphical user interface
to this selection of how you want to build this add in.
In this case, I need to create this as a ProcessBook
add in. And I also need
to, if I wanted to choose the version, I could do that right here.
I could choose some of the behaviour
here. But more importantly, I can go into the
code and choose view code. And I can remove a lot of
this boiler plate. And this wizard
builds a tremendous amount of boiler plate. And
all we really need is the OnConnect
and OnDisconnect sub-routines. So all these
other things, all the variable
definitions, these sub-routines here... All
of these I can delete.
And this is one of the ones
that I would like to keep. It's the AddInstanceOnConnection
This is the sub-routine that executes
when you load the add in. Except all I need is
the stub. I do not need any of the code that goes with it.
And in fact, I am going to delete it.
So the first step here is to go
ahead and get rid of all of the boiler plate that you think you do not need.
Obviously this is useful stuff.
If I were trying a more complex example,
some of these things may be critical-- things
like manipulating toolbars and what not. But in this case,
I am simply interested in a certain behaviour
when we load the add in, and a certain
behaviour when we unload the add in.
So that's why I keep just these two stubs.
Let's look at a couple of other things
on this project that we may want to clean up at this point.
Again, we just ran this add in wizard
so that we have some boilerplate. Part of the boilerplate
is a form. Now
this form might serve your purposes, but it does not serve my purposes in this case.
So I am going to remove that form.
I am going to select that and right mouse click and remove that
form because I just will not need it in this application.
I am going to be using a different form
and all that code, I just do not want to have to deal
with purging out that code and perhaps leaving behind some
things that interfered later on.
Now at this point, we are just about ready
to start writing some code that does something.
To get hooks
into ProcessBook, we are going to have to somehow,
when this add instance occurs,
somehow get access to the object in
ProcessBook called the application object.
Now if you remember, in a previous example using
WithEvents, we were able to get access to application objects. In fact,
that's where we are going to start here.
So let's take a look at that. It's time for us
to define some variables that are going to be used in here.
I am going to make it real simple, I am going to define two
variables, X and Y.
We will say define with events,
X as a ProcessBook object
library.application.
We are going to define that to be the application object in ProcessBook.
Now did you notice IntelliSense
could not figure out what this is. When
I put my cursor off of there,
we do not see any of the capitalization that you normally see
that indicates that we recognize what that object is.
The reason that is is because we are in a different application here.
We have not made reference to the
ProcessBook object library. So in order to do that,
I need to go into the project
menu. And under project, there is a section called references.
This is where we need to go out and find references
to ProcessBook.
Since ProcessBook is installed on this machine, it
should not be hard. There we go.
We see ProcessBook Symbol and
Type Library. I know
that this is in, not the symbol library, but in the type library. That's where
the large objects, such as applications and
displays are defined. The symbol library is more for
smaller things like trends etc.
I will go ahead and make reference to that.
And of course now, if
I tried doing this again, and dimension this is
as a PB object library. You notice that IntelliSense
recognizes it in that application.
So we will dimension that. We will also dimension
WithEvents
Y as a display.
The reason I needed
to define these two variables, X as in application and
Y as the display. It's because
I need to get access to whenever you open a new
display in ProcessBook. I can do that
through the application object. If you remember, one of the
events in the application object was activating a
display. So everytime a display is
activated, I would like to be able to trigger something.
Also, I want to capture the double click
event when somebody double clicks on a display.
And I can do that by using
this variable Y here to represent my display.
So let's look at what happens first.
What happens first is we need to set X equal to something.
We need to set X equal to the current
ProcessBook application.
So I can do that in the AddInstance
by simply saying, set X equal
to the
current application, the current ProcessBook.
Now I could have just chosen
application. However if you have got a lot of references, as I
said before, there are a lot of objects
called application. We want to make sure that this is the
correct one. So during the initialization
of the add in, at this point we are saying
basically X is going to be a pointer to the ProcessBook
application in general.
The next step is to
check to see when X, which is now
representing our ProcessBook, when
X has had a DisplayActivate event.
Now we actually can go out and find this
since this was defined with events. We can find this
now in the object drop down list box. It
is an object that has events. And as you can see, one of the
events is DisplayActivate.
So I am going to choose in
_DisplayActivate, this is where I am
now going to go out and try to get a pointer
to the specific display
that we may
currently be using. And I have an easy way to do
that. The DisplayActivate,
in fact returns a variable
which is a ProcessBook Display variable.
If we look at the code here, this is returning a ProcessBook
object that is a display variable.
ADisplay is going to be a ProcessBook
Display. What I can do is use that returned value to
say let's set Y equal
to ADisplay. ADisplay is the name of
the display that is being returned by
the DisplayActivate-- so it's the current display.
Y is now going to be a pointer to that current display.
Why do we do that?
We do that because there is an event
in the Y object. Y again is a variable
pointing at a display. There is an event
called ForDoubleClick that I am very interested in.
I would like to
trigger this whenever somebody double clicks
on that display. And it's the Y
variable defined with
events that gives us access to that 4th double click event.
The goal of this add in is
when I double click on a display,
I would like to launch a form that has a calendar on it.
So let's test to see if we can make that hook work. I have
learned from experience that if we simply
invoke this without regard
to whether the user selects an object or not, we are going to have
problems. What I mean by this
is we need some kind of an if then
statement to say, let's just do this is the selected
symbols count is equal to zero. So what I am
going to say is if Y.SelectedSymbols-- remember,
Y is my display. So it has a SelectedSymbols
collection.
We can make use of that by saying, if
its count is equal to zero,
then
we will do something.
That's the end of our if then statement.
So I would like to check
to see if this much works. See the benefit of doing
this first, this if then, is if the
user selects a trend for example, and double clicks on the trend,
normally you would like to see the default
behaviour which is the trend expands. And
if you do not add something like this
to prevent
the user from triggering this
add in script just by clicking on regular
objects, then of course the normal
behaviours in ProcessBook will not work.
So let's see if this works. The easiest
way to test this would be
to compile it into a DLL. Let's
see if it works-- we will do that next.
Now I need to test this so I will do something
really simple here like just put in a message box. Later on we will
worry about that calendar. And before I can test this,
normally I would just make this into a DLL. Before
I do that, a couple of other things. First of all let me change the
name of this. I do not like the default so I will just call it mytest1.
And I will do the same thing
in the Connection Designer. This is the
label.
And now we are ready to go ahead and make it.
I will choose File, Make mytest1.dll.
I put it into the same directory
as everything else. And at this point,
it's not working. The reason it's not working
is because I already have this loaded.
I will unload this and
do that one more time.
File, Make
and we will go ahead and overwrite that.
You see the reason that failed last time
is because I had just been testing before recording this,
I had loaded this add in just to double check and make sure everything
worked, and I forgot to unload it.
When you have an add in loaded, you cannot go through and
start overwriting. Well actually there is a way that you can do that
which we will describe later on.
But the way I am currently configured with my compiler options,
I cannot overwrite that. Now let's test it and see
if it actually works. I just overwrote that .DLL
I will go into the Add In Manager
and as you can see, I found that
add in and I will go ahead and load it.
And it looks like it fails.
But remember, this add in
is triggered by
the DisplayActivate method. And so
far, we have loaded the add in after all the displays were already
active. Now if I were to switch over now, I
believe that's going to load the add in and sure enoug,
that's what happens. So you can see,
because I am doing the DisplayActivate, that's
actually what is giving us the pointer to the current display.