An introduction to Visual Cadd API programming with PB/DLL
By Bob Benson

Would you like to customize Visual Cadd and start exploring the Visual 
Cadd API in the easiest possible way?  Have you looked at BASIC programming in the past, but are totally confused with all the Visual-this and Visual-that hype?  Do you think that there must be an easier way?

What is PB/DLL?

PowerBASIC was first introduced as TurboBasic by Borland in 1986.  In 1989, Robert Zale, author of the language and president of PowerBASIC, Inc., renamed the compiler and set about pushing the Basic standard to new heights.  In 1993, PC Magazine recognized PowerBASIC as the most advanced Basic available.  In 1996, PowerBASIC introduced PB/DLL Compiler for Windows.

The art of writing a Windows DLL has been shrouded in mystery.  It was thought to be one of those things that only a few chosen ones, who know how to program in languages like C++, Delphi, etc. could do.  PB/DLL is a compiler which allows BASIC programmers to write industry standard DLLs and EXEs in a familiar language.  DLLs created with PB/DLL can be used by programs written in any other language which supports 32-bit Windows DLLs, such as Visual Cadd.  PB/DLL is similar to Visual Basic, but compiled PB/DLL code is typically 3 to 23 times faster than Visual Basic code, and EXEcutables are typically 4 to 40 times smaller!  This means that with PB/DLL, you get native machine code and small DLLs which do not require any additional external or runtime modules.  PB/DLL also gives BASIC programmers the following features:

*  Fast and small 32-bit DLLs and EXEs for Windows 95/98 and NT

*  32-bit protected mode code generation for maximum performance

*  True 32-bit code pointers, great for callbacks

*  Multi-thread application support

*  Register variables

*  Direct import and export of string functions and parameters

*  Unsigned integer types: BYTE, WORD, DWORD

*  80-bit extended precision math
 
*  64-bit QUAD-WORD integers

*  Two currency variable types

*  Native ASCIIZ (null-terminated) strings

* User-Defined TYPEs and UNIONs

*  Data pointer variables

*  Use of all available memory for arrays and dynamic strings

*  ARRAY sort, scan, insert, delete

*  BIT shift, rotate, test, set, reset, toggle

*  Optional parameters in BASIC Subs and Functions

*  Optional parameter passing to CDECL procedures

*  Optional requirement that arrays and variables be declared before use

*  Matrix operations

* Built-in 32-bit Inline Assembler with 80486 and Pentium opcodes

*  Inline Assembler includes Floating Point and MMX instructions

*  A complete set of string manipulation functions

*  MIN and MAX functions that work with both numeric and string data

*  PEEK, POKE, PEEK$, POKE$ for direct memory access

*  Complete access to the entire Win32 API

New features in PB/DLL 6.0 include advanced string handling,  high-speed serial communications, Client/Server Network communications using TCP and UDP, and Dynamic Dialog Tools.  With only a few lines of BASIC code you can create a complete Graphical User Interface in minutes.  No more struggling with drag-and-drop form designers.  No more slow forms.  And no more expensive ActiveX controls to access the controls built into Windows 95/98 and NT 4.0.  For more info: www.powerbasic.com.

What is a DLL?

A Dynamic Link Library (DLL) is a Windows executable library module containing one or more procedures which can be called by executables (EXEs) or other DLLs.  Unlike executables, DLLs don't have a single entry point.  Instead, like libraries, DLLs have multiple entry points, one for each procedure made available to other EXEs or DLLs.

What are the advantages of using a DLL?

DLLs are the fastest, most compact, and most efficient form of a Windows library file.  The Microsoft Windows operating system itself is based almost entirely on DLLs!  The first two words of "Dynamic Link Library" describe another very powerful aspect of DLLs.  Your program "links" to them, dynamically, at runtime, not at compile time.  While it is running, your application sees a DLL as if it was part of your program, even though it is a separate file.  That means that if you have a DLL that contains some multi-purpose functions, many different programs can use one copy of the DLL file.  This can result in significantly smaller programs.  DLLs are memory-efficient.  If two or more different programs are using a certain DLL, only one copy of the DLL is actually stored in memory.  Each program will have its own set of variables, but the DLL itself will only be loaded once.

Within the Visual Cadd environment, DLLs offer some additional specific advantages as well.  A DLL shares the same memory space as Visual Cadd, and once loaded into memory, a DLL will remain in memory until Visual Cadd closes.  Code can be run when your DLL is first loaded and different code can be run each time a function is called.  A number of procedures can be in one DLL without the command line options necessary for EXEs to achieve the same functionality.  No checking is required to see if Visual Cadd is running since it is the calling application.  No Windows interface and associated programming is required as long as we are developing simple add-on tools that will be used within the Visual Cadd environment.

What is the Visual Cadd API?

From the beginning, Visual Cadd was designed with the ability to be customized to suit the individual needs of a wide user base.  Many Generic Cadd users, such as myself, have come to depend on custom menus and custom macros to tailor our cadd package to meet our own individual needs.  As we look to Visual Cadd, we welcome the support for our Generic Cadd drawings, components, etc. and appreciate the 2-letter shortcuts and custom menu capabilities.  The biggest shortcoming is with the scripting commands and the small amount of documentation for them.  Visual Cadd advertises an open API that lets advanced users create specialized utilities or stand-alone applications based on the Visual Cadd graphics engine.

