Call Lisp from Modeless Dialog or Help Converting LiSP Functions

Call Lisp from Modeless Dialog or Help Converting LiSP Functions

David_Prontnicki
Collaborator Collaborator
422 Views
2 Replies
Message 1 of 3

Call Lisp from Modeless Dialog or Help Converting LiSP Functions

David_Prontnicki
Collaborator
Collaborator

OK, So I have routine that runs a bunch of stuff on a drawing file. I am doing 95% of the work via the API. Due to the restrictions of the Burst command I am forced to do 5% via lisp. The problem I have is the Lisp does not fire until after the dialog is closed. But it needs to run in the middle of other things. Meaning I need this part (the Lisp) to run before the rest of the routine or I do not get the desired results. 

 

The Lisp is Here:

 

(defun C:LSPMCTELTRANS()

    (vl-load-com)

    ;;; This section will make all blocks explode-able!
    (vlax-for b (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object)))

	    (or 

		    (wcmatch (vla-get-Name b) "`**_Space*")
		    (vla-put-explodable b :vlax-true)

	    )

    ) ;end vlax-for

    ;;; This section will switch to each layout and burst all blocks
    (foreach layout (layoutlist)

	    (setvar "ctab" layout)

		    (setq burstrc 0)

			    (while

				    (and

					    (setq compare1 (ssget "_X" (list '(0 . "INSERT") (cons 410 (getvar 'ctab)))))
					    (<= burstrc 5)

				    )

					    (sssetfirst nil compare1)
					    (c:burst)

				    (if

					    (setq compare2 (ssget "_X" (list '(0 . "INSERT") (cons 410 (getvar 'ctab)))))

						    (if (= (sslength compare1) (sslength compare2))

							    (setq burstrc (+ burstrc 1))
							    (setq burstrc 0)

						    )

				    )

		        ) ;end while

    (princ)

    (command "zoom" "e")

    (command "regenall")

    ) ; end for each

    (princ)

    ;;; This section will set the first layout tab active!
    (vlax-for layt

	    (vla-get-layouts (vla-get-ActiveDocument (vlax-get-acad-object)))

		    (if (= (vla-get-TabOrder layt) 1)

			    (setvar 'CTAB (vla-get-Name layt))

		    )

    ) ;end vlax-for

) ;end defun LSPMCTELTRANS

 

It basically goes to each tab and bursts all blocks. Because it literally switches tabs the form must be modeless. I tried as Modal with no luck.

 

I have tried calling it many different ways as shown on the forums. From Send string to execute to loading it first then calling the command but I just cant get it to work. 

 

curDoc.SendStringToExecute("(load ""M:\\Utilities\\LISP Routines\\Modify Routines\\Drawing Prep\\MCTELTRANSLSP.lsp"") ", False, False, False)

'I have tried loading that on form load. then calling this when needed but with no luck. Neither worked.

curDoc.SendStringToExecute("LSPMCTELTRANS" + " ", True, False, False)

docEd.Command("LSPMCTELTRANS ")

 

I have used a different way in the past. With some help from @_gile but the problem with the below code is it is recursive and the drawing size increases from 9MG to 44MG. (There are other functions and subs that go with this)

 

And the other thing with the below code is that in VS2019 ent.OpenAs throws an error. Not a member of ObjectId

 

Public Sub BurstAllBlocks() Implements IExplodeServices.BurstAllBlocks

        Dim curDb As Database = Active.Database

        Try

            Using tr As Transaction = curDb.TransactionManager.StartTransaction()

                Dim layoutDbDictionary As DBDictionary = tr.GetObject(curDb.LayoutDictionaryId, OpenMode.ForRead)

                For Each layoutDbDictionaryEntry As DBDictionaryEntry In layoutDbDictionary

                    Dim layout As Layout = CType(layoutDbDictionaryEntry.Value.GetObject(OpenMode.ForRead), Layout)
                    Dim blkTblRec As BlockTableRecord = tr.GetObject(layout.BlockTableRecordId, OpenMode.ForWrite)

                    Dim rxClass = RXObject.GetClass(GetType(BlockReference))
                    Dim blocks = blkTblRec.Cast(Of ObjectId).Where(Function(ent) ent.ObjectClass.IsDerivedFrom(rxClass)) _
                        .Select(Function(ent) ent.OpenAs(Of BlockReference)(tr, OpenMode.ForRead))

                    For Each block As BlockReference In blocks

                        BurstBlocks(tr, block, blkTblRec)

                    Next

                Next

                tr.Commit()

            End Using

        Catch ex As Exception

