You can create scripts using any text editor or word processor, then run the script directly from TurboCAD using the Menu:Tools|Run Scripts command. A built-in Enable Basic debugger is also provided (Menu:Options|Scripts and select Debug).
Scripts can be attached to a specific drawing through the Menu: Options|Scripts property sheet. You can also modify the TCW40.ini file to have your scripts made available on the Scripts toolbar for all your drawings.
This manual is aimed at those familiar with Basic or other programming languages. It is not a tutorial.
'Hello World in TurboCAD
Sub Main() Dim hDrawing As Long Dim hGraphic As Long Dim Result As Long Dim e As String 'Must have a drawing active hDrawing = TCWDrawingActive() If (hDrawing = 0) Then TCWLastErrorGet(e) MsgBox e Stop End If 'Create a graphic that has the text "hello world" 'TCWText takes 6 parameters: X, Y, Z, string, font size, and 'angle to print text hGraphic = TCWText(2#, 2#, 0#, "Hello World!", .5, 0#) 'hGraphic should how have a handle to our text graphic If (hGraphic = 0) Then TCWLastErrorGet(e) MsgBox e Stop End If End Sub
Save the file as hworld.bas (text format). Then launch TurboCAD v4, select Menu:Tools|Run Scripts... and select hworld.bas.
Now we've written our first sample program and run it in TurboCAD v4. Let's look at the parts of our script and explain some of the basics about programming in TurboCAD v4.
Enable Basic includes built-in functions as well (e.g. MsgBox, Cos, Strcomp). You can also call Windows API functions from your Basic script. Just add a Declare statement for the function call.
Cypress Enable Basic does not verify that you have passed the correct number of parameters or the correct values for the parameters when calling TCADAPI or any other DLL. It is the programmer's responsibility to ensure that functions are called correctly.
In our ``Hello World'' example, we use the currently active drawing:
Hello World in TurboCAD Sub Main()Dim hDrawing As Long Dim Result As Long Dim e As String 'Must have a drawing active hDrawing = TCWDrawingActive() If (hDrawing = 0) Then TCWLastErrorGet(e) MsgBox e Stop End If
TCWDrawingActive will return the handle of the active drawing. If no drawing is active (all drawings are closed), then hDrawing will be NULL. Here we have used the API TCWLastErrorGet to retrieve the error string and display our error.
TCADAPI provides another method of creating graphics: TCWGraphicCreate will create a graphic but will not add the graphic to the drawing. You must do this yourself. This function gives you more control over how you construct graphics. TCWGraphicCreate will be discussed in a later chapter of the manual.
Our ``hello world'' script example will create a text graphic with our ``Hello World!'' string. Our graphic will be added to the active drawing automatically. If TurboCAD couldn't make the graphic (e.g. no memory), TCWText will return a NULL handle for our graphic. In this case, we call TCWLastErrorGet to see the error result.
'Create a graphic that has the text "hello world" 'TCWText takes 6 parameters: X, Y, Z, string, font size, and 'angle to print text in radians hGraphic = TCWText(2#, 2#, 0#, "Hello World!", .5, 0#) 'hGraphic should how have a handle to our text graphic If (hGraphic = 0) Then TCWLastErrorGet(e) MsgBox e Stop End If
TCWAppPropertyGet, TCWAppPropertySet
TCWDrawingPropertyGet, TCWDrawingPropertySet
TCWGraphicPropertyGet, TCWGraphicPropertySet
TCWLayerPropertyGet, TCWLayerPropertySet
You must call these functions with function calling syntax:
result = TCWGraphicPropertySet(g, ``PenColor'', &HFFFFFF)
and not as a subroutine. Enable Basic will report an error if you call these functions as subroutines. See the section on Writing TurboCAD v4 Scripts for the difference between calling subroutines and functions.
There are several fundamental differences between a subroutine and a function:
Initialize "Survey Data"
While calling a function that takes two parameters and returns a result looks like this:
result = atan2(dx, dy)
You must use parentheses around the arguments being passed to a function.
TCWDrawingCount, TCWDrawingAt, TCWDrawingName
'Program to loop through open drawings and add drawing name Dim x As LongDim y As Long Dim angle As Double Sub Main() Dim dCount as Long Dim hDrawing as Long Dim i As Long Dim dName as Long 'Get count of number of drawings open dCount = TCWDrawingCount() If (dCount = 0) Then MsgBox "No drawings open" Stop End If 'Loop through open drawings For i = 0 to dCount -1 'activate drawing "i" hDrawing = TCWDrawingAt(i) 'Get drawing name TCWDrawingName dName 'Prompt for location and angle of text MyDialog 'Calculate angle in radians for text angle = angle * 3.14159265359 angle = angle / 180 'Write the name on the drawing TCWText x, y, 0.0, dName, .2, angle Next i End Sub Sub MyDialog() Begin Dialog MyUI 60, 60, 240, 105, "Add Drawing Name" Text 10, 10, 150, 10, "X Coordinate for name:" TextBox 120, 10, 110, 10, .x Text 10, 20, 150, 10, "Y Coordinate for name:" TextBox 120, 20, 110, 10, .y Text 10, 30, 150, 10, "Angle to print text (in degrees):" TextBox 120, 30, 110, 10, .angle OKbutton 80, 50, 40, 12 CancelButton 120, 50, 40, 12 End Dialog Dim Dlg1 As MyUI Dlg1.x = 0.0 Dlg1.y = 0.0 Dlg1.angle = 90.0 button = Dialog(Dlg1) if button = 0 then END elseif button = -1 then x = Dlg1.x y = Dlg1.y angle = Dlg1.angle end if End Sub
You can also use Automation to read from Microsoft Excel spreadsheets or Word documents. All this and more can be found in the examples and references sections in this manual.
TCWCircleCenterAndPoint, TCWLineRectangle, TCWGraphicPropertySet
Here's the subroutine of padwiz.bas:
Sub MakeObject(ByVal x As Double, ByVal y As Double) Dim gP As Long Dim g1 As Long Dim g2 As Long Dim r As Double r = PadSize / 2# If PadShape = 0 Then g1 = TCWCircleCenterAndPoint(x, y, 0#, x - 2 * r, y, 0#) Else ' Create the empty rectangle graphic g1 = TCWLineRectangle(x - r, y - r, 0#, x + r, y + r, 0#) End If ' Color is set as R, G, B - this is black Result = TCWGraphicPropertySet(g1, "PenColor", &H0) ' Fill Pattern is a style. We know that style 1 is always solid Result = TCWGraphicPropertySet(g1, "BrushStyle", BrushSolid) ' Add the black background of the pad to the pad group ' Make the hole 1/3 of the size of the pad unless it is smaller ' then a minimum, in which case it is set to that minimum r = PadSize / 6# If r > 0.0625 Then r = 0.0625 End If If PadShape = 0 Then ' Create the empty arc graphic g2 = TCWCircleCenterAndPoint(x, y, 0#, x - 2 * r, y, 0#) Else ' Create the empty rectangle graphic g2 = TCWLineRectangle(x - r, y - r, 0#, x + r, y + r, 0#) End If ' Color is set as R, G, B - this is white Result = TCWGraphicPropertySet(g2, "PenColor", &HFFFFFF) ' Fill Pattern is a style. We know that style 1 is always solid Result = TCWGraphicPropertySet(g2, "BrushStyle", BrushSolid) End Sub
TCWDrawingOpen, TCWLayersCount, TCWLayersAt, TCWLayerPropertyGetHere's the program:
'Program to get the id and name of each layer in the drawing
Sub Main() Dim dActive As Long Dim hDrawing As Long Dim count As Long Dim i As Long Dim LayerID As Long Dim LayVar As String Dim Result As Variant hDrawing = TCWDrawingOpen("c:\imsi\tcw40\Samples\mouse.tcw") count = TCWLayersCount() i = 1 LayVar = "Name" Do While (i <> count) LayerID = TCWLayersAt(i) Msgbox LayerID Result = TCWLayerPropertyGet(LayerID, LayVar) MsgBox Result i = i + 1 Loop MsgBox "Finished" End Sub
sub main() Title$ = "TCAPI Calculator" Prompt$ = "Enter a valid Enable Basic numeric expression. (e.g. " & Chr(34) & "sqr(47) / 2" & Chr(34) Default$ = "" E$ = InputBox$(Prompt$, Title$, Default$) If E$ <> "" Then TCWBasicRun "A# = " & E$ & Chr(10) & "MsgBox A#" End If end sub
The expression you type into the input box will be encapsulated into a new basic program, compiled and then executed. Execution by the calling script will proceed when TCWBasicRun returns.
You can also specify the name of another script as the parameter to TCWBasicRun. Now you can put commonly used subroutines and functions into files, and call them from your script, instead of copying and pasting the procedures into each of your scripts.
TCWBasicDebug just like TCWBasicRun except that it will start up the Enable Debugger so that you can step through the script.
TCWDrawingActive, TCWSelectionCount, TCWSelectionAt, TCWOpenOutput, TCW-
WriteOutput, TCWCloseOutput, TCWGraphicPropertyGet, TCWVertexCount,
TCWVertexAt, TCWGetX, TCWGetY, TCWGetZ
Global Const GK_GRAPHIC = 11 Global Const NULL = 0 Sub Main () Dim FileName As String Dim myLine As String Dim g As Long Dim v As Long Dim vi As Long Dim vCount As Long Dim gCount As Long Dim i As Long Dim fh As Long Dim dActive As Long ' Check for valid drawing dActive = TCWDrawingActive () If dActive = NULL Then MsgBox "Program requires active drawing" ' Terminate the program Stop End If ' Get the name of the output file. FileName = InputBox("Type in the filename to export to") If FileName <> "" Then gCount = TCWSelectionCount() If (gCount = 0) Then MsgBox "Need to have at least one graphic selected" Stop End If ' Open the output text file. fh = TCWOpenOutput(FileName) ' Walk through the selected graphics and pick only ' GK_GRAPHICS. for i = 0 to gCount - 1 g = TCWSelectionAt(i) If TCWGraphicPropertyGet(g, "Kind") = GK_GRAPHIC Then If vi > 0 Then ' Place a blank line after the previous graphic TCWWriteOutput fh, "" End If vCount = TCWVertexCount(g) ' Iterate through the vertices of the graphic g. for vi = 0 to vCount - 1 v = TCWVertexAt(g, vi) ' Write the coordinates of vertex v into the string Line. ' The delimiter for numeric fields is chr(9) character. myLine = Str$(vi) & chr$(9) & Str$(TCWGetX(v)) & chr$(9) & _ Str$(TCWGetY(v)) & chr$(9) & Str$(TCWGetZ(v)) TCWWriteOutput fh, myLine next vi End If next i TCWCloseOutput fh End If End Sub
TCWDrawingActive, TCWOpenInput, TCWReadInput, TCWCloseInput,
TCWGraphicCreate, TCWGraphicAppend, TCWGraphicXYZAdd, TCWGraphicDraw
' This sample program is an example of how to do custom file IO from ' TurboCAD. We will build graphics from the vertices in the table. 'Constants Global Const GK_GRAPHIC = 11 Global Const NULL = 0 ' File I/O constants Global Const EOFILE = -1 Sub Main () Dim FileName As String Dim LineBuffer As String Dim g As Long Dim v As Long Dim vi As Long Dim fh As Long Dim dActive As Long Dim x As Double Dim y As Double Dim z As Double Dim Part As String Dim PartX As String Dim PartY As String Dim PartZ As String Dim Delim As String Dim Pos As Integer ' Check for valid drawing dActive = TCWDrawingActive () If dActive = NULL Then MsgBox "Program requires active drawing." ' Terminate the program Stop End If vi = 0 g = NULL ' Delimiter for record fields in the input text file (tab) Delim = Chr$(9) ' Get the name of the input file FileName = InputBox("Type in the filename to import from") If (FileName <> "") Then ' Open input text file. fh = TCWOpenInput(FileName) ' Read lines from the input file and break them down ' to numeric values vi = 0 while (TCWReadInput(fh, LineBuffer) <> EOFILE) ' Graphic separator if LineBuffer = "" Then if ((g <> NULL) And (vi > 0)) Then TCWGraphicAppend NULL, g TCWGraphicDraw g, 0 g = NULL End If vi = 0 End If if (LineBuffer <> "") Then ' find the first delimiters position in Line Pos = InStr(1, LineBuffer, Delim, 0) ' Let's remove the index part Part = Right$(LineBuffer, Len(LineBuffer) - Pos) ' Let's find position of the second delimiter Pos = InStr(1, Part, Delim, 0) ' Let's extract the first number PartX = Left$(Part, Pos-1) x = Val(PartX) Part = Right$(Part, Len(Part) - Pos) ' Let's find the position of the third delimiter Pos = InStr(1, Part, Delim, 0) PartY = Left$(Part, Pos-1) y = Val(PartY) PartZ = Right$(Part, Len(Part) - Pos) z = Val(PartZ) ' Add vertex (x, y, z) to the graphic g If vi = 0 Then g = TCWGraphicCreate(GK_GRAPHIC, "") End If If g <> NULL Then TCWGraphicXYZAdd g, x, y, z End If vi = vi + 1 End If wend ' If anything is left out we need to add to the drawing ' now. if ((g <> NULL) And (vi > 0)) Then TCWGraphicAppend NULL, g End If TCWCloseInput fh End If End Sub
Sub OpenOrgSheet() Dim xlFile As String Dim shtNum As Integer CurrentRow = 1 CurrentCol = 1 'CreateObject will create an instance of an Excel object Set xlApp = CreateObject("Excel.Application") 'Open our Excel Spreadsheet file Set xlWbk = xlApp.Workbooks.Open("Org Chart Data.XLS") 'Access our worksheet Set xlSht = xlWbk.Worksheets("Employee Database") End Sub Function GetNextOrgSheetValue() As Variant Dim RtnVal As String If FileLoaded <> 0 Then 'Get the data in our cell RtnVal = xlSht.Cells(CurrentRow, CurrentCol).Value CurrentCol = CurrentCol + 1 'If the data returned is Null, then go to next row If RtnVal = "" Then CurrentCol = 1 CurrentRow = CurrentRow + 1 End If GetNextOrgSheetValue = RtnVal Else GetNextOrgSheetValue = Null End If End Function
TCWDrawingActive, TCWSelectionCount, TCWSelectionAt, TCWGraphicPropertyGet, TCWGraphicPropertySet, TCWVertexAt, TCWDeselectAll, TCWGetX, TCWGetY, TCWUndoRecordStart, TCWUndoRecordEnd, TCWText
'Sample that shows how to draw text along arcs ' Misc Global Const NULL = 0 GLobal Const GK_ARC = 2 sub Main Dim t As Long Dim gCount As Long Dim ga As Long Dim vCount As Long Dim vc As Long Dim vs As Long Dim ve As Long Dim strText As String dim g as Long dim i as integer dim x as double dim y as double dim angle as double dim angle2 as double dim r as double dim s as double dim pi as double dim l as long dim a as double dim c as string dim hActive as long dim gText As Long dim res As Long 'Get drawing handle hActive = TCWDrawingActive() if (hActive = NULL) then MsgBox "Need active drawing." 'Terminate Program Stop end if 'Get selection count to see that we have 1 graphic selected gCount = TCWSelectionCount if (gCount = NULL) or (gCount <> 1) then MsgBox "Program requires an arc (not circle) to be selected." 'Terminate the program Stop end if 'Get graphic handle for the selection ga = TCWSelectionAt(0) if (ga = NULL) then MsgBox "Program requires an arc (not circle) to be selected." ' Terminate the program Stop end if 'Make sure we have an arc and not a circle if ((TCWGraphicPropertyGet(ga, "Kind") <> GK_ARC) or TCWGraphicPropertyGet(ga, "Closed")) then MsgBox "Program requires an arc (not circle) to be selected." ' Terminate the program Stop End If vc = TCWVertexAt(ga,1) ' center of arc vs = TCWVertexAt(ga,2) ' start point of arc ve = TCWVertexAt(ga,3) ' end point of arc 'Deselect the arc TCWDeselectAll 'Text to put around the arc strText = "He who goes round in circles shall be known as a big wheel!" 'Calculate the value of pi pi = atn(1)*4 'Calculate the start angle angle = arctan((TCWGetY(vs)-TCWGetY(vc)),(TCWGetX(vs)-TCWGetX(vc))) 'Calculate the end angle angle2 = arctan((TCWGetY(ve)-TCWGetY(vc)),(TCWGetX(ve)-TCWGetX(vc))) while (angle > angle2) angle2 = angle2 + pi*2 wend 'Calculate the radius of the arc r = sqr((TCWGetY(ve)-TCWGetY(vc))*(TCWGetY(ve)-TCWGetY(vc)) + (TCWGetX(ve)-TCWGetX(vc))*(TCWGetX(ve)-TCWGetX(vc))) ' text character width = chord length / number of chars in string s = ((angle2-angle) * r) / len(strText) 'Length of string l = len(strText) 'Setup Undo Record for this copy, we don't need to add the text graphics to 'the undo record because TCADAPI will do that for us TCWUndoRecordStart hActive, "Radical Text Copy" 'put the characters around the arc for i = 0 to l - 1 a = angle + ((angle2 - angle)*i)/l x = TCWGetX(vc) + r * cos(a) y = TCWGetY(vc) + r * sin(a) c = mid(strText, l-i, 1) gText = TCWText(x, y, 0.0, c, s, (a - (pi/2))) res = TCWGraphicPropertySet(gText, "TextFont", "Arial") next i ' End undo record TCWUndoRecordEnd hActive End Sub ' Four quadrant ArcTan function written by a mathematically impaired programmer who did not want to ' leave anything to chance. (It will take dx and dy and deliver an angle between 0 and 2pi). function arctan(ByVal dy As double, ByVal dx As Double) As Double Dim pi as Double Dim a as double pi = atn(1)*4 if (abs(dx) < 0.0001) then if (dy > 0) then a = pi/2 else a = 3*pi/2 end if a = abs(atn(dy/dx)) if (dx < 0) then if (dy < 0) then ' 3rd quad a = pi+a else ' 2nd quad a = pi-a end if else if (dy < 0) then ' 4th quad a = 2*pi-a else ' 1st quad end if end if end if arctan = a end function
TCWDrawingActive, TCWVertexCreate, TCWGetPoint, TCWVertexDispose, TCWSelectionCount, TCWGetX, TCWGetY, TCWGetZ, TCWGraphicCount, TCWSelectionAt, TCWGraphicCopy, TCWGraphicAppend, TCWDeSelectAll, TCWGraphicAt, TCWGraphicPropertySet, TCWSelectionMove
'Sample that shows how to do a linear copy of selected graphics ' Misc Global Const NULL = 0 dim v1 as long dim v2 as long dim copies as long dim hActive as long sub Main 'Get drawing handle hActive = TCWDrawingActive() if (hActive = NULL) then MsgBox "Need active drawing." 'Terminate Program Stop end if 'Get number of copies from the user copies = Val(InputBox$("Input number of copies to make")) 'create a vertex v1 = TCWVertexCreate(0.0, 0.0, 0.0) if (v1 = NULL) then MsgBox "Cannot create vertex" Stop end if v2 = TCWVertexCreate(0.0, 0.0, 0.0) if (V2 = NULL) then MsgBox "Cannot create vertex" Stop end if 'click on screen to get points result = TCWGetPoint(v1,"Get first point", NULL, NULL, 0, 1) result = TCWGetPoint(v2,"Get second point", NULL, NULL, 0, 1) If copies = 0 Then MsgBox "No copies desired, finished!" Stop end if 'Go and copy away DoCopy 'Need to delete the two vertex objects that we created above TCWVertexDispose v1 TCWVertexDispose v2 End Sub Sub DoCopy () Dim gCount As Long Dim sCount As Long Dim ga As Long dim g as Long dim i as integer dim j as integer dim result as long dim dx as double dim dy as double dim dz as double 'Get selection count to see that we have something selected sCount = TCWSelectionCount if (sCount = NULL) then MsgBox "Program requires at least one graphic to be selected." 'Terminate the program Stop end if 'Calculate the delta between the points for the copy dx = (TCWGetX(v2) - TCWGetX(v1)) dy = (TCWGetY(v2) - TCWGetY(v1)) dz = (TCWGetZ(v2) - TCWGetZ(v1)) for i = 1 to copies 'Get total graphics in drawing gCount = TCWGraphicCount(hActive) 'loop through selected graphics making copies for j = 0 to sCount-1 ga = TCWSelectionAt(j) if (ga = NULL) then MsgBox "Lost Selection?" Stop end if 'make copy of selected graphic g = TCWGraphicCopy(ga) 'add copy to the drawing result = TCWGraphicAppend(NULL, g) next j 'Deselect the original graphics TCWDeSelectAll 'Select the newly added graphics that we just copied 'they will be at gCount+1... for j = 0 to sCount-1 ga = TCWGraphicAt(hActive, gCount+j) if (ga = NULL) then MsgBox "Cannot find new copied graphic" stop end if 'select the graphic result = TCWGraphicPropertySet(ga, "Selected", 1) next j 'move the selection on the vector TCWSelectionMove dx, dy, dz 'Select the newly added graphics that we just copied again, 'TCWSelectionMove loses the selection state for j = 0 to sCount-1 ga = TCWGraphicAt(hActive, gCount+j) if (ga = NULL) then MsgBox "Lost selection" stop end if 'set selected result = TCWGraphicPropertySet(ga, "Selected", 1) next j next i End Sub
[Script_Table]
rad_copy = c:\imsi\tcw40\Scripts\radcopy.bas
Obviously the script names will vary according to your requirements. The ``_'' in the name will be translated into a `` `` (Spaces are not allowed left of the ``='' in the INI file). TurboCAD will always load the scripts in the INI file first.
You can also attach scripts to a specific drawing or template. You attach scripts to a drawing or template through the Menu:Options|Scripts property page.
You can use the debug source window to create scripts and then save them to a file. Find a mistake while debugging? Make changes to your script, recompile and continue testing. Save your changes along the way.
Features include single step(into or over), break points and go to execute your program. You can add your variables to the watch window and see their values as you step through the program.