Академический Документы
Профессиональный Документы
Культура Документы
Pa r t 1
Introduction
Good Morning and welcome to the first instalment in this ActiveX control tutorial.
Today, we'll be:
• Getting the low-down on ActiveX components
• Finding out the difference between ActiveX components and ActiveX controls
• Discussing a few nerdy things (too boring to mention)
• And…. <drum roll> … we'll be creating our own ActiveX control!
I know you're excited – but please, hold it in.
So without further ado, let's tootle off into the magical realms of ActiveX...
What's an ActiveX Control?
What's the difference between a horse trainer and a tailor? One tends a mare and one
mends a tear!
And now for another belly-chuckler - what's the difference between an ActiveX
component and an ActiveX control?
OK, not quite a dinner party puzzler but still an important point. Let's take a look at what
exactly an ActiveX component is... and is not.
An ActiveX component is just a general term, encompassing:
• An ActiveX EXE
• An ActiveX DLL
• An ActiveX Control
An ActiveX component is not:
• Active, in any way, shape or form
• A source of fibre that can help you lose weight as part of a calorie controlled diet
So what exactly are ActiveX EXEs and DLLs? Basically, they're chunks of code you use
in your Visual Basic projects just by setting a reference to them – a little like how you set
a reference to DAO or ADO when you need access to a database.
But that's another department completely... more to the point, just what are ActiveX
controls?
Well, you might not know this, but you already have experience of ActiveX controls.
You've used them, tweaked them and tossed them to one side – all in the course of a days
work. Ohhhh yes.
Indeed, every time you set the Text property of a Text Box, you're utilising an ActiveX
control. Every time you respond to the Click event of a Command Button, you're utilising
an ActiveX control. Every time you run the MoveNext method of the Data control, you're
utilising an ActiveX control.
I think you get the picture. In essence, an ActiveX control is anything you might see in the
Toolbox.
Top Tip: Don't forget that you can also add more controls to the Toolbox by selecting
Projects, Components
Err, so what?
• Now resize the workspace so it just touches the bottom edges of your Option
Button – like this:
Now the stuff you currently see in your workspace will become your 'control', the thing
your user sees when adding it to their forms.
Hmm, it's about time we added some code. Not much, just a lil'.
• Enter the code window by selecting View, Code
• Type in the following code:
Public Sub Flash()
tmrAnimation.Interval = 300
End Sub
This just sets the Interval property of tmrAnimation to around a third-of-a-second (300
milliseconds). When the Timer springs into action every 300-milliseconds, it fires its Timer
event.
So let's add code to that...
• In the Object drop-down list (which currently says General), select 'tmrAnimation'
• The Procedure drop-down list next to it should say 'Timer' – if not, select the
'Timer' event from the list
Your screen should look a little like this at the moment:
NoOfFlashes = NoOfFlashes + 1
'Increment the variable to show number
'of times we have "flashed"
If NoOfFlashes = 8 Then
'If we've had eight separate flashes so far
tmrAnimation.Interval = 0
'... and turn off the timer
End If
That's it! You've completed the creation of your first ActiveX control.
Now let's put it to the test...
Testing our Control
Let's see what all that hard work has given us.
• Click File, Add Project
• Select 'Standard EXE' and click Open
Now we have two different projects open at the same time; our control and this new
Standard EXE thing we've just created.
Let's add our new control to the Standard EXE now.
• Drag out the Flasher control ( ) on your toolbar onto Form1, like this:
Top Tip: If your Flasher control is greyed-out... it means your copy of Visual Basic has
been attacked by huge killer bees from the terrifying jungles of Outer Mongolia or you
haven't closed the workspace of your control. Hmm, probably the latter actually. Close
the workspace and try again!
See how your Option Button appears?
Look in the Properties window. Can you see all the Properties your control already has? A
Name property, TabIndex, ToolTipText... and more! These are all assigned by default.
Now...
• Add a Command Button to the form
• Place the following code behind it:
Flasher1.Flash
The method you've just tapped in is the one we coded!
When we added the 'Public Sub Flash' code, it's automatically turned into one heckuva
groovy method!
Try hitting F5 and running your application. Now hit the Command Button! See what
happens?
The Option Button should flash for a few seconds... great for highlighting a warning of
some sort. But not so great at anything else.
P a rt 2
Introduction
welcome to the second part in this cool ActiveX tutorial.
As ever, I'm your surprisingly sophisticated host Karl Moore – and this week we'll be
covering:
• Creating property procedures
• Enumeration (whoah!)
• Dealing with resizing
Notice how the text box inside our control doesn't automatically resize itself?
• Right click on 'Project2' in the Project Explorer and click Remove Project, not
saving any changes
The text box doesn't automatically resize because as of yet, we haven't told it to. Oh, and
'cause Visual Basic is about as smart as the winner of last year's "World's Scruffiest Bloke"
competition.
• Click View, Code to enter the code window
• Select UserControl from the Object drop-down box
Don't forget that the UserControl is just your control. When something happens to it,
certain events fire – such as Initialize, Resize, LostFocus and so on. It's the equivalent of
the Form object in regular programming, where you have events such as Load and
Unload.
• Select Resize from the Procedure drop-down box
• Add the following code to your project:
Private Sub UserControl_Resize()
With txtTextBox
.Height = UserControl.ScaleHeight
.Top = UserControl.ScaleTop
Sure, it's about as stunning as Queen Elizabeth's bottom, but this is only the second
tutorial...
[Ed: So by the last instalment should we expect something akin to Pamela Anderson?]
Decisions, Decisions...
Now I want the person using this control to be able to decide whether the text box should
accept just letters, numbers or both – and whether letters entered should be converted to
upper or lower case.
So I've already determined two possible properties:
• AcceptType – should it hold just letters, numbers or both?
• ConvertCase – automatically convert to upper case, lower case or neither?
But how will the user tell me which they wish to use? I could perhaps tell them to set
AcceptType=1 if they wish to hold letters, 2 if they only require numbers and so on. Err,
but that ain't too user friendly. And you know how darn picky those users get.
This is where enumerations come into play. Yessiree, that's another geeky word designed
to scare off potential programmer types. But it's really very simple.
• Back in your project, open the code window
• Enter the General Declarations section
End Property
End Property
Here we have a let and a get. The let piece of code runs when a user tries to set the value
of our AcceptType property. And the get piece runs when someone tries to retrieve the
value of AcceptType.
Apart from that rather important difference, this property lark isn't that dissimilar from
regular subs and functions. You can imagine that the let piece of code is a sub, that
accepts the new value of AcceptType in the passed vNewValue. And the get piece of code
works just like a function – to send information back to the user, you simply set
AcceptType to a specific value.
Following me?
[Reader: Yeah, in the same way the King of Egypt followed Moses...]
Let's take a peek at an example property let and get pair...
Dim strUserName as String
End Property
Here, we have a local variable called strUserName.
When the property is set...
MyControl.UserName = "John"
... the let procedure runs and sets the value of strUserName.
When the property is retrieved...
MsgBox MyControl.UserName
... the get procedure runs and returns the value of strUserName.
That's exactly how most property procedures work. But we're using enumerations to make
life easier for our end user... yet alas, slightly more difficult for ourselves.
• Change the skeletal property procedures Visual Basic created for us to something
like this:
Public Property Get AcceptType() As CharacterType
End Property
The only important thing we've done here is to change 'Variant' to 'CharacterType'. If the
user passes a variant, they could be sending anything our way. This way we're saying –
you will pass us one of the CharacterType options and nothing else. Haha, the power!!
Muhahaha!
<ahem>
Top Tip: If you wanted the user to just supply a True or False value, you could always
use 'As Boolean' in place of 'As CharacterType'. Or perhaps 'As Integer' or 'As String'.
Now let's add actual code to bring the property procedure to life:
• In the General Declarations section, declare the following:
Dim m_CharType as CharacterType
• Add a little more code to our AcceptType property procedures, changing them to:
Public Property Get AcceptType() As CharacterType
AcceptType = m_CharType
End Property
Public Property Let AcceptType(ByVal CharType As CharacterType)
m_CharType = CharType
End Property
Think about it for a short while. Do you understand what's happening here? The
m_CharType variable stores the actual value.
Top Tip: You're probably wondering why we're bothering to code all these Property
Get/Let statements – when it seems to do just the same job as a public variable. The
difference here is that you have the power to add code behind your Get/Let statements,
whereas with a public variable you have no control whatsoever. In other words, you
could have a property that accepts some usernames – but if they choose 'Admin', you
could tell them to go swizzle. Erm, programmatically speaking, of course.
• Now add the ConvertCase property to your project:
Dim m_CaseType As Integer
If you click on any of our custom designed properties, you should be presented with a
combo box – enabling you to select any of our defined options!
Try changing the options. Does it work?
Note the numbers next to each option. These are automatically added by Visual Basic.
Now try adding a command button – and insert code behind it that changes our two
properties in code. Notice that just after you type...
Control.OurProperty =
... it allows you to select one of our options, making your code much easier to read. Isn't
that pleasing!?
Now, using the instructions I gave you last week, set the Standard EXE project as 'startup'
– then run it, both setting and reading our properties in code.
Did it all work? What happens when you read the properties?
'UserControl1' isn't a very professional name. Why not try changing it to something like
'TextBoxPro' using the techniques we explored last week?
Conclusion
This week we've started work on our wizzy intelligent text box control. We discussed
resizing and then explained properties.
We went on to put two of our own properties in place – both of which supported
enumerations, making it easier for the end developer and ensuring code is easy-to-read.
Next week, we'll build on what we started today – and will find out just how those
enumerations can start to make our life a lot easier. We'll also add a host of new
properties, code a few methods plus add our own custom events – the easy way!
But until next week, this is your fantabulous host Karl Moore, saying goodnight for
tonight. Goodnight!
The Keypress event fires whenever the user types something in the Text Box. An
argument is passed with the event – KeyAscii.
Top Tips: KeyAscii is a number that represents a key on the keyboard. To convert
KeyAscii to its keyboard letter, use Chr(KeyAscii). To convert a letter to its KeyAscii
code, use Asc(Letter). Setting KeyAscii = 0 in the KeyPress event cancels the character.
• Add the following code to the txtTextBox_KeyPress event:
Private Sub txtTextBox_KeyPress(KeyAscii As Integer)
Case Letters
'If only accepting letters, check...
End Select
Case UpperCase
'If text needs to be in upper case,
'change the KeyAscii value to
'the Ascii code of an upper case
'version of the KeyAscii {phew!}
'DON'T FORGET - Asc() changes a
'letter to it's Ascii value, UCase()
'changes a letter to upper case,
'Chr() changes an Ascii character to
'a normal letter. So here, we're converting
'the Ascii to a normal letter, making it
'upper case then changing it back again!
KeyAscii = Asc(UCase(Chr(KeyAscii)))
End Select
End Sub
By observing the comments, you should be able to understand this code. Don't worry if it's
seems slightly alien – after all, it was written by me, Karl Moore, distant son of Phwasack
"Area 51" Carstolemew and third supreme commander of the planet Clot.
Just bare in mind that you don't need to know about 'KeyAscii codes' in order to create
most ActiveX controls. Except this one.
In our control, it's the above chunk of code that does all the work - checks the properties,
ensures characters are upper case or lower case, and beeps if a character is invalid.
Try testing our code. Add a new test 'Standard EXE' project and throw our control onto a
Form.
Don't set the properties at design time – set them in code behind a Command Button.
Then run your application, press the Command Button and attempt to type a few invalid
characters.
Does the control work?
<Karl sniggers as he sinfully realises this is a one-way medium>
Note: If you set the control properties at design time, they will disappear when you run
the application. That's because we haven't told Visual Basic to save that information. You
do this via Property Bags. Remember that – it'll make sense later.
And Another Note: Can you spot the bug? What happens when you choose the 'Letters'
option and tap the spacebar? What about the backspace? Can you fix this?
The Problem...
So you've created your own control with two easy-to-use properties. You've even put
those properties to use via a chunk of code in the KeyPress event of the text box.
Now it's time for a nerdy developer to test your control.
You stick him at your desk and 2.4 seconds later he feebly complains, "But how can I read
or write stuff inside the text box?"
"Damn", comes your reply. "You noticed"
If using a normal text box, you could retrieve the value by running the code...
MsgBox Text1.Text
... but unfortunately your control doesn't have a text property. However our actual Text
Box (txtTextBox) does.
'Cause you're a super-intelligent ActiveX boffin now, you could easily implement such
functionality by adding code similar to the following...
Public Property Get Text() As String
Text = txtTextBox.Text
End Property
So let's recall our original problem – what if our end user wanted to respond to events of
the Text Box? Say, the Click event?
Well, we could create our own custom events identical to those of the Text Box. Then,
when those Text Box events fire, we could raise our own events to the end user.
Let's see an example of how we'd do this with the Click event:
Public Event Click()
The current screen should ask you to select the 'interfaces' you want Visual Basic to
automatically 'code' for you.
Interfaces? Yeah, that's just a posh word to describe what stuff your control shows (or
'exposes') to the developer. And 'stuff' is a technical term defined as properties, methods
and events.
So - the list box to the left of your screen displays this list of suggested interface members,
such as the Font property and the Click event.
Note: These suggested interfaces have been determined by the existing properties,
methods and events of controls you currently have in your workspace. At the moment, we
just have a Text Box – so it's suggesting it should code all the 'stuff' related to a Text
Box, such as the Font property.
• Move a few of the interface members across to the second box:
• -- BackColor, BorderStyle, Click, DblClick, Font, FontBold, FontItalic,
FontUnderline, PasswordChar, Refresh, Text
• Click Next
If you wanted to add any extra properties, methods or events – the current screen would
be the place to do it. But we don't, so...
• Click Next
Now we're going to 'map' all the properties, methods and events we selected direct to our
Text Box. This lets the wizard know that our custom Click event, for example, should be
fired when the Click event of the Text Box is activated. And the custom BackColor
property should pass its value direct to the BackColor property of the Text Box. And so
on and so forth.
This is called 'mapping'.
• Select all the interface members in the list box (hold your left mouse button down
and drag along the list)
• From the 'Maps to Control' list, select your Text Box
• Click Next
Lot's of professional components have these 'property pages'. They allow you, as the
developer to have much more control over how you can display and allow users to select
properties.
Each item in this list will represent one 'tab' when you view the property page of your
control. For instance, this control has five different property pages – each represented by a
tab:
Huh, not very exciting. In fact, you're looking at the only computer screenshot so plain it
ships with its own aviation certificate.
Let's take a peek at some of the code behind this rather dull property page.
Underneath all the Change events of the Text Boxes and the Click events of the Check
Boxes, you should find this code:
Changed = True
This tells Visual Basic that at least one property on the page has changed. Of course, it
doesn't signify that the change should be saved - you mustn't forget that all property pages
With cboConvertCase
Now it's time for the wizard to step in. Follow the prompts through to the end. Note that:
• On the 'Cab Options' screen, select 'Multiple Cabs' if you're going to distribute via
floppy disk, or 'Single Cab' if you're going to dish out via CD-ROM or as a zipped
up download from the Internet
• On the 'Installation Title' screen, enter the title of your project such as 'Super Cool
Text Box'
• If you want to save your setup settings for a later session, enter a script name on
the 'Finished!' screen
Most of the time, you'll be fine just accepting the defaults. But be sure to read the
explanations and change anything you desire.
• When you've cycled through all the wizard screens, hit Finish
• After your machine stops buzzing, read the brief status report then click Close
That's it! You've just created a setup package for your control, ready to be distributed to
your end users!
Try checking out the folder in which the wizard placed your setup files. You did make a
note of it, right? It's probably called 'Package'.
Try copying these files across to a different computer, running the Setup program
(setup.exe) and trying out your control within Visual Basic, Excel or whatever. It should
work just the same as it does on your computer!
Well done! You've just created and tested a setup package for your control!
In fact, you'd better keep those test setup disks. They'd make an ideal Christmas present
for any self-respecting nerd.
Important Top Tip: Now that you've compiled your control, it isn't just restricted to use
within Visual Basic. You could utilise it within Excel, Word, Internet Explorer, Visual
C++ or any ActiveX-aware application!
Top Tips for your Control, Part One
End Property
This raises an error in the application attempting to set your control's Username property.
Groovy? I think so.
Top Tip: To find out more about raising errors within your control, look up the 'Raise
Method' (Visual Basic Reference) in the Visual Basic help files.
If something goes wrong in your own code that you can't handle, you could try 'passing
back' the error to the developer using your control. Once again, you could simply use
Err.Raise() – this time, in your error handler. You'd be raising an error that you received –
or rather, passing it back.
Resizing your Controls
In our sample Text Box control, we didn't have to worry about resizing too much. We
simply set the dimensions of our Text Box to the dimensions of the UserControl object.
However if we were dealing with more complex items – such as a File Open dialog box
that needed to perfectly resize all the controls within it – you'd need to get much more
technical. You'd be dividing heights by three, multiplying the square root of 18 by the
width of your control, then taking away the number you last thought of... and so on.
Trust me, resizing work can get pretty complicated. So you might want to think about
purchasing one of the many resize controls available that simply does it all for you – try
checking out our ReSize OCX review </controls/resizeocx/> for size.
Top Tips for your Control, Part Two
Getting it on the Net
If you have the urge, you can even get your control on the Internet. How?
Notice how the text box inside our control doesn't automatically resize itself?
• Right click on 'Project2' in the Project Explorer and click Remove Project, not
saving any changes
The text box doesn't automatically resize because as of yet, we haven't told it to. Oh, and
'cause Visual Basic is about as smart as the winner of last year's "World's Scruffiest Bloke"
competition.
• Click View, Code to enter the code window
• Select UserControl from the Object drop-down box
Don't forget that the UserControl is just your control. When something happens to it,
certain events fire – such as Initialize, Resize, LostFocus and so on. It's the equivalent of
the Form object in regular programming, where you have events such as Load and
Unload.
• Select Resize from the Procedure drop-down box
• Add the following code to your project:
Sure, it's about as stunning as Queen Elizabeth's bottom, but this is only the second
tutorial...
[Ed: So by the last instalment should we expect something akin to Pamela Anderson?]
Decisions, Decisions...
Now I want the person using this control to be able to decide whether the text box should
accept just letters, numbers or both – and whether letters entered should be converted to
upper or lower case.
So I've already determined two possible properties:
• AcceptType – should it hold just letters, numbers or both?
• ConvertCase – automatically convert to upper case, lower case or neither?
But how will the user tell me which they wish to use? I could perhaps tell them to set
AcceptType=1 if they wish to hold letters, 2 if they only require numbers and so on. Err,
but that ain't too user friendly. And you know how darn picky those users get.
This is where enumerations come into play. Yessiree, that's another geeky word designed
to scare off potential programmer types. But it's really very simple.
• Back in your project, open the code window
• Enter the General Declarations section
• Select (General) from the Object drop-down box and (Declarations) from the
Procedure drop-down box
• Type in the following code:
Public Enum CharacterType
All
Numbers
Letters
End Enum
End Property
End Property
Here we have a let and a get. The let piece of code runs when a user tries to set the value
of our AcceptType property. And the get piece runs when someone tries to retrieve the
value of AcceptType.
Apart from that rather important difference, this property lark isn't that dissimilar from
regular subs and functions. You can imagine that the let piece of code is a sub, that
accepts the new value of AcceptType in the passed vNewValue. And the get piece of code
works just like a function – to send information back to the user, you simply set
AcceptType to a specific value.
Following me?
[Reader: Yeah, in the same way the King of Egypt followed Moses...]
Let's take a peek at an example property let and get pair...
Dim strUserName as String
End Property
Here, we have a local variable called strUserName.
When the property is set...
MyControl.UserName = "John"
... the let procedure runs and sets the value of strUserName.
When the property is retrieved...
MsgBox MyControl.UserName
... the get procedure runs and returns the value of strUserName.
That's exactly how most property procedures work. But we're using enumerations to make
life easier for our end user... yet alas, slightly more difficult for ourselves.
• Change the skeletal property procedures Visual Basic created for us to something
like this:
Public Property Get AcceptType() As CharacterType
End Property
End Property
The only important thing we've done here is to change 'Variant' to 'CharacterType'. If the
user passes a variant, they could be sending anything our way. This way we're saying –