If you're enhancing an existing control, that single constituent control will typically occupy the entire visible surface of your UserControl object. You can accomplish this by using the Move method of the constituent control in the Resize event of the UserControl, as shown below.
Private Sub UserControl_Resize()
picBase.Move 0, 0, ScaleWidth, ScaleHeight
End Property
The code above assumes that an enhanced picture control is being authored. A PictureBox control has been placed on the UserControl, and named picBase.
If the control you're enhancing has a minimum size, or a dimension that increases in large increments — such as the height of a ListBox control, which changes by the height of a line of text — you will have to add code to determine whether the Move method has produced the desired result.
You can rely on the control you're enhancing to handle painting, including (where appropriate) default button highlighting.
Tip You may also have to add code to resize your UserControl object, to accommodate a constituent control that can't be sized arbitrarily — such as a text box or list box. To avoid exhausting stack space with recursive calls to the Resize event, use static variables to determine when the UserControl_Resize event procedure is making recursive calls.
If you're authoring a control assembly, the Resize event will be more complex, because you have to adjust both size and relative location of multiple constituent controls.
If you author a control with a large number of constituent controls, there may be a minimum size below which resizing the constituent controls is futile, because too little of each control is visible to be of any use, or because the enforced minimum sizes of some constituent controls has been reached.
There is no real harm in allowing the user to reduce the size of your control to absurdity. Most controls allow this, because preventing it is a lot of work, and because at some point you have to rely on your user's desire to produce an application that works and is usable.
In the event that resizing below some threshold causes your control to malfunction, you might make all of your constituent controls invisible, as an alternative to enforcing a minimum size.
The following code fragment provides a simple example of enforcing a minimum size.
Private Sub UserControl_Resize()
Dim sngMinH As Single
Dim sngMinW As Single
' Code to resize constituent controls. It is
' assumed that each of these will have some minimum
' size, which will go into the calculation of the
' UserControl's minimum size.
sngMinW = <<Width calculation>>
sngMinH = <<Height calculation>>
If Width < sngMinW Then Width = sngMinW
If Height < sngMinH Then Height = sngMinH
End Sub
Notice the <<pseudo-code placeholders>> for the calculation of your control's minimum width and height. These calculations will be in the ScaleMode units of your UserControl. They may be very complicated, involving the widths and heights of several of the constituent controls.
The Width and Height properties of the UserControl are then set, if necessary.
Important The Width and Height properties of the UserControl include the thickness of the border, if any. If BorderStyle = 1 (Fixed Single), the area available for constituent controls will be reduced by two pixels (not Twips) in both width and height. If you have exposed the BorderStyle property for your user to set, include code to test the current value.
As an alternative, you could use the Size method:
If Width > sngMinW Then sngMinW = Width
If Height > sngMinH Then sngMinH = Height
If (sngMinW <> Width) Or (sngMinH <> Height) Then
' (Optionally, set recursion flag.)
Size sngMinW, sngMinH
' (Clear recursion flag, if set.)
End If
This code is more slightly more complicated, but it simplifies things if you need to avoid recursion when resizing your control, as discussed below.
Important The Width and Height properties of the UserControl are always expressed in Twips, regardless of the ScaleMode setting. If you have set ScaleMode to something other than Twips, use the ScaleX and ScaleY methods to convert your minimum size calculations to Twips.
No code for recursion is included in the example above, and recursion is virtually guaranteed. For example, if you attempt to resize the control so that both width and height are below the minimum values, the Resize event will reset the Width property, which will cause a second Resize to be raised immediately.
This second Resize event will test and reset the height, and then return — so that by the time the first Resize event tests the height, it will already have been reset to the minimum. Clearly, this can lead to confusing debugging situations.
Even if you use the Size method, a second Resize event will occur, repeating all your calculations. This can be avoided by setting a flag when you deliberately resize the control. The Resize event should check this flag, and skip all processing when it is True.
A recursion flag is not necessary for simple minimum size situations, but is virtually required for more complicated scenarios.
For example, if you use the code above in a control whose Align property is True, so that it aligns to the form it's placed on, as described in "Making Your Control Align to the Edges of Forms," infinite recursion errors are guaranteed, until stack space is exhausted and an error occurs.
Important Always use error handling in Resize event procedures. Errors here cannot be handled by the container, and your control component will therefore fail, causing the application using your control to fail, as well.
For More Information The models for creating controls are discussed in "Three Ways to Build ActiveX Controls" earlier in this chapter.