End Try

 

I am not particular in the answer what ever will work I am fine with. Any help would be greatly appreciated. 

0 Likes
423 Views
2 Replies
Replies (2)
Message 2 of 3

_gile
Consultant
Consultant

Hi,

 

You can try the Application.Invoke() method which works synchronously.

But, IMHO, calling LISP from .NET rapidly becomes more difficult than converting the LISP routines to .NET.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 3

David_Prontnicki
Collaborator
Collaborator

Hi,

 

Thank you for the help but I am running into a problem. When I use the Application.Invoke method I receive an error:

AutoCAD command rejected: nil

 

I can see it start to work as I know the section make all blocks explode-able works and it switches to the first tab in the drawing. I BELIEVE it is when it gets to the (c:burst) is were it is erroring as when the .net command finalizes all the blocks on that tab are selected. I can run the lisp on its own with no problems. 

 

 

    Public Sub test() Implements IExplodeServices.test

        'Dim args As ResultBuffer = New ResultBuffer(New TypedValue(CInt(LispDataType.Text), "LSPMCTELTRANS"))
        'Dim result As ResultBuffer = Application.Invoke(args)
        'Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
        'ed.WriteMessage(result.ToString())

        Application.Invoke(New ResultBuffer(New TypedValue(CInt(LispDataType.Text), "C:LSPMCTELTRANS")))

    End Sub

 

 

I apsolutly agree with you on the point of trying to convert to .net. I would and have for this but as I stated I run into the problem were for what ever reason the drawing size increases a ridiculous amount. I BELIEVE my only option is to get this LiSP to run mid way through.  

 

Here is were I am calling it from (on the actual form, as modal):

 

Try

            Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("CMDECHO", 0)
            Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("OSMODE", 0)
            Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("NOMUTT", 1)

            Using lockDocument As DocumentLock = curDoc.LockDocument()

                '-------------------------------------------------------------

                FormUpdate("Unlocking Layers...", 0)

                _layerServices.UnlockLayers()

                FormUpdate("Unlocking Layers... Completed", 7)

                '-------------------------------------------------------------

                FormUpdate("Detaching Unresolved Xref's...", 7)

                _xrefServices.DetachBrokenXrefs()

                FormUpdate("Detaching Unresolved Xref's... Completed", 14)

                '-------------------------------------------------------------

                FormUpdate("Binding Resolved Xref's, This may take some time...", 14)

                If _xrefServices.BindResolvedXrefs() = False Then

                    FormUpdate("Starting Undo Process...", 14)

                    FormUpdate("Undoing Process, Please Wait...", 7)

                    _saveServices.UndoMcdtpi()

                    FormUpdate("Undo Process... Completed", 0)

                    ResetSystemVariables()

                    Me.Close()

                    Exit Sub

                End If

                FormUpdate("Binding Resolved Xref's... Completed", 21)

                '-------------------------------------------------------------

                FormUpdate("Detaching ALL Images... ", 21)

                _imageServices.DetachAllImages()

                FormUpdate("Detaching ALL Images... Completed", 28)

                '------------------------------------------------------------

                FormUpdate("Bursting All Blocks, This may take some time...", 28)

                'curDoc.SendStringToExecute("LSPMCTELTRANS" + " ", True, False, False)

                'docEd.Command("LSPMCTELTRANS ")

                _explodeServices.test()

                '_explodeServices.BurstAllBlocks()

                FormUpdate("Bursting All Blocks... Completed", 35)

                '-------------------------------------------------------------

                FormUpdate("Deleting All Data Links...", 42)

                _dataLinkServices.DetachDataLinks()

                FormUpdate("Deleting All Data Links... Completed", 49)

                '-------------------------------------------------------------

'there are a few more things to run after this as well.

            End Using

            Me.Close()

            ResetSystemVariables()

        Catch ex As Exception

            ResetSystemVariables()

        End Try

 

 

0 Likes