Computer programs use pre-defined procedures to perform specific tasks.  In Generic Cadd, these procedures were the two letter commands.  The program would find the two letter command in a table of available commands and then execute the procedure for that command.  These procedures were hard coded into the program and could not be used by any other program.  On the other hand, a program or application can make it's procedures available to any other program by using an open architecture Application Programming Interface (API).  This is a basic concept of Windows, which is also an API with many procedures available to any program or application.  The Visual Cadd API provides many functions for users to utilize in their applications.  General categories include:

		*  Entity creation procedures
		*  Entity editing procedures
		*  Environment settings procedures
		*  User data procedures
		*  Parsing procedures
		*  Calculation procedures
		*  Drawing tool procedures
		*  Dialog procedures
		*  Query procedures
		*  3D procedures

The Visual Cadd API can be a little overwhelming at first look.  When printed out, it can easily fill several large notebooks.  A large number of the procedures are for environment settings.  Once a few basic formats are understood, finding the proper procedure becomes more of a problem then figuring out how to use it.

One Generic Cadd command that we use often is DF (Fill Display).  Each time the DF procedure is called, the ON/OFF status is toggled.  In a macro, a toggle procedure could be turned on with (DF,++), turned off with (DF,--) and the current setting could be returned with (DF,??).   The equivalent procedures in the Visual Cadd API are VCGetFillDisplay and VCSetFill Display.  All the Visual Cadd procedure names start with the letters `VC' and are somewhat self explanatory.  These procedures are located in several DLLs located in the \Programs subdirectory.

Does this imply that all we have to do is create our own DLL to make the appropriate calls to the desired Visual Cadd API procedures?  YES!



A Simple Example:

Before we can call the Visual Cadd procedures, we have to DECLARE them in our program.  A procedure can be defined as either a FUNCTION (returns a value) or a SUB (does not return a value).  PB/DLL defaults to SDECL or STDCALL which specifies that the declared procedure uses the "Standard Calling Convention" where parameters are passed on the stack right to left.  BDECL (Basic/Pascal Calling Convention) and CDECL (C Calling Convention) options are available for other applications if required.  Visual Cadd uses STDCALL so this is not an issue here.  The DECLARE  statement also defines the name that we want to use for the procedure, the location of the procedure, the name(case sensitive) of the procedure as originally defined, the variable types to be passed (in order) and the variable type passed if the procedure is called as a FUNCTION.  Most of the toggles in Visual Cadd are similar to this format.  Note the simple trick of getting the current setting (1 or 0) and then subtracting it from 1 to determine the toggle setting.

1 - 0 = 1
1 - 1 = 0    No rocket science here.....  

As a DLL can only contain procedures, we need to program our own SUBs to call the appropriate Visual Cadd procedures.  Subs are private by default.  The EXPORT keyword is used to make a sub accessible from another program or DLL.  Here as well, the ALIAS is case sensitive and defines the name we will use to call our procedure from Visual Cadd.

To define our custom command for Visual Cadd, we need to add the following line to the cmdext.def file:

GcDF,DF,,,,DllName;Sample01.dll;DllFunName;ToggleFill;DllRun; 

If you want the drawing to redraw after the fill is toggled, add  Regen; to the end of the line.  If you will be using the new command while another operation is being performed, replace DllRun with DllRunNested.
  
As you can see from the following example, we don't have to get deeply involved in Windows programming or Object Orientated Programming to make use of the features available within the Visual Cadd API.  This sample shows the ENTIRE listing of source code required to produce the Sample01.DLL with PB/DLL.  There are no projects, forms, runtime modules, header files, etc. required.  




'============================================================
'  SAMPLE01.BAS by Bob Benson
'  using PowerBASIC DLL Compiler
'  Source code for SAMPLE01.DLL 
'============================================================
DECLARE FUNCTION VCGetFillDisplay LIB "VCMAIN32.DLL" _
          ALIAS "VCGetFillDisplay" (iError AS INTEGER) _
          AS INTEGER

DECLARE SUB VCSetFillDisplay LIB "VCMAIN32.DLL" _
     ALIAS "VCSetFillDisplay" (iError AS INTEGER, _
                             BYVAL tf AS INTEGER)

'------------------------------------------------------------
SUB MyHideFill ALIAS "HideFill" () EXPORT
'------------------------------------------------------------
CALL VCSetFillDisplay(iError%, 0)
END SUB

'------------------------------------------------------------
SUB MyShowFill ALIAS "ShowFill" () EXPORT
'------------------------------------------------------------
CALL VCSetFillDisplay(iError%, 1)
END SUB

'------------------------------------------------------------
SUB MyToggleFill ALIAS "ToggleFill" () EXPORT
'------------------------------------------------------------
CALL VCSetFillDisplay(iError%, 1 - VCGetFillDisplay(iError%))
END SUB
'------------------------------------------------------------             


The ALIAS for the Visual Cadd procedures are required due to the fact that 32 bit windows is case sensitive.  If the ALIAS was not used, this version of the compiler would convert to all upper case, as was normally done prior to 32 bit windows, and the Visual Cadd procedure would not be found.

The DLL for this example is 4608 bytes on disk with a memory image of 1708 bytes.  This same example, if done with Visual Basic, would require over 1,400,000 bytes with all the necessary runtime DLLs.

I hope this helps eliminate some of the mystery involved with creating a true native windows DLL, and offers an insight into some of the ease of using PB/DLL.  Once we find the right tool for the task at hand, the rest is relatively easy!

Bob Benson


