ActiveX Control Tutorial - Part 2
Bonjour and welcome to the second part in this jabber-wockingly 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
- Some other stuff
If you missed part one, it's probably a good idea to check it out before reading on - click here!
I can see you're getting all giddy now, so let's don our anoraks and thick glasses as we hop on the pink boat destined for the fluffy world of ActiveX controls...
Today, we're going to start creating an advanced text box.
In just a few clicks of the mouse, we'll allow users of our control to dictate how the text box works. Perhaps it will restrict people to entering just numbers or mere text. This will be done by setting properties.
We'll also make the text box automatically translate characters to upper case, lower case — or any ol' case.
So let's get going...
- Start up Visual Basic
- Create a new 'ActiveX Control' project
- Add a text box to your workspace
For the moment, don't worry about sizing or positioning or whatever. These things do matter — just ask my girlfriend but we'll deal with them later.
- Rename the text box to 'txtTextBox'
- Remove 'Text1' from the Text property
We haven't really done much yet, but let's test it so far.
- Click File, Add Project
- Select 'Standard EXE'
- Add your 'UserControl1' control from the toolbox direct onto Form1
Your screen should look a little something like this:
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 .Left = UserControl.ScaleLeft .Width = UserControl.ScaleWidth End WithEnd Sub
Here, we're resizing the dimensions of the text box depending on various properties of the UserControl object.
The UserControl object is there to tell you how your user is playing with the control. So if they resize it, the Resize event fires and you grab the new ScaleHeight, etc. properties, reorganising your controls as such.
In our project, we simply set the text box properties equal to the exact UserControl Scale properties. Of course, if you had more than just one simple text box to resize, you'd have to start with a few Einstein-like calculations. For now, I'll spare you the pleasure.
Go ahead and test the control— just as we did earlier.
See what happens? Whenever the user resizes your control, the text box follows!
My test project looks like this:
Sure, it's about as stunning as Queen Elizabeth's bottom, but this is only the second tutorial...
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
Let me explain what's happening here; the first line simply tells Visual Basic we're creating an enumeration christened CharacterType. The Public bit just ensures our end users can see the enumeration.
The next three lines list our options — no spaces allowed. The user can select All, Numbers or Letters.
Top Tip: You can also assign numbers to each of our options, so All might equal zero, Numbers might equal one and so on. Lookup the 'Enum Statement' in Visual Basic help for more information!
That final line of code simply states that the enumeration ends here.
So we've just defined the 'options' for our planned 'AcceptType' property. Now let's add another enumeration for the 'CaseConvert' property.
- Type in the following code:
Public Enum CaseType All UpperCase LowerCaseEnd Enum
Hmm, I guess you're not impressed in fact, I saw more impression the last time I drop a 1st class stamp onto a freshly produced ingot of 22 carat gold. But you will be, as soon as we get these things working.
Still, that's it for enumerations. Let's add a few properties!
You've played around with properties before. Every time you say...
Text1.Text = "Hello World!"
... you're setting a property. And every time you say...
... you're reading a property.
Because you're now a supercool ActiveX programmer, you're going to have to provide all this functionality to your end user too.
Now creating properties can get a little bit difficult so let me try to explain. When you set a property in code, it runs one bit of code. When you retrieve a property in code, it runs another piece of code.
So even though you may be setting and retrieving the same property, behind the scenes two different pieces of code actually fire up. And as you're now working behind the scenes, you need to know about them.
- Open the code window
- Click Tools, Add Procedure
- In the Name box, type 'AcceptType'
- Click the Property option button
- Hit OK
You should notice the following added to your code window:
Public Property Get AcceptType() As VariantEnd PropertyPublic Property Let AcceptType(ByVal vNewValue As Variant)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.
[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 StringPublic Property Get UserName() As VariantUserName = strUserNameEnd PropertyPublic Property Let UserName(ByVal NewUserName As Variant)strUserName = NewUserNameEnd 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...
... 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 CharacterTypeEnd PropertyPublic Property Let AcceptType(ByVal CharType 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!
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_CharTypeEnd Property
Public Property Let AcceptType(ByVal CharType As CharacterType)m_CharType = CharTypeEnd 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 IntegerPublic Property Get ConvertCase() As CaseType ConvertCase = m_CaseTypeEnd PropertyPublic Property Let ConvertCase(ByVal CsType As CaseType) m_CaseType = CsTypeEnd Property
Are you getting acquainted with properties yet? Hah, you see they're not that frightening in fact I was more petrified the last time I watched that epic of epic's, Hoger and Rammerstein's the Sound of Music.
[Ed: So were we it was your 538th visit!]
Now let's test your control!
- Click File, Add Project
- Select 'Standard EXE'
- From the toolbox, add your control to the form
Click on the control and take a peek at the properties window. Do you see the 'AcceptType' and 'ConvertCase' properties?
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...
... 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?
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 we 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!