Introduction
You may want to create a GUI application written in VBScript or JScript using Windows Common Controls. I'm sure you would not like to read tons of sources to find two lines of useful code. This article is only an ABC, a starting point.
First of all, VBScript or JScript GUI application are not real Win32 API. This kind of GUI is HTA or HTML for Internet Explorer browser. By using any of them, you can take advantage of easy using Windows features. Standard windows controls like buttons, edit boxes, comboboxes do not require anything special to use in HTA. But Windows Common Controls, like TreeView
, ListView
are available as ActiveX controls.
This may look a little like WEB design. But in fact this is a mixed style of programming.
If you need plain Win32 API, you would rather need some scriptable wrapper of WinAPI written in C/C++, or any other languages. But for many Windows applications, HTA and HTML for Internet Explorer are far enough. You can be surprised how many types of applications you may write in HTA or HTML for Internet Explorer.
Background
This code explains as briefly as possible the main ideas of using standard ActiveX controls as to what wraps Windows Common Controls. It can be used with client side scripting just in HTML pages, or as standalone HTA applications. It is ideal to use at the office, where policy could prohibit using some third party programming languages, browsers, compilers, components, non windows operation systems, or all of them. You don't need to install anything, and these applications will work. To use HTA applications, you will need to copy scripts to each computer on which you would like to use them, or put on a share folder on the local network. Or you could put applications on a WEB server, and users will use it via Internet Explorer browser.
This Code Can't be Used
This code is incompatible with non Microsoft Windows operation systems. This code is not compatible with non Microsoft Internet Explorer browsers. A big advantage is to have some basic knowledge of ActiveX. But it is not required. You can use this without knowing ActiveX.
Some Technical Background
I don't intend to write a full guide to ActiveX controls. All the member functions, properties, events and passed arguments, you can find with tools like Office VBA, OleView. In Office VBA, you need to add a reference to some version of Microsoft Windows Common Controls by finding and checking it in the list of references, or add by browsing for mscomctl.ocx. After that, you will see all the information in the Object Browser. If you use OleView for that, I'm quite sure that you know how to find these objects.
Now, some information for people who are not familiar with ActiveX. The ActiveX objects are identified by ClassID
(clsid
). This is a GUID which looks like a big thing with 32 hex numbers that makes no sense for a human. A more human readable identificator is ProgID
. If you would like to use some other versions, or if windows has other versions of controls, you may need to use other clsid
s than the ones from my samples. In this case, you need to find the clsid
in the type library. If you don't have OleView, you can't find them in Windows registry. For instance, I use the TreeView
control. The ProgID
of TreeView
control is MSComctlLib.TreeCtrl
. You have to find this ProgID
in the registry inside HKEY_CLASSES_ROOT
:
HKEY_CLASSES_ROOT\MSComctlLib.TreeCtrl
or some other version:
HKEY_CLASSES_ROOT\MSComctlLib.TreeCtrl.2
Here you find the default value of subkey CLSID
. It is exactly the CLSID
you need. On my computer, it is {C74190B6-8589-11D1-B16A-00C0F0283628}. Just remove the brackets and copy/paste in your code.
Let's Use a TreeView
See the archive TreeView.zip.
To use the TreeView
, you need to insert the TreeView
ActiveX object:
<object id="ITreeView" classid="clsid:C74190B6-8589-11D1-B16A-00C0F0283628"
height="200" width="200" >
......
</object>
To manipulate the object, you will need to obtain the object.
In VBScript, you do like this:
set treeObj = document.getElementById("ITreeView").object
Quite the same thing is done in JScript:
treeObj = document.getElementById('ITreeView').object;
From ActiveX point of view, this code obtains the IDispatch
of the ActiveX object.
Let's add nodes/items to the treeview
in VBS:
set x = treeObj.Nodes.Add(null, TreeRelationship.tvwFirst, "key 1", "The VBS Item 1")
set x1 = treeObj.Nodes.Add(x, TreeRelationship.tvwChild, "key 1.1", "The VBS Item 1.1")
...
Same thing in JS:
x = treeObj.Nodes.Add(null, TreeRelationship.tvwFirst, "key 1", "The JS Item 1");
x1 = treeObj.Nodes.Add(x, TreeRelationship.tvwChild, "key 1.1", "The JS Item 1.1");
The function add(...)
returns the added node. The first parameter should be a related tree node, for example the parent node. The second parameter indicates how the nodes have to be added. The third parameter is a key which must be unique.
Using ImageList VBScript and JScript with TreeView
See archive TreeViewAndImages.zip.
To use images/icons for tree nodes, you need an image list:
treeObj.ImageList = imgList
Now, adding a node with image is just a snap:
set x = treeObj.Nodes.Add(null, TreeRelationship.tvwFirst,
"key 1", "VBS Tree Item 1", "PictureNumber0")
A small difference is one more parameter. The last one. This parameter indicates the ID of picture in the imgList
.
Same thing in JScript:
x = treeObj.Nodes.Add(null, TreeRelationship.tvwFirst,
"key 1", "salut 1", "PictureNumber0");
The imgList
is another ActiveX object. It can be instantiated like this:
VBS:
set imgList = CreateObject("MSComctlLib.ImageListCtrl.2")
JScript:
var imgList = new ActiveXObject("MSComctlLib.ImageListCtrl.2");
Loading images is done in VBScript like this:
imgList.ListImages.Clear()
imgList.ListImages.add 1, "PictureNumber0", LoadPicture("Icon\Number0.ico")
imgList.ListImages.add 2, "PictureNumber1", LoadPicture("Icon\Number1.ico")
Function LoadPicture
returns a IPictureDisp
. This function is available in standard WSH VBScript, but is not available in WSH JScript. To use it in JScript, we can write a short and very simple VBScript wrapper, see VBScriptWrapper.wsc in TreeViewAndImages.zip.
First of all, register this wrapper with regsvr32
in the command line:
regsvr32 VBScriptWrapper.wsc
Now we can use function LoadPicture
in the JScript program:
var vbsw = new ActiveXObject("IFVBScript.Wrapper");
Now load pictures:
imgList.ListImages.Clear();
imgList.ListImages.add(1, "PictureNumber0", vbsw.LoadPicture("Icon\\Number0.ico"));
imgList.ListImages.add(2, "PictureNumber1", vbsw.LoadPicture("Icon\\Number1.ico"));
Another way to use this wrapper is to declare it as an HTML <object>
:
<object id="VBScriptFunctionsWrapper"
classid="clsid:02F3817F-4555-4e51-A741-D87662FA7987" > </object>
Accessing it in JScript and loading images:
var vbobj = document.getElementById('VBScriptFunctionsWrapper').object;
imgList.ListImages.Clear();
imgList.ListImages.add(1, "PictureNumber0", vbobj.LoadPicture("Icon\\Number0.ico"));
imgList.ListImages.add(2, "PictureNumber1", vbobj.LoadPicture("Icon\\Number1.ico"));
If you know a better way to LoadPicture
in JScript, please tell me.
Events
In response to user input, you may need to process events. Let's process the click on an item, and the mouse move over the tree. See TreeViewWithEvents.zip.
In VB, you will do the standard way of processing event SomeEvent
of an object with ID SomeObject
. You just have to add a procedure named SomeObject_SomeEvent
, and voila:
sub MyTreeView_MouseMove(Button, Shift, x, y)
end sub
sub MyTreeView_NodeClick(node)
end sub
In JavaScript, this is quite standard as well. You addition should look like this SomeObject::SomeEvent
.
function MyTreeView::MouseMove(Button, Shift, x, y)
{
}
function MyTreeView::NodeClick(node)
{
}
To find what item is under a coordinate x,y
is used the function HitTest
. But function HitTest
does not accept pixel coordinates like the ones you get in MouseMove
event. Before you pass coordinates to HitTest
, it is required to transform them from pixels to twips. On my computer, I use 14.4 to transform.
VB:
set node = treeObj.HitTest(x * 14.4, y * 14.4)
JScript:
node = treeObj.HitTest(x * 14.4, y * 14.4);
Points of Interest
This article is not finished, and will be continued.