NS BASIC Controls
NS BASIC Controls implements set of controls and helper classes.
Together they enable the NSBasic developers to use a number of Windows Common
Controls in their projects. The library will grow in time including
more controls of this category. This documentation will be updated
accordingly.
When a new version is published you can just replace the
library's DLL in your application distributives. The backward
compatibility between the versions is preserved and only new
features and controls are added with each new version. Check for
more general information in the FAQ.
1. The library contents
Insertable (visual)
Controls |
Helper ActiveX objects. |
These
are the ActiveX controls you would want to put onto your
forms. Usually you should put them in the NSBasic IDE's
toolbox and then place them on the forms on which they will be
used. |
These
are creatable ActiveX objects which have no visual appearance
of their own at run time. They are used by the visual controls
in this library to maintain certain common data. Most often you
do not need to create them directly because the
visual controls create them automatically and enable you work
with them as if they are integral part of the control
itself (see faq). |
NSListView
ProgID: NSBasic.comctl.ListView
ClassID: {F7A4DFE2-C262-457E-B0C5-B4789D02988D}
Create example:
AddObject "NSBasic.comctl.ListView",
"NSListView1", 312, 0, 328, 456, Form1
Note: It is more convenient to put it into the
toolbox of the IDE first and then place it on the forms.
|
NSBImageList
ProgID: NSBasic.comctl.ImageList
ClassID: {E4FD27CF-BA94-452F-A486-82CFA4D09868}
Create example:
AddObject "NSBasic.comctl.ImageList",
"MyImageList1"
NSFont
ProgID: NSBasic.comctl.NSFont
ClassID: {07679CF2-323B-46A7-87CB-A8DC600BC4BE}
Create example:
AddObject "NSBasic.comctl.NSFont",
"MyFont1" |
How to add a control to the toolbox
manually: Make sure
that the Windows desktop version of control's DLL (NSBControls.dll)
is installed/registered on your desktop/notebook computer. Open the ActiveX
Control manager dialog box from the tool menu, browse for the DLL
and add it. Note that for the both NSBasic development environments
(Desktop and CE) the desktop version of the DLL is used at design
time. The
specific version for the device is needed only when the application
is deployed. This is so, because the IDE uses only the registration
information of the DLL and may need to query it for some information
while you are developing the application on the desktop.
2. NS BASIC Controls FAQ
Q: Why put many controls in single DLL instead of putting each control in separate DLL?
A: Most of the controls in this library are complex and thus require
common helper objects and facilities. Having them all in a single DLL
makes the integration of all those objects easier and minimizes the impact
over the performance. For example NSBImageList objects are used by
the NSListView control but they are also used by the NSTreeView control.
Having separate DLL for each control will require implementation of image
list in each of them and make it harder to share the same object
between different kind of controls. When in single DLL the objects have
the opportunity to create such objects directly and not through the
standard COM API routines thus avoiding the ned to dig into the registry each time an object
is created. Obviously in case of extensive usage of certain objects this
improves the performance drastically. The DLL may be a bit bigger than
usual but over a third of its size is occupied by code common to all the
controls. Therefore splitting the controls in separate DLL-s will cause
noticeable size overhead if more than one control is needed in any
particular project.
Q: How do the helper objects become integral
parts of the controls?
A: Let's illustrate this with the NSBImageList object. The
NSListView control needs 3 such objects - one for each: the big item
icons, small item icons and the column headings. When created NSListView
implicitly creates 3 empty image lists - one for each purpose and exposes
them through these properties:
- Icons - the big icons
- SmallIcons - the small icons and the icons in report view
(both for items and subitems)
- ColumnHeaderIcons - the icons for the column headings.
Thus when you need to load some images to display in the NSListView you do not need to create an NSBImageList
object. Instead you
address the already existing object through the property that exposes it
to you:
NSListView1.Icons.LoadBitmap "\myimages.bmp"
will load images into the big icons image list of the control. You
can also change the sizes the same way:
' Note that usually this is done before loading any
images,
' because when the size changes all the existing images are deleted.
NSListView1.Icons.Width = 48
NSListView1.Icons.Height = 48
So, effectively you can consider the image list integral part of the
control. In the NSListView there are 3 such integral parts and you can
manage them through the corresponding property.
Is it possible to replace such an object in the control? Yes! You can
create a NSBImageList separately or get it from another object on the
form and assign it to the control. Suppose we have two list views on the
same form:
Set NSListView2.SmallIcons = NSListView1.SmallIcons
will assign the small icons image list from the first list view
control to the second and both list views will share the same object.
This is especially helpful when you want to use the same set of images
in different controls.
Creating object such as NSBImageList explicitly is rarely needed. One
of the cases in which it would make sense is a scenario in which you are
adding control dynamically to the form. In such case you may want to
have the images already prepared before adding the new control(s).
However, this is extremely untypical.
Q: What are these Tag properties for?
Almost all the objects in the NS BASIC Controls library has
this property. The application can save in it whatever it wants
and then access it later. This means that you can assign to a Tag
property a simple value (such as string) or Set an object - it is
up to you. Further this Tag can be used to tag an element in a
control or help the application recognize the element in some
convenient way. The Tag can be used for many purposes, but we will
try to emphasize two of the most interesting ones:
Handling events: A good example is the NSListView
control. Its events carry single argument - a NSListViewEvent
object which has several properties that can be empty or filled
with something. That something is the control's element or elements
relevant to the event. Thus handling the vent you can access
an element relevant to it directly. For example:
Sub NSListView1_OnClick(e)
e.Item.Text = "I have been clicked!"
End Sub
This code changes the text of the clicked item to "I have
been clicked!". In this sample code there is no indexing -
the item that have been clicked is in the event object and
you can work with it directly regardless of its index in the control.
In the real world the items carry some meaning and very often the
application needs to establish a relation between the item and
other data. For example if the items represent the rows from the
result returned by a database query you may want to
"attach" each row to its item. Lets illustrate this with
an example. Assume you have SQLite COM or SQLite3 COM database
opened (the db variable holds the DB connection object):
Set res = db.Execute("SELECT * FROM
T")
For Each row In res
Set itm = NSListView1.ListItems.Add(,,row("FIRST_NAME"))
Set itm.Tag = row
Next
In this code we add one item for each row in the result of the
query. For brevity we only assign a text to each item (no icons or
other goodies). Then we also assign the row to the Tag property of
the item. Thus we have each row attached to its item. Visually the
item uses one of the fields from the result as a text label, but
internally we keep a reference to the entire row and we can access it through the
Tag property whenever we want. When we would want to do so? Again
when handling events, but also we may want to do the same when we
do something else - such as enumerating the items, searching for
items and then access the DB row for each found item and so on.
Most clear is the event handling case (lets use OnClick again):
Sub NSListView1_OnClick(e)
Dim s
s = ""
For I = 1 To e.Item.Tag.Count
s = s & e.Item.Tag.Key(I) &
"=" & e.Item.Tag(I) & vbCrLf
Next
MsgBox s
End Sub
We simply show a message box with all the fields in the row in
Name=Value format. Note that we know that the Tag contains a row
from the previously extracted data from the DB, thus we can use
over it the Count property to see how many fields are there and
the Key property to get the name for each field.
Obviously without the Tag property in the above example we will
need to make complex and sometimes risky calculations to identify
the row that corresponds to an item. Why risky? Imagine the
application decides to add items generated the same way for
another query, not removing the already existing items first. Then
we have two data sets and many items which may have been sorted
visually before we access them again. The index of an item will be
of no use after all the visual sorting - no index to row relation is preserved and
remember we have two datasets used, so which one corresponds to a
particular item... With the tags the data is attached to the item
and we have everything at hand.
Sorting and searching: This applies to some objects only
(such as Item and SubItem in the NSListView control). The
NSListView.FindItems method and the sorting functions of this
control support search/sort by text or Tag. Very often the
application would need to show the user one text and keep in the
background another data that is more convenient for processing.
The best examples are scenarios in which you want to show the user
values marked with measurement units. For example file size
rounded to KBytes or MBytes as appropriate for each individual
value, or another example weight - again some values will be
rounded to grams other to kilograms and so on. The texts shown to
the user are not numbers and cannot be sorted or searched as such
without complicated string parsing - specific for each individual
similar scenario. Sorting them as texts will be ridiculous 1g and
1kg will appear both smaller than 2g and 2kg which is not exactly
true. So, the simplest solution is to save convenient numeric or
text value in the Tag property of each item/subitem and then
search/sort over the contents of the Tag properties and not the
texts - which remain only visual labels for human
consumption.
What if we want to combine both - keep for example entire row
of data (as in the example above) and also use the Tag-s for
sorting/searching. Is it possible? Almost always - yes! When the
sorting and the searching functions use the Tag properties of the
elements in the control they do not require the Tag property to
contain plain string or a number. Instead you may have an object
there (an entire row of data for example) which have default
property that returns text or numeric value (as appropriate for
the sort or search you want to perform). In the case with the
SQLite COM/SQLite3 COM the results are packed using VarDictionary
objects from newObjects ActiveX Pack1. Thus each row is a
VarDictionary object which is actually a general purpose
collection/dictionary object and can be configured to behave the
way you want it. For the purposes of this example we want the
default property of such a row of data to return something
sensible. Lets modify the code from the above example a little:
Set res = db.Execute("SELECT * FROM
T")
For Each row In res
Set itm = NSListView1.ListItems.Add(,,row("FIRST_NAME"))
row.Root = row("LAST_NAME")
Set itm.Tag = row
Next
The VarDictionary's Root property specifies what default value
should be returned by the object when it is queried for its
default property without index (when index is used the indexed
element is returned). Thus by assigning the value of a specific
field to it we ensure that the sorts or the searches in the
NSListView controls will be done over the text in that field. Remember how we want to have one text shown to the user and
another actually used for sorting - we achieved that (frankly in a
bit weird way in this example) - the item shows the FIRST_NAME,
but any sorts using the Tag property will occur over the LAST_NAME.
Conclusion: The Tag properties are powerful way to create
relations between visible elements and data managed by the
application internally. They enable the developer to avoid complex
index calculations and can be used to tune the behavior of some
controls according to the actual meaning of the information and
not its human readable representation. While it is hard to
estimate it exactly in
a typical application Tag based implementation would require at
least 2-3
times less code than index based data to visual elements relation
implementation. And note that this means that by choosing
appropriate values for the Tag-s you are free to perform whatever
visual operations you want without losing the relation with the
internal data - this enables you to provide more user
friendly features without concern about the rest of the work the
application does.
3. Supported platforms and compatibility
The library is available as single DLL named: NSBControls.dll.
All the ActiveX controls in this library look the same way to the application on each platform. The actual functionality is virtually the same on both
desktop and Windows CE/CE.NET devices. There are only a couple of tiny cosmetic
differences that does not concern the controls' behavior (see the
notes in the page of the corresponding control).
|