Defining a CustomControl

A CustomControl is simply an ordinary twinBASIC class, with a few extra attributes and requirements.

Tip

It is highly advisable to look at and experiment with the sample project provided with twinBASIC before trying to implement your own CustomControl.

The New / Open Project dialog on the Samples tab. A red ring and the number 1 mark the Samples tab; a red ring and the number 2 mark the title of Sample 6. CustomControls.The New / Open Project dialog on the Samples tab. A red ring and the number 1 mark the Samples tab; a red ring and the number 2 mark the title of Sample 6. CustomControls.

CustomControl() attribute

The CustomControl attribute of the class MyGrid in the editor, naming the image /Miscellaneous/MyGrid.png.The CustomControl attribute of the class MyGrid in the editor, naming the image /Miscellaneous/MyGrid.png.

This is a required attribute for all CustomControls. You must provide the relative path to an image file within your project that can be used to identify your control in the form designer toolbox. We recommend that you put the image file in the Miscellaneous folder in your project.

In the CustomControls sample, the controls are in the CustomControls package, so their images are in the package’s own Miscellaneous folder. WaynesGrid, for example, names /miscellaneous/frmGrid.png:

The Project Explorer of the CustomControls sample, with its Packages folder open on CustomControlsPackage and that package’s Miscellaneous folder open. A red arrow points at frmGrid.png, among the control images frmButton.png to frmTextbox.png.The Project Explorer of the CustomControls sample, with its Packages folder open on CustomControlsPackage and that package’s Miscellaneous folder open. A red arrow points at frmGrid.png, among the control images frmButton.png to frmTextbox.png.

ClassId() attribute

The ClassId attribute of the class MyGrid in the editor, with a GUID, under its CustomControl attribute.The ClassId attribute of the class MyGrid in the editor, with a GUID, under its CustomControl attribute.

This is a required attribute for all CustomControls. You must provide a unique CLSID (GUID) in order for the form engine to work with your control.

Tip

If you enter [ ClassId () ] twinBASIC helps you out - just press the ‘insert a randomly generated GUID’ text:

A ClassId attribute with empty parentheses in the editor, with a red wavy underline under ClassId and, above the line, the editor’s text: insert a randomly generated GUID.A ClassId attribute with empty parentheses in the editor, with a red wavy underline under ClassId and, above the line, the editor’s text: insert a randomly generated GUID.

COMCreatable() attribute

The three attributes of the class MyGrid in the editor, CustomControl, ClassId and COMCreatable(False), above the line Class MyGrid. A red arrow points at the COMCreatable attribute.The three attributes of the class MyGrid in the editor, CustomControl, ClassId and COMCreatable(False), above the line Class MyGrid. A red arrow points at the COMCreatable attribute.

This is an optional attribute, but it is usually advisable to set this attribute to False, as you don’t need to instantiate CustomControls from external COM environments.


Must implement ICustomControl

The editor’s hover over ICustomControl in the line Implements CustomControls.ICustomControl of the class MyGrid. It names the interface, in package CustomControls, and lists its members Initialize, Destroy and Paint.The editor’s hover over ICustomControl in the line Implements CustomControls.ICustomControl of the class MyGrid. It names the interface, in package CustomControls, and lists its members Initialize, Destroy and Paint.

All CustomControls must implement CustomControls.ICustomControl. This interface currently has 3 methods that you must implement:

Sub Initialize(ByVal Context As CustomControlContext)

This method is called when your control is attached to a form. You must store the provided Context object in a class field as it offers a Repaint() method for informing the form engine that something in your control has changed and needs to be repainted.

Sub Destroy()

This method is called when your control is detached from a form. This allows an opportunity to break circular references so that your object instance can be destructed properly. The implementation for this can often be left empty provided you don’t create circular references in objects.

Sub Paint(ByVal Canvas As Canvas)

This is the most interesting part for a CustomControl. As such, it gets its own section, see Painting / drawing to your control


Minimum set of properties

As twinBASIC doesn’t yet support inheritance, you must expose a set of common properties (class fields) for all CustomControls:

Public Name As String
Public Left As CustomControls.PixelCount
Public Top As CustomControls.PixelCount
Public Width As CustomControls.PixelCount
Public Height As CustomControls.PixelCount
Public Anchors As CustomControlsPackage.Anchors = New CustomControlsPackage.Anchors
Public Dock As CustomControls.DockMode
Public Visible As Boolean

The form designer and the form engine work with these properties, so it is important to include them in your CustomControl class. The types used here are all defined in the framework: PixelCount, DockMode, and the Anchors style object.

Note that the form designer works with pixel values which are not DPI-scaled. So the Left/Top/Width/Height properties of your control do not reflect DPI scaling. For example, if your control has a width of 50 pixels, then at DPI 150%, then the actual drawing width is 75 pixels ( see Painting / drawing to your control).


Must load its property values in Initialize

The property values set for your control in the form designer are loaded by your Initialize method. The Context object passed to it offers a GetSerializer() method, and the serializer that it returns offers a RuntimeUISrzDeserialize() method, which copies the saved values into your control’s properties:

Private Sub OnInitialize(ByVal Context As CustomControls.CustomControlContext) _
        Implements CustomControls.ICustomControl.Initialize
    If Not Context.GetSerializer.RuntimeUISrzDeserialize(Me, False) Then
        InitializeDefaultValues     ' nothing was saved yet; you implement this
    End If
    Set Me.ControlContext = Context
End Sub

See Property Sheet and Object Serialization for further information, and SerializeInfo for the serializer’s other members — the design-mode flag, the runtime / report mode, and the owner window handle.


See also