Writing New Tool Functions

The GUI Designer toolkit provides a very convenient method of including re-usable grid functions in your code.  Once you are comfortable using GUI Designer to write your own grid functions, it is fairly easy to learn to create new tools that can be added to the toolkit and used just like the built-in tools.  This page describes one approach to writing and using tool grid functions. 



Creating an accessory toolset involves the following steps:
  1. Create a GUI Designer program (the toolset) to contain the tools.
  2. Write a grid function for each tool to be included in the toolset.
  3. Compile the toolset source code to create the toolset DLL.
  4. Create a toolset text file listing the tools in the toolset.
  5. Add the name of the toolset text file to the master toolkit file.
The example below illustrates this procedure, by developing a simple scrollable grid for displaying BMP-format images.  The complete source code for this example can be viewed here.

1. Create the toolset source program.

The source program for a toolset is a GUI Designer program, created in the usual way - select 'new' from the XBasic PDE file menu, then click the 'gui program' button.  The PROLOG can be edited immediately, paying attention to the following:
For testing purposes, it is convenient to create a test window, using the GUI Designer toolkit, containing an XuiLabel grid as a placeholder for the new tool.  Use the Appearance Window's 'Image' option to select a large BMP-format image to be displayed in the grid.  If the program is run at this point, the image should be displayed in the label grid, but of course without scroll bars.

2. Write the grid function for the tool.

The appearance of the tool is laid out in the usual way, using the PDE's toolkit to create the desired grid.  In this example, create a window called ScrollImage, and place into it XuiLabel, XuiScrollBarV, and XuiScrollBarH grids, which will be the kids of the new grid.  Size and position the grids as desired, name them (eg., ImageGrid, ScrollV, ScrollH), and select styles, borders, etc., using the Appearance window.  Then use Window, ToFunction to create the grid function ScrollImage(), and the callback function ScrollImageCode().

Callbacks ultimately need to be handled by the tool's grid function; it is easiest to do this from the start, so delete the callback (aka 'code') function - you won't be using it.

Now is a good time to take care of a few details elsewhere in the program, before proceeding to flesh out the grid function:
Now that there is a basic grid function for the tool, go to the grid function for the test window, SUB Create, and change the line

    XuiLabel (@g, #Create, ....


    ScrollImage (@g, #Create, ....

Run the program, and the test window should display the label with scroll bars.  But there is no image, and the scroll bars do nothing, because the grid function contains no code to process the relevant messages.  Several changes need to be made in SUB Initialize, in the tool's grid function, so that the function will handle messages appropriately.
The tool will probably need to respond to one or more messages in order to operate properly.  In the example, to display the image, the grid function will need a "SUB SetImage" to process the #SetImage message; and also a "SUB Scroll" to process #Change, #OneMore, #OneLess, #MuchMore, and #MuchLess messages.  The addresses of these SUBs should be added to the list in SUB Initialize:

    sub[#SetImage] = SUBADDRESS(SetImage)
    sub[#Change] = SUBADDRESS(Scroll)
    sub[#OneLess] = SUBADDRESS(Scroll)
    sub[#OneMore] = SUBADDRESS(Scroll)
    sub[#MuchLess] = SUBADDRESS(Scroll)
    sub[#MuchMore] = SUBADDRESS(Scroll)

(To be complete, the example should also repond to #SetImageCoords, #GetImage, and #GetImageCoords, and probably #MouseWheel; these are ignored here to keep things simple.)

Now write the SUBs that actually operate the tool.  The SUBs will differ depending on the tool's function - see the source code for the SUBs required by the ScrollImage example.  There are no particular difficulties in writing these SUBs, assuming you are familiar with ordinary GUI Designer programs, but there is one point to keep in mind.  In any program that uses the tool, there may be several instances of the tool active at once, all using the same grid function.  The function must be written so that the different instances do not interfere with each other.  Mainly, this means that STATIC and SHARED variables should be used only for quantities that apply to all active instances - quantities specific to each instance should be kept in a value array, from which they can be retrieved as needed.  #SetValue, #GetValue, and related messages are useful here.  Since each instance of the tool will have its own value array, there is no interference between instances.  In the ScrollImage example, the image grid number, and the width and height of the image, are kept in a value array for this reason.

3. Compile the toolset source.

The toolset is compiled as an ordinary DLL, selecting 'library' from the PDE's 'run' menu.  See Making a Standalone Executable for more information.  You can remove the code associated with the test window once the tool has been tested, but there is no harm in leaving it in.  Because of a bug in the PDE, you may see a compile-time error like "0x00000000 undefined".  Just convert the file to text mode (select 'mode' from the file menu), then convert back to program mode and try compiling again.

4. Create the toolset text file.

The toolset text file can be created with any text editor.  The fields in each entry in the file are

   dllname   gridType   gridFunc   imageFile   category

Each entry must start with one or more tabs, and fields must be tab-separated.  Consult the standard toolset text file, xtool0.xxx (in the XBasic\templates folder) for examples of the proper format.

   dllname is the name of the toolset dll, without the .dll extension.  This DLL must be somewhere in the Windows search path, such as the \Windows folder or the XBasic\bin folder.

   gridType is the name under which the tool function's grid type was registered (this happens in the grid function, SUB Initialize, in the call to XuiRegisterGridType()).  The gridType is always the same as the gridFunc.

   gridFunc is the name of the grid function that defines the tool.

   imageFile is the name of a 32x32-pixel BMP-format file. It must be in the XBasic\images folder, and can be 16, 256, or 24-bit color.  A suitable image for the ScrollImage tool can be downloaded here - save it in your XBasic\images folder.

   category is a general category name for the tool (Button, List, etc.).  This field is never used, so any category name is acceptable.


tooldemo ScrollImage ScrollImage scrollimage.bmp Image

Once all tools are listed in the toolset text file, save it in the XBasic\templates folder.

5. Add the toolset text file name to the master toolkit file.

This file is called xtoolkit.xxx, and is located in the XBasic\templates folder.  It consists simply of a list of names of toolset text files.  Do not include a path for any of the listed files.  Any file name can be commented out, using the usual XBasic comment character (').  In fact, any file name in xtoolkit.xxx that does not begin with a letter of the alphabet will be ignored.

Using the new tool.

If everything has been done properly, it should now be possible to start up the PDE, create a GUI program shell, click the toolkit button, and find a new button corresponding to the ScrollImage tool.  The tool can be used like any of the built-in tools, keeping in mind a couple of